How to maintain the glow effect of a json model rotating in three.js scene?

335 Views Asked by At

I add a json model with glow effect into the scene.

As follows: enter image description here

I try to rotate the json model automatically. However, it looks weird when it is rotating. The glow effect of the model does not work. enter image description here enter image description here

I assume that the position of the json model does not be changed when this model is rotating. As the result, the viewVector.value of the ShaderMaterial is constant when this model is rotating(I do not change position of the camera).

if(jsonMesh){
    jsonMesh.rotation.y += 0.1;
    jsonMesh.material.uniforms.viewVector.value =
        new THREE.Vector3().subVectors( camera.position, jsonMesh.position );

}

This is the Three.ShaderMaterial.

VertexShader and FragmentShader

<script id="vertexShader" type="x-shader/x-vertex">
    uniform vec3 viewVector;
    uniform float c;
    uniform float p;
    varying float intensity;
    void main()
    {
        vec3 vNormal = normalize( normalMatrix * normal );
        vec3 vNormel = normalize( normalMatrix * viewVector );
        intensity = pow( c - dot(vNormal, vNormel), p );

        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    }
</script>

<script id="fragmentShader" type="x-shader/x-fragment"> 
    uniform vec3 glowColor;
    varying float intensity;
    void main() 
    {
        vec3 glow = glowColor * intensity;
        gl_FragColor = vec4( glow, 1.0 );
    }
</script>

Three.ShaderMaterial.

var customMaterial = new THREE.ShaderMaterial( 
{
    uniforms: 
    { 
        "c":   { type: "f", value: 1.0 },
        "p":   { type: "f", value: 1.4 },
        glowColor: { type: "c", value: new THREE.Color(0xffff00) },
        viewVector: { type: "v3", value: camera.position }
    },
    vertexShader:   document.getElementById( 'vertexShader'   ).textContent,
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
    side: THREE.FrontSide,
    blending: THREE.AdditiveBlending,
    transparent: true
}
);

How should I modify the code in this case? Here is the Demo and source code.

1

There are 1 best solutions below

6
On BEST ANSWER

You can use built in three.js functions for this. Instead of using the camera position, I chose to show you how to set a light source position in the world. That way you can match the light source on your custom shader to any light sources you plan to add later to your 3d world. Feel free to change the worldLightPoint value to camera.position instead of new THREE.Vector3(100,100,100). and in that case the effect will remain constant with the camera position.

var v = new THREE.Vector3();
//var worldLightPoint =  camera.position;
var worldLightPoint = new THREE.Vector3(100,100,100);
function update()
{
    controls.update();
    stats.update();
    if(jsonMesh){
        jsonMesh.rotation.y += 0.1;
        jsonMesh.material.uniforms.viewVector.value = jsonMesh.worldToLocal(v.copy(worldLightPoint));
    }
}