2015-11-17 10 views
5

C'è un modo per ottenere l'effetto litofania utilizzando Three.jseffetto litofania in tre JS

Sample image.

Attualmente ho provato diversi materiali con trasparenza e opacità ma non ci sono riuscito.

<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> 

E la mia uscita è come:

output image

Ho anche provato materiale shader e mi dà qualcosa di simile: Shadder output

Quello che voglio è: ci dovrebbe essere un leggero dal retro dell'oggetto e la parte incisa dell'oggetto dovrebbe illuminare (rispetto alla profondità dell'oggetto).

+0

Questa è una domanda davvero interessante. Hai provato a cercare uno shader, magari scritto in GLSL o Cg, che produce l'effetto? Non sono sicuramente la persona da chiedere, ma potrebbe essere possibile scriverne una! Forse dargli una pugnalata/trovare qualcun altro (incompleto o meno), e poi fare una nuova domanda specifica a quel problema :) –

risposta

5

Questa non è affatto una risposta, ma penso davvero che l'approccio migliore sarebbe scrivere (o trovare) uno shader personalizzato. Premetterò questo concetto dicendo che scrivere shaders è NON gioco da ragazzi: può diventare incredibilmente complesso, poiché i linguaggi di programmazione degli shader sono relativamente di basso livello e fanno affidamento su una conoscenza di geometria/matematica esoteriche.


Dopo qualche snooping, sembra che avresti bisogno di uno shader che consente di ottenere qualcosa chiamato sub-surface scattering (colloquialmente nota come SSS) - questo è essenzialmente il comportamento della luce attraverso un oggetto trasparente, in base alla sua spessore (e alcune altre proprietà che non approfondiranno):

Sub Surface Scattering (SSS)

per ottenere un effetto litofania, avresti bisogno di generare una "mappa dello spessore" di sorta che le mappe di rete del vostro oggetto, e quindi lo shader personalizzato diffonderà la luce correttamente attraverso questa mappa per produrre un effetto simile a quello desideri.

Ho imparato tutto questo passando da uno strumento principale simple presentation eseguito dal Programmatore rendering di piombo ai giochi DICE. Ecco un esempio di diapositive dalla presentazione:

DICE Game's presentation of their SSS shader implementation

Questa Shader produce un effetto che assomiglia a questo, in base allo spessore, in tempo reale:

enter image description here

Se siete seriamente riguardo al raggiungimento di questo effetto, consiglierei seriamente di fare qualche lettura sulla programmazione degli shader Cg o GLSL. Personalmente mi piace Cg, perché sono stato incentivato ad apprenderlo per la sua compatibilità con Unity3D. Per questo motivo, ho trovato una grande risorsa per l'apprendimento di Cg, ovvero the wikibook on the subject. È (in qualche modo) specifico per Unity, ma i principi saranno validi.

In entrambi i casi vi auguro buona fortuna in materia. Spero che questo ti aiuti!