How to render fog on top of SSAO?

Hi,
I’m using Fog and SSAO in my project, and the SSAO is emphasize stuff that needed to be faded, like the horizon line and buildings (like in the example image)
Is there any way the render the fog on top of the SSAO effect?
thanks.

SSAO is a screen-space technique. The standard fog that three.js gives you out of the box is a forward rendering technique.

What this means is that three.js’s standard fog is drawn together with the scene into the color buffer, and then you draw SSAO on top of that.

Your SSAO default shader has no knowledge of the fog, in fact - it doesn’t even know anything about the color, it operates purely on depth (well, you can mix normals in as well, but that’s not important here).

If you want to have fog on top of the SSAO - you need to either modify SSAO shader to render fog in there, or write another shader that would draw fog based on depth information, same as above basically, just as a separate step.

By the way, this issue comes up more often than you might think, transparent objects for example should typically be drawn on top of SSAO, so having something like a 3-pass rendering where you draw some solid stuff, then you do some postprocessing and then you draw transparent stuff - this is quite normal.

2 Likes

I have little experience in writing shaders… do you have any suggestions how to start with a shader that draw fog based on depth information?

if you don’t already do, consider using GitHub - vanruesc/postprocessing: A post processing library that provides the means to implement image filter effects for three.js. i’ve found an example with fog + shadow plane + ao. may not be comparable since the plane is transparent but in any case, vanruesc is very responsive and works on it constantly, if you bring the issue up he will look at it.

in any case distanceThreshold should fix it as well:

Property Description
options.distanceThreshold Number
* default: 0.97 A global distance threshold at which the occlusion effect starts to fade out. Range [0.0, 1.0].
options.distanceFalloff Number
* default: 0.03 The distance falloff. Influences the smoothness of the overall occlusion cutoff. Range [0.0, 1.0].

I tried to write a shader, but it not working…

( function () {

	var FogShader = {
		uniforms: {
			'tDiffuse': { value: null },
			'fogColor': {  value: new THREE.Vector3( 1.0, 0, 0 ) },
			'fogNear': {  value: 1.0 },
			'fogFar': {  value: 10.0 }
		},
		vertexShader:
		
  /* glsl */
		
		varying vec2 vUv;
		varying float fogDepth;
		
		void main() {

			vUv = uv;
			
			vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
			gl_Position = projectionMatrix * mvPosition;
			
			fogDepth = - mvPosition.z;
			

		}`,
		fragmentShader:
		
  /* glsl */
  `

		uniform vec3 fogColor;
		uniform float fogNear;
		uniform float fogFar;
		varying float fogDepth;
		
		uniform sampler2D tDiffuse;
		varying vec2 vUv;

		void main() {

			vec4 texel = texture2D( tDiffuse, vUv );
			gl_FragColor = texel ;
			
			float fogFactor = smoothstep( fogNear, fogFar, fogDepth );
			gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );

		}`
	};

	THREE.FogShader = FogShader;

} )();

I’m using it like this:

	var fogpass = new THREE.ShaderPass( THREE.FogShader );
	composer.addPass( fogpass );

If I manually change the fogFactor to 1 - all output is red, so I think I have something wrong with the fogDepth…