Is there a way to get Lithophane effect using three.js
.
Currently i have tried different materials with transparency and opacity but have not succeeded.
<html lang="en">
<head>
<title>Lith (Three.js)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<script src="js/three.min.js"></script>
<script src="./js/dat.gui.min.js"></script>
<script src="./js/STLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/SkyShader.js"></script>
<script src="js/THREEx.WindowResize.js"></script>
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<script>
var container, scene, camera, renderer, controls, stats;
var clock = new THREE.Clock();
var cube;
init();
animate();
function init()
{
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.setClearColor( 0x999999 );
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
controls = new THREE.OrbitControls( camera, renderer.domElement );
// SKYBOX/FOG
var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
// scene.add(skyBox);
scene.fog = new THREE.FogExp2( 0x9999ff, 0.00025 );
////////////
// CUSTOM //
////////////
// must enable shadows on the renderer
renderer.shadowMapEnabled = true;
// "shadow cameras" show the light source and direction
// spotlight #1 -- yellow, dark shadow
var spotlight = new THREE.SpotLight(0xffff00);
spotlight.position.set(0,150,-50);
spotlight.shadowCameraVisible = true;
spotlight.shadowDarkness = 0.8;
spotlight.intensity = 2;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
scene.add(spotlight);
var sphereSize = 10;
var pointLightHelper = new THREE.SpotLightHelper( spotlight, sphereSize );
scene.add( pointLightHelper );
var light = new THREE.SpotLight(0x999999);
light.intensity = 0.6;
camera.add(light);
var loader = new THREE.STLLoader();
loader.load('./TestOriginal.stl', function(object) {
meshObject = object;
var color = new THREE.Color( 0xffffff );
var material = new THREE.MeshPhongMaterial({
color: color,//'white',
side: THREE.DoubleSide,
//shading: THREE.SmoothShading,
opacity: 0.6,
transparent: true
});
this.mesh = new THREE.Mesh(object, material);
mesh.position.set(0,0,0);
scene.add(mesh);
mesh.position.set(0,0,0);
var newScale = 1;
mesh.geometry.computeBoundingBox();
boundingBox = mesh.geometry.boundingBox;
mesh.translateX(-((boundingBox.max.x + boundingBox.min.x) * newScale) / 2);
mesh.translateY(-((boundingBox.max.y + boundingBox.min.y) * newScale) / 2);
mesh.translateZ(-((boundingBox.max.z + boundingBox.min.z) * newScale) / 2);
});
// floor: mesh to receive shadows
var floorTexture = new THREE.ImageUtils.loadTexture( './checkerboard.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
// Note the change to Lambert material.
var floorMaterial = new THREE.MeshLambertMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 100, 100);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -80.5;
floor.rotation.x = Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
}
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
controls.update();
}
function render()
{
renderer.render( scene, camera );
}
</script>
</body>
</html>
And my output is like:
I have also tried shader material and it gives me something like:
What i want is: there should be a light from backside of object and the engrave part of object should glow (with respect to depth of object).
This is by no means an answer, but I really think the best approach to this would be writing (or finding) a custom shader. I will preface this by saying that writing shaders is NOT child's play: it can become incredibly complex, due to shader programming languages being relatively low level and relying heavily on a knowledge of esoteric geometry / mathematics.
After some snooping, it looks like you'd need a shader that achieves something called Sub-Surface Scattering (known colloquially as SSS) - this is essentially the behavior of light through a translucent object, based on its thickness (and some other properties which I won't delve into):
To achieve a Lithophane effect, you'd need to generate a "thickness map" of sorts that maps to your object's mesh, and then the custom shader would scatter light correctly through this map to produce an effect similar to what you desire.
I learnt all of this from going through a principally simple presentation performed by the Lead Rendering Programmer at DICE games. Here's an example slide from the presentation:
This shader produces an effect that resembles this, based on thickness, in real time:
If you're serious about achieving this effect, I'd seriously recommend doing some reading on Cg or GLSL shader programming. Personally I like Cg, because i was incentivised to learn it for it's compatibility with Unity3D. For this reason, I found a great resource for learning Cg, namely the wikibook on the subject. It's (somewhat) specific to Unity, but the principles will be sound.
Either way I wish you luck on the subject. Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With