2017-10-21 15 views
2

J'ai un objet où les particules ouvertes aléatoires et d'autres sont solides. Comment puis-je placer un faux soleil à l'intérieur de l'objet et obtenir des rayons à travers les particules ouvertes en utilisant threejs. Lorsque l'objet tourne X, les rayons Y devraient traverser les particules ouvertes (POST PROCESSING)?comment obtenir des rayons du soleil à partir du milieu de l'objet en troisj

SAMPLE VIDEO

Mon objet code Three.js est ci-dessous

var camera, scene, renderer; 
var geometry, material, mesh; 

    init(); 
    animate(); 

function init() { 

    camera = new THREE.PerspectiveCamera(70, window.innerWidth/window.innerHeight, 10, 10000); 
    camera.position.z = 200; 

    scene = new THREE.Scene(); 

    hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6); 
    scene.add(hemiLight); 

    var geometry = new THREE.DodecahedronGeometry(80, 0); 

    var material = new THREE.MeshPhongMaterial({ 
    color: 0xffffff, 
    specular: 0xffffff, 
    shininess: 1, 
    shading: THREE.FlatShading, 
    polygonOffset: true, 
    polygonOffsetFactor: 1, 
    wireframe:true 

    }); 

    mesh = new THREE.Mesh(geometry, material); 

    scene.add(mesh); 

    var geo = new THREE.EdgesGeometry(mesh.geometry); // or WireframeGeometry 
    var mat = new THREE.LineBasicMaterial({ color: 0xffffff, linewidth: 2 }); 
    var wireframe = new THREE.LineSegments(geo, mat); 
    mesh.add(wireframe); 

    //outer frame end 

    //inner world like object start 

    var sphere_material = [ 
     new THREE.MeshLambertMaterial({ color: 0xffff00, side: THREE.DoubleSide }), 
     new THREE.MeshBasicMaterial({ transparent: true, opacity: 0 }) 
    ]; 

    var sphere_geometry = new THREE.OctahedronGeometry(60, 3); 
    // assign material to each face 
    for(var i = 0; i < sphere_geometry.faces.length; i++) { 
     sphere_geometry.faces[ i ].materialIndex = THREE.Math.randInt(0, 1); 
    } 

    sphere_geometry.sortFacesByMaterialIndex(); 

    var sphere_mesh = new THREE.Mesh(sphere_geometry, sphere_material); 
    sphere_mesh.position.set(0, 0, 0) 
    mesh.add(sphere_mesh); 


    renderer = new THREE.WebGLRenderer({ 
    antialias: true 
    }); 

    renderer.setSize(window.innerWidth, window.innerHeight); 
    document.body.appendChild(renderer.domElement); 

} 
renderer.gammaInput = true; 
renderer.gammaOutput = true; 

function animate() { 

    requestAnimationFrame(animate); 

    mesh.rotation.x += 0.003; 
    mesh.rotation.y += 0.003; 

    renderer.render(scene, camera); 

} 

DEMO

+0

Pourriez-vous, s'il vous plaît, expliquer ce qui est "particules ouvertes au hasard et d'autres"? Ou mieux, pour illustrer ce que c'est. Pour l'instant, votre question est très difficile à comprendre ce que vous voulez dans le résultat. Ou vous devez retravailler la question. – prisoner849

+0

@ prisoner849 merci pour le commentaire. j'ai mis mon code. – underscore

+0

ressemble à vous essayez de répéter [celui-ci] (https://www.youtube.com/watch?v=suqFV7VGsL4) – prisoner849

Répondre

2

Vous êtes à la recherche volumetric lights. Vérifiez cet exemple de code ci-dessous ou peut-être mieux le regarder sur jsfiddle (pour le voir en pleine dimension ne pas surchargé par le journal de la console).

Il est basé sur l'article this. J'ai légèrement modifié votre code et mis à jour les couleurs ainsi que certaines valeurs et le code. Il a encore besoin de jouer (par exemple, le nombre de visages, la couleur de la lumière, les propriétés des shaders, etc.) mais, espérons-le, cela vous aidera. Tout dépend vraiment de la façon dont vous souhaitez le faire ressembler.

THREE.VolumetericLightShader = { 
 
    uniforms: { 
 
    tDiffuse: {value:null}, 
 
    lightPosition: {value: new THREE.Vector2(0.5, 0.5)}, 
 
    exposure: {value: 0.18}, 
 
    decay: {value: 0.95}, 
 
    density: {value: 0.8}, 
 
    weight: {value: 0.4}, 
 
    samples: {value: 50} 
 
    }, 
 

 
    vertexShader: [ 
 
    "varying vec2 vUv;", 
 
    "void main() {", 
 
     "vUv = uv;", 
 
     "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);", 
 
    "}" 
 
    ].join("\n"), 
 

 
    fragmentShader: [ 
 
    "varying vec2 vUv;", 
 
    "uniform sampler2D tDiffuse;", 
 
    "uniform vec2 lightPosition;", 
 
    "uniform float exposure;", 
 
    "uniform float decay;", 
 
    "uniform float density;", 
 
    "uniform float weight;", 
 
    "uniform int samples;", 
 
    "const int MAX_SAMPLES = 100;", 
 
    "void main()", 
 
    "{", 
 
     "vec2 texCoord = vUv;", 
 
     "vec2 deltaTextCoord = texCoord - lightPosition;", 
 
     "deltaTextCoord *= 1.0/float(samples) * density;", 
 
     "vec4 color = texture2D(tDiffuse, texCoord);", 
 
     "float illuminationDecay = 1.0;", 
 
     "for(int i=0; i < MAX_SAMPLES; i++)", 
 
     "{", 
 
     "if(i == samples){", 
 
      "break;", 
 
     "}", 
 
     "texCoord -= deltaTextCoord;", 
 
     "vec4 sample = texture2D(tDiffuse, texCoord);", 
 
     "sample *= illuminationDecay * weight;", 
 
     "color += sample;", 
 
     "illuminationDecay *= decay;", 
 
     "}", 
 
     "gl_FragColor = color * exposure;", 
 
    "}" 
 
    ].join("\n") 
 
}; 
 

 
THREE.AdditiveBlendingShader = { 
 
    uniforms: { 
 
    tDiffuse: { value:null }, 
 
    tAdd: { value:null } 
 
    }, 
 

 
    vertexShader: [ 
 
    "varying vec2 vUv;", 
 
    "void main() {", 
 
     "vUv = uv;", 
 
     "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);", 
 
    "}" 
 
    ].join("\n"), 
 

 
    fragmentShader: [ 
 
    "uniform sampler2D tDiffuse;", 
 
    "uniform sampler2D tAdd;", 
 
    "varying vec2 vUv;", 
 
    "void main() {", 
 
     "vec4 color = texture2D(tDiffuse, vUv);", 
 
     "vec4 add = texture2D(tAdd, vUv);", 
 
     "gl_FragColor = color + add;", 
 
    "}" 
 
    ].join("\n") 
 
}; 
 

 
THREE.PassThroughShader = { 
 
\t uniforms: { 
 
\t \t tDiffuse: { value: null } 
 
\t }, 
 

 
\t vertexShader: [ 
 
\t \t "varying vec2 vUv;", 
 
    "void main() {", 
 
\t \t "vUv = uv;", 
 
\t \t \t "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);", 
 
\t \t "}" 
 
\t ].join("\n"), 
 

 
\t fragmentShader: [ 
 
    "uniform sampler2D tDiffuse;", 
 
    "varying vec2 vUv;", 
 
    "void main() {", 
 
\t \t \t "gl_FragColor = texture2D(tDiffuse, vec2(vUv.x, vUv.y));", 
 
\t \t "}" 
 
\t ].join("\n") 
 
}; 
 

 
(function(){ 
 
    var scene, camera, renderer, composer, box, pointLight, 
 
     occlusionComposer, occlusionRenderTarget, occlusionBox, lightSphere, 
 
     volumetericLightShaderUniforms, 
 
     DEFAULT_LAYER = 0, 
 
     OCCLUSION_LAYER = 1, 
 
     renderScale = 0.5, 
 
     angle = 0, 
 
     sphere_mesh, 
 
     mesh; 
 
    
 
    scene = new THREE.Scene(); 
 
    camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 
 
    renderer = new THREE.WebGLRenderer(); 
 
    renderer.setPixelRatio(window.devicePixelRatio); 
 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 
    document.body.appendChild(renderer.domElement); 
 

 
    function setupScene(){ 
 
    var ambientLight, 
 
     geometry, 
 
     material; 
 

 
    ambientLight = new THREE.AmbientLight(0x2c3e50); 
 
    scene.add(ambientLight); 
 
    
 
    pointLight = new THREE.PointLight(0xddddff); 
 
    scene.add(pointLight); 
 
    
 
    geometry = new THREE.SphereBufferGeometry(1, 32, 32); 
 
    material = new THREE.MeshBasicMaterial({ color: 0x99ddff }); 
 
    lightSphere = new THREE.Mesh(geometry, material); 
 
    lightSphere.layers.set(OCCLUSION_LAYER); 
 
    scene.add(lightSphere); 
 
    
 
    camera.position.z = 6; 
 
    } 
 
    
 
    function addFragmentedSphere(){ 
 
    var geometry = new THREE.DodecahedronGeometry(2.9, 0); 
 

 
    var material = new THREE.MeshPhongMaterial({ 
 
    color: 0x000000, 
 
    specular: 0xffffff, 
 
    shininess: 1, 
 
    shading: THREE.FlatShading, 
 
    polygonOffset: true, 
 
    polygonOffsetFactor: 1, 
 
    wireframe:true 
 

 
    }); 
 

 
    mesh = new THREE.Mesh(geometry, material); 
 

 
    scene.add(mesh); 
 

 
    //outer frame end 
 

 
    //inner world like object start 
 

 
    var sphere_material = [ 
 
     new THREE.MeshLambertMaterial({ color: 0xffff00, side: THREE.DoubleSide }), 
 
     new THREE.MeshBasicMaterial({ transparent: true, opacity: 0 }) 
 
    ]; 
 

 
    var sphere_geometry = new THREE.OctahedronGeometry(2.7, 4); 
 
    // assign material to each face 
 
    for(var i = 0; i < sphere_geometry.faces.length; i++) { 
 
     sphere_geometry.faces[ i ].materialIndex = THREE.Math.randInt(0, 1); 
 
    } 
 

 
    sphere_geometry.sortFacesByMaterialIndex(); 
 

 
    sphere_mesh = new THREE.Mesh(sphere_geometry, sphere_material); 
 
    sphere_mesh.position.set(0, 0, 0) 
 
    mesh.add(sphere_mesh); 
 
    sphere_mesh.layers.set(OCCLUSION_LAYER); 
 
    } 
 

 
    function setupPostprocessing(){ 
 
    var pass; 
 
    
 
    occlusionRenderTarget = new THREE.WebGLRenderTarget(window.innerWidth * renderScale, window.innerHeight * renderScale); 
 
    occlusionComposer = new THREE.EffectComposer(renderer, occlusionRenderTarget); 
 
    occlusionComposer.addPass(new THREE.RenderPass(scene, camera)); 
 
    pass = new THREE.ShaderPass(THREE.VolumetericLightShader); 
 
    pass.needsSwap = false; 
 
    occlusionComposer.addPass(pass); 
 
    
 
    volumetericLightShaderUniforms = pass.uniforms; 
 
    volumetericLightShaderUniforms.exposure.value = 0.5; 
 
    volumetericLightShaderUniforms.decay.value = 0.96; 
 
    volumetericLightShaderUniforms.density.value = 0.95; 
 
    volumetericLightShaderUniforms.weight.value = 0.59; 
 
    volumetericLightShaderUniforms.samples.value = 100; 
 
    
 
    composer = new THREE.EffectComposer(renderer); 
 
    composer.addPass(new THREE.RenderPass(scene, camera)); 
 
    pass = new THREE.ShaderPass(THREE.AdditiveBlendingShader); 
 
    pass.uniforms.tAdd.value = occlusionRenderTarget.texture; 
 
    composer.addPass(pass); 
 
    pass.renderToScreen = true; 
 
    } 
 
    
 
    function onFrame(){ 
 
    requestAnimationFrame(onFrame); 
 
    update(); 
 
    render(); 
 
    } 
 
    
 
    function update(){ 
 
    mesh.rotation.x += 0.003; 
 
    mesh.rotation.y += 0.003; 
 
    } 
 

 
    function render(){ 
 
    camera.layers.set(OCCLUSION_LAYER); 
 
    renderer.setClearColor(0x000000); 
 
    occlusionComposer.render(); 
 
    
 
    camera.layers.set(DEFAULT_LAYER); 
 
    renderer.setClearColor(0x090611); 
 
    composer.render(); 
 
    } 
 
    
 
    function addRenderTargetImage(){   
 
    var material, 
 
     mesh, 
 
     folder; 
 

 
    material = new THREE.ShaderMaterial(THREE.PassThroughShader); 
 
    material.uniforms.tDiffuse.value = occlusionRenderTarget.texture; 
 

 
    mesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), material); 
 
    composer.passes[1].scene.add(mesh); 
 
    mesh.visible = false; 
 
    } 
 
    
 
    window.addEventListener('resize', function(){ 
 

 
    camera.aspect = window.innerWidth/window.innerHeight; 
 
    camera.updateProjectionMatrix(); 
 

 
    renderer.setSize(window.innerWidth, window.innerHeight); 
 

 
    var pixelRatio = renderer.getPixelRatio(), 
 
     newWidth = Math.floor(window.innerWidth/pixelRatio) || 1, 
 
     newHeight = Math.floor(window.innerHeight/pixelRatio) || 1; 
 

 
    composer.setSize(newWidth, newHeight); 
 
    occlusionComposer.setSize(newWidth * renderScale, newHeight * renderScale); 
 
     
 
    }, false); 
 
    
 
    setupScene(); 
 
    setupPostprocessing(); 
 
    addFragmentedSphere();// 
 
    addRenderTargetImage(); 
 
    onFrame(); 
 
}())
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script> 
 
<script src="https://abberg.github.io/lib/shaders/CopyShader.js"></script> 
 
<script src="https://abberg.github.io/lib/postprocessing/EffectComposer.js"></script> 
 
<script src="https://abberg.github.io/lib/postprocessing/RenderPass.js"></script> 
 
<script src="https://abberg.github.io/lib/postprocessing/ShaderPass.js"></script>

+0

comment pouvons-nous ajuster les paramètres lors de l'ajout de l'image de fond à la scène? – underscore

+0

@underscore Bonjour à tous. À mon avis, le paramètre le plus pertinent est la couleur des rayons (définie par la propriété 'pointLight = new THREE.PointLight (0xddddff); line) et la lumière volumétrique (définie par l'objet shader' volumetericLightShaderUniforms' à l'intérieur de la fonction 'setupPostprocessing()'). Peut-être aussi la taille de la sphère lumineuse comparée à la taille de 'sphere_geometry'. –

+0

Avez-vous une méthode de chat rapide? – underscore