diff --git a/src/lib/model/ModelMaterial.ts b/src/lib/model/ModelMaterial.ts index 85e55e7..aef6120 100644 --- a/src/lib/model/ModelMaterial.ts +++ b/src/lib/model/ModelMaterial.ts @@ -16,6 +16,8 @@ class ModelMaterial extends THREE.RawShaderMaterial { this.uniforms = { textures: { value: textures }, alphaRef: { value: alphaRef }, + fogColor: { value: new THREE.Color(0.25, 0.5, 0.8) }, + fogParams: { value: new THREE.Vector3(0.0, 1066.0, 1.0) }, }; this.glslVersion = THREE.GLSL3; diff --git a/src/lib/model/shader/fragment.ts b/src/lib/model/shader/fragment.ts index 6b64c29..407d270 100644 --- a/src/lib/model/shader/fragment.ts +++ b/src/lib/model/shader/fragment.ts @@ -4,6 +4,8 @@ const FRAGMENT_SHADER_PREAMBLE = ` precision highp float; uniform sampler2D textures[2]; +uniform vec3 fogColor; +uniform vec3 fogParams; uniform float alphaRef; in float vLight; @@ -68,6 +70,19 @@ void combine_opaque_mod2x(inout vec4 color, in vec4 tex0, in vec4 tex1) { } `; +const FRAGMENT_SHADER_FOG = ` +void applyFog(inout vec4 color, float distance) { + float fogStart = fogParams.x; + float fogEnd = fogParams.y; + float fogModifier = fogParams.z; + + float fogFactor = (fogEnd - distance) / (fogEnd - fogStart); + fogFactor = clamp(fogFactor * fogModifier, 0.0, 1.0); + + color = vec4(mix(color.rgb, fogColor.rgb, 1.0 - fogFactor), color.a); +} +`; + const FRAGMENT_SHADER_MAIN_ALPHATEST = ` // Alpha test if (color.a < alphaRef) { @@ -82,6 +97,11 @@ vec3 lightAmbient = normalize(vec3(0.5, 0.5, 0.5)); color.rgb *= lightDiffuse * vLight + lightAmbient; `; +const FRAGMENT_SHADER_MAIN_FOG = ` +// Apply fog +applyFog(color, vCameraDistance); +`; + const createFragmentShader = (textureCount: number, combineFunction: string) => { const shaderChunks = []; @@ -96,6 +116,8 @@ const createFragmentShader = (textureCount: number, combineFunction: string) => shaderChunks.push(FRAGMENT_SHADER_COMBINERS); + shaderChunks.push(FRAGMENT_SHADER_FOG); + const mainChunks = []; mainChunks.push(`color.rgba = vec4(1.0, 1.0, 1.0, 1.0);`); @@ -113,6 +135,8 @@ const createFragmentShader = (textureCount: number, combineFunction: string) => mainChunks.push(FRAGMENT_SHADER_MAIN_LIGHTING); + mainChunks.push(FRAGMENT_SHADER_MAIN_FOG); + const main = [`void main() {`, mainChunks.map((chunk) => ` ${chunk}`).join('\n'), '}'].join( '\n', );