OiO.lk Blog javascript How can I fix GLSS Shading on THREE.js so it shows an accurate day-night cycle on an earth?
javascript

How can I fix GLSS Shading on THREE.js so it shows an accurate day-night cycle on an earth?


I’m working on a 3D Model of the earth for a project, and I am having a problem. Originally, I was using no shading, and added both materials to a group, with THREE.AdditiveBlending. This led to what is seen in the image below, where the lights that show up on the night texture show up throughout the day too.

Next, I switched over to GLSL. I’m new to it, so I apologize if my code is terrible. I’m trying to get it so that no lights are shown if the dayTexture is there. In the image below, you can see that this just ends up with the area where the nightTexture is supposed to be a dark blue blur.

You can ignore the atmosphere and clouds, that is something that was added after the previous screenshot.

So far, I have swapped over from blending to GLSL, with my current code being here:

<script id="earthVertexShader" type="x-shader/x-vertex">
    //varying means the value is passed in the both the vertex and fragment shader, so a vector3 is passed to the fragment shader
    varying vec3 varyNormal;
    varying vec3 varyPosition;
    void main(){
    //basically prevents the model from being distorted, when orbitControls are used
    varyNormal = normalize(normalMatrix * normal);
    //position of the vertex in the world space (where the earth is)
    varyPosition = vec3(modelViewMatrix * vec4(position, 1.0));
    //gets the final position for the rendering
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>
 <!-- fragment shader deals with colors, while vertex is for points on the 3d shape-->
<script id="earthFragmentShader" type="x-shader/x-fragment">
    uniform sampler2D dayTexture;
    uniform sampler2D nightTexture;
    uniform vec3 lightDirection;
    uniform vec2 resolution;
    varying vec3 varyNormal;
    varying vec3 varyPosition;
        
    void main(){
        vec3 lightDir = normalize(lightDirection);
        float dotData = dot(varyNormal, lightDir);
        //takes info abt the light and the normal of the vertex to calculate the brightness of the vertex
    float blendFactor = smoothstep(-0.1, 0.1, dotData);                 
    //gets brightness of the current vertex
    vec2 uv = gl_FragCoord.xy / resolution;
    vec4 dayColor = texture2D(dayTexture, uv);
    vec4 nightColor = texture2D(nightTexture, uv);
    
    // Blend day and night textures
        vec4 finalColor = mix(nightColor, dayColor, blendFactor);
        gl_FragColor = vec4(finalColor.rgb, 1.0);
    }
</script>

In addition, here is where I add the nightTexture to the earth:

//values needed for the shading: texture and where the light is from
    const dayTexture = new THREE.TextureLoader().load(dayTimeTexture);
    const nightTexture = new THREE.TextureLoader().load(nightTimeTexture);
    const lightDirection = new THREE.Vector3(-3.5, 0.5, 1.5).normalize();
    //changed to shaderMaterial for the shading
    const nightShader = new THREE.ShaderMaterial({
        //uniforms are just the data that the shader uses we defined earlier
        uniforms: {
            dayTexture: {value: dayTexture},
            nightTexture: {value: nightTexture},
            lightDirection: {value: lightDirection},
            resolution: {value: new THREE.Vector2(window.innerWidth, window.innerHeight)},
        },
        vertexShader: document.getElementById("earthVertexShader").textContent,
        fragmentShader: document.getElementById("earthFragmentShader").textContent,
        transparent: true,
        blending: THREE.NormalBlending,
    });
    
    const lightMesh = new THREE.Mesh(geometry, nightShader)
    earthGrouping.add(lightMesh);

The daytimeTexture that is added is a meshPhongMaterial using a imgmap, I also tried that before realising that does not work for a ShaderMaterial. I think it has something to do with the blending and/or transparency in the fragment shader, but I am not the most sure.

Any help would be greatly appreciated!



You need to sign in to view this answers

Exit mobile version