Lithophane effect in three JS

Is there a way to get the lithophane effect using three.js

Sample image .

Currently, I have tried different materials with transparency and opacity, but failed.

<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 conclusion is similar:

output image

I also tried the shader stuff and it gives me something like: Shader output

What I want: there should be light from the back of the object, and the engraved part of the object should glow (relative to the depth of the object).

+5
source share
1 answer

This is by no means the answer, but I really think the best approach to this is to write (or find) a custom shader. I anticipate this by saying that writing shaders is NOT a children's game: it can become incredibly complex because shader programming languages ​​are relatively low and rely heavily on knowledge of esoteric geometry / mathematics.


After some tracking, it looks like you will need a shader that achieves something called Sub-Surface Scattering (known in the conversation as SSS) - this is essentially the behavior of light through a translucent object based on its thickness (and some other properties that I I will not delve into):

Sub Surface Scattering (SSS)

To achieve the lithophane effect, you need to create a “thickness map” that will be matched to your mesh of objects, and then the user shader will properly diffuse light through this map to create an effect similar to what you want.

I learned all this by going through a fundamentally simple presentation made by a leading Rendering programmer in DICE games. Here is an example slide from a presentation:

DICE Game introduces Shader SSS

This shader creates an effect similar to this, depending on the thickness, in real time:

enter image description here

If you are serious about achieving this effect, I seriously recommend doing some reading on Cg or GLSL shader programming. Personally, I like Cg because I was interested in learning about its compatibility with Unity3D. For this reason, I found an excellent resource for learning Cg, namely wikibook on this subject . It is (somewhat) characteristic of Oneness, but the principles will be sound.

In any case, I wish you the best of luck on this. Hope this helps!

+5
source

Source: https://habr.com/ru/post/1236126/


All Articles