API

Supporting Fog With ShaderMaterial

How To Support Fog with ShaderMaterial

In order to support fog in your custom shaders, you will have to add some lines of code in your vertex and pixel shaders.

Vertex shader

First, you need to make sure you are computing the world position in your vertex shader (it has to be named worldPos):

vec4 worldPos = world * p;
gl_Position = viewProjection * worldPos;

This means you have to declare these uniforms:

uniform mat4 world;
uniform mat4 view;
uniform mat4 viewProjection;

Please note the addition of view which is used by the fog functions. Then you need to import the fog functions:

#include<fogVertexDeclaration>

And call them:

#include<fogVertex>

Here is a full example of a working vertex shader:

import { Effect } from "@babylonjs/core/Materials/effect";
Effect.ShadersStore["myVertexShader"] = `
precision highp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 world;
uniform mat4 view;
uniform mat4 viewProjection;
varying vec2 vUV;
#include<fogVertexDeclaration>
void main() {
vec4 p = vec4(position, 1.);
vec4 worldPos = world * p;
gl_Position = viewProjection * worldPos;
vUV = uv;
#include<fogVertex>
}`;

Fragment shader

For the fragment shader, you also need to import the fog functions:

#include<fogFragmentDeclaration>

Then use them:

#include<fogFragment>(color,gl_FragColor)

The full version will look like this:

import { Effect } from "@babylonjs/core/Materials/effect";
Effect.ShadersStore['myFragmentShader'] = `
varying vec2 vUV;
uniform sampler2D tex;
#include<fogFragmentDeclaration>
vec2 uvPixelPerfect(vec2 uv) {
vec2 res = vec2(textureSize(tex, 0));
uv = uv * res;
vec2 seam = floor(uv + 0.5);
uv = seam + clamp((uv-seam) / fwidth(uv), -0.5, 0.5);
return uv / res;
}
void main() {
vec4 color = texture2D(tex,vUV);
gl_FragColor = color;
#include<fogFragment>(color,gl_FragColor)
}`;

Javascript

You then have to add the following code in the onBind callback of your ShaderMaterial:

shaderMaterial.onBind = function () {
const effect = shaderMaterial.getEffect();
effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
effect.setColor3("vFogColor", scene.fogColor);
};

And you're done :)

Please find an example here: Fog And Shader Material