Anyone have any luck getting shader materials to respond to fog?

Hey everyone - I’m trying to get this shader:

varying vec2 vUv;

uniform sampler2D uMap;
uniform float uTime;
uniform vec3 uColor;

uniform vec3 fogColor;
uniform float fogNear;
uniform float fogFar;

void main() {
    vec2 uv = vUv * 10.0 + vec2(uTime * -0.05);

    uv.y += 0.01 * (sin(uv.x * 3.5 + uTime * 0.35) + sin(uv.x * 4.8 + uTime * 1.05) + sin(uv.x * 7.3 + uTime * 0.45)) / 3.0;
    uv.x += 0.12 * (sin(uv.y * 4.0 + uTime * 0.5) + sin(uv.y * 6.8 + uTime * 0.75) + sin(uv.y * 11.3 + uTime * 0.2)) / 3.0;
    uv.y += 0.12 * (sin(uv.x * 4.2 + uTime * 0.64) + sin(uv.x * 6.3 + uTime * 1.65) + sin(uv.x * 8.2 + uTime * 0.45)) / 3.0;

    vec4 tex1 = texture2D(uMap, uv * 1.0);
    vec4 tex2 = texture2D(uMap, uv * 1.0 + vec2(0.2));

    vec3 color = uColor;

    gl_FragColor = vec4(color + vec3(tex1.a * 0.9 - tex2.a * 0.02), 1.0);
    #ifdef USE_FOG
        #ifdef USE_LOGDEPTHBUF_EXT
            float depth = gl_FragDepthEXT / gl_FragCoord.w;
        #else
            float depth = gl_FragCoord.z / gl_FragCoord.w;
        #endif
        float fogFactor = smoothstep( fogNear, fogFar, depth );
        gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );
    #endif
}

to respond to fog. The fog portion came from an old stackoverflow question and I’ve had no luck - setting fog to true in the constructor:
let shade = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide
})

just causes:

three.module.js:24079 Uncaught TypeError: Cannot read property 'value' of undefined
    at Object.refreshFogUniforms 

has anyone done this recently?

Three Version & react-three-fiber:

    "react-three-fiber": "^4.2.17",
    "three": "^0.118.3"

Here is a complete, minimal example with a custom shader using fog: https://jsfiddle.net/03ref9q4/2/

The idea is to:

  • add the correct fog uniforms to the material.
  • set ShaderMaterial.fog to true so the renderer knows the material should be affected by fog and thus updates the respective uniforms.
  • include the respective shader chunks.
4 Likes

Ah cool I didn’t know you could just #include <fog_fragment>

that’s super nifty. - thanks

Thanks a ton this worked!

Did you write this off the top of your head? Or was the example laying around somewhere I didn’t see

I have written it from scratch.

4 Likes

Well thank you for your work!!!
It saved me a lot of time I’d been fiddling with this for a few hrs!

Just to be sure I understand: the #include s come from threejs and are loaded into the browser by three correct?

The renderer will parse the include statements and replace them with the actual GLSL code.

1 Like

Very cool - so it’s like a threejs specific pre-processor?

Yes, that sounds right :wink:

1 Like