Skip to content

Instantly share code, notes, and snippets.

@gsimone
Last active June 6, 2022 09:19
Show Gist options
  • Save gsimone/08b5e0cbe65ad3917581fa2b7acd004d to your computer and use it in GitHub Desktop.
Save gsimone/08b5e0cbe65ad3917581fa2b7acd004d to your computer and use it in GitHub Desktop.
Three fog rework

Three.js fog rework

Why?

Three's fog is very hardcoded in both the engine internals and the shaders:

A custom fog can't setup custom shaders or custom uniforms. While the shaders are "hackable" by overriding the globals, uniforms aren't since we can't override the refreshFogUniforms method.

Current Implementation

Uniforms are copied to shaders here:

	function refreshFogUniforms( uniforms, fog ) {

		uniforms.fogColor.value.copy( fog.color );

		if ( fog.isFog ) {

			uniforms.fogNear.value = fog.near;
			uniforms.fogFar.value = fog.far;

		} else if ( fog.isFogExp2 ) {

			uniforms.fogDensity.value = fog.density;

		}

	}
if ( fog && material.fog === true ) {

  materials.refreshFogUniforms( m_uniforms, fog );

}

The Fog classes (Fog and FogExp2) are effectively only used to hold configuration and a single flag used in shader compilation.

Propsal

New Fog class:

  • it holds the specific fog shaders in an object ( eg. this.shaders.fog_fragment )
  • it has a refreshFogUniforms method that behaves like the one in WebGLMaterials but only cares about the specific fog type.
  • it holds uniform values

WebGLRenderer would NOT call a method on the materials object, calling one on the scene's fog instead:

if ( fog && material.fog === true ) {

  fog.refreshFogUniforms( m_uniforms, materials );

}

Backwards compatibility

  • Fog and FogExp2 should keep working as they do now.
    • can they be even kept in the same codepaths ( ie. the fog shader stays where it is, only new fog types add on to it )
/**
* Abstract example, a real one will be better
**/
class MyFog extends Fog {
constructor( fogEnvMap ) {
super()
// initialize whatever you need
// keep some of the shaderChunk shaders and override others
this.shaders = {
fog_vertex: ShaderChunk.fog_vertex,
fog_pars_vertex: /* glsl */`my code`,
...etc
}
}
refreshFogUniforms( uniforms, materials ) {
uniforms.fogEnvMap.value = this.envMap;
uniforms.fogNear.value = this.near
uniforms.fogFar.value = this.far
}
toJSON() { ... }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment