Variable: surfaceWeather
constsurfaceWeather:object
Defined in: modules/lighting/surface-weather/surface-weather.ts:57
Material helpers for persistent wetness, puddles and upward-facing snow. Every helper accepts a caller-provided exposure mask, so water and sheltered surfaces can opt out.
Type Declaration
defaultUniforms
readonlydefaultUniforms:SurfaceWeatherUniforms=DEFAULT_UNIFORMS
dependencies
readonlydependencies: [{fs: "\nfloat valueNoise_hash(vec2 cell) {\n vec3 value = fract(vec3(cell.x, cell.y, cell.x) * 0.1031);\n value += dot(value, value.yzx + 33.33);\n return fract((value.x + value.y) * value.z);\n}\nfloat valueNoise_noise(vec2 position) {\n vec2 cell = floor(position);\n vec2 fraction = fract(position);\n vec2 blend = fraction * fraction * (3.0 - 2.0 * fraction);\n return mix(mix(valueNoise_hash(cell), valueNoise_hash(cell + vec2(1.0, 0.0)), blend.x),\n mix(valueNoise_hash(cell + vec2(0.0, 1.0)), valueNoise_hash(cell + vec2(1.0)), blend.x), blend.y);\n}\n\nfloat valueNoise_hash3(vec3 cell) {\n vec3 value = fract(cell * 0.1031);\n value += dot(value, value.yzx + 33.33);\n return fract((value.x + value.y) * value.z);\n}\nfloat valueNoise_noise3(vec3 position) {\n vec3 cell = floor(position);\n vec3 fraction = fract(position);\n vec3 blend = fraction * fraction * (3.0 - 2.0 * fraction);\n float bottom = mix(mix(valueNoise_hash3(cell), valueNoise_hash3(cell + vec3(1.0, 0.0, 0.0)), blend.x),\n mix(valueNoise_hash3(cell + vec3(0.0, 1.0, 0.0)), valueNoise_hash3(cell + vec3(1.0, 1.0, 0.0)), blend.x), blend.y);\n float top = mix(mix(valueNoise_hash3(cell + vec3(0.0, 0.0, 1.0)), valueNoise_hash3(cell + vec3(1.0, 0.0, 1.0)), blend.x),\n mix(valueNoise_hash3(cell + vec3(0.0, 1.0, 1.0)), valueNoise_hash3(cell + vec3(1.0)), blend.x), blend.y);\n return mix(bottom, top, blend.z);\n}\n";name:"valueNoise";source: "\nfn valueNoise_hash(cell: vec2f) -> f32 {\n var value = fract(vec3f(cell.x, cell.y, cell.x) * 0.1031);\n value += vec3f(dot(value, value.yzx + vec3f(33.33)));\n return fract((value.x + value.y) * value.z);\n}\nfn valueNoise_noise(position: vec2f) -> f32 {\n let cell = floor(position);\n let fraction = fract(position);\n let blend = fraction * fraction * (vec2f(3.0) - 2.0 * fraction);\n return mix(mix(valueNoise_hash(cell), valueNoise_hash(cell + vec2f(1.0, 0.0)), blend.x),\n mix(valueNoise_hash(cell + vec2f(0.0, 1.0)), valueNoise_hash(cell + vec2f(1.0)), blend.x), blend.y);\n}\n\nfn valueNoise_hash3(cell: vec3f) -> f32 {\n var value = fract(cell * 0.1031);\n value += vec3f(dot(value, value.yzx + vec3f(33.33)));\n return fract((value.x + value.y) * value.z);\n}\nfn valueNoise_noise3(position: vec3f) -> f32 {\n let cell = floor(position);\n let fraction = fract(position);\n let blend = fraction * fraction * (vec3f(3.0) - 2.0 * fraction);\n let bottom = mix(mix(valueNoise_hash3(cell), valueNoise_hash3(cell + vec3f(1.0, 0.0, 0.0)), blend.x),\n mix(valueNoise_hash3(cell + vec3f(0.0, 1.0, 0.0)), valueNoise_hash3(cell + vec3f(1.0, 1.0, 0.0)), blend.x), blend.y);\n let top = mix(mix(valueNoise_hash3(cell + vec3f(0.0, 0.0, 1.0)), valueNoise_hash3(cell + vec3f(1.0, 0.0, 1.0)), blend.x),\n mix(valueNoise_hash3(cell + vec3f(0.0, 1.0, 1.0)), valueNoise_hash3(cell + vec3f(1.0)), blend.x), blend.y);\n return mix(bottom, top, blend.z);\n}\n"; }]
fs
readonlyfs: "\nlayout(std140) uniform surfaceWeatherUniforms {\n float wetness;\n float snow;\n float puddles;\n float scale;\n vec3 snowColor;\n vec3 skyColor;\n} surfaceWeather;\n\nfloat surfaceWeather_getSnow(vec3 position, vec3 normal, float exposure) {\n if (surfaceWeather.snow <= 0.0 || exposure <= 0.0) return 0.0;\n float slope = smoothstep(0.4, 0.85, normalize(normal).z);\n float variation = valueNoise_noise(position.xy / max(surfaceWeather.scale, 0.01));\n float coverage = smoothstep(variation * 0.65, variation * 0.65 + 0.35, surfaceWeather.snow);\n return coverage * slope * clamp(exposure, 0.0, 1.0);\n}\nfloat surfaceWeather_getWetness(vec3 position, vec3 normal, float exposure) {\n if (surfaceWeather.wetness <= 0.0 || exposure <= 0.0) return 0.0;\n return clamp(surfaceWeather.wetness, 0.0, 1.0) * clamp(exposure, 0.0, 1.0) * (1.0 - surfaceWeather_getSnow(position, normal, exposure));\n}\nfloat surfaceWeather_getPuddle(vec3 position, vec3 normal, float exposure) {\n if (surfaceWeather.wetness <= 0.0 || surfaceWeather.puddles <= 0.0 || exposure <= 0.0) return 0.0;\n float variation = valueNoise_noise(position.xy / max(surfaceWeather.scale, 0.01) + vec2(8.3, 2.7));\n return surfaceWeather_getWetness(position, normal, exposure) * clamp(surfaceWeather.puddles, 0.0, 1.0) *\n smoothstep(0.8, 0.98, normalize(normal).z) * smoothstep(0.38, 0.7, variation);\n}\nvec3 surfaceWeather_getAlbedo(vec3 albedo, vec3 position, vec3 normal, float exposure) {\n if ((surfaceWeather.wetness <= 0.0 && surfaceWeather.snow <= 0.0) || exposure <= 0.0) return albedo;\n float wetness = surfaceWeather_getWetness(position, normal, exposure);\n float snow = surfaceWeather_getSnow(position, normal, exposure);\n return mix(albedo * (1.0 - wetness * 0.38), surfaceWeather.snowColor, snow);\n}\nfloat surfaceWeather_getRoughness(float roughness, vec3 position, vec3 normal, float exposure) {\n if ((surfaceWeather.wetness <= 0.0 && surfaceWeather.snow <= 0.0) || exposure <= 0.0) return roughness;\n float wetness = surfaceWeather_getWetness(position, normal, exposure);\n float puddle = surfaceWeather_getPuddle(position, normal, exposure);\n float snow = surfaceWeather_getSnow(position, normal, exposure);\n return mix(mix(roughness, 0.16, max(puddle, wetness * 0.6)), 0.95, snow);\n}\n// Approximate dielectric highlights and sky tint; callers may use the albedo/roughness helpers with PBR instead.\nvec3 surfaceWeather_getReflection(vec3 position, vec3 normal, vec3 camera, vec3 lightDirection, vec3 lightColor, float exposure) {\n if (surfaceWeather.wetness <= 0.0 || exposure <= 0.0) return vec3(0.0);\n vec3 surfaceNormal = normalize(normal);\n vec3 view = normalize(camera - position);\n vec3 halfway = normalize(view + normalize(lightDirection));\n float wetness = surfaceWeather_getWetness(position, normal, exposure);\n float puddle = surfaceWeather_getPuddle(position, normal, exposure);\n float facing = max(dot(surfaceNormal, view), 0.0);\n float fresnel = 0.02 + 0.98 * pow(1.0 - facing, 5.0);\n float highlight = pow(max(dot(surfaceNormal, halfway), 0.0), mix(36.0, 160.0, puddle)) * max(dot(surfaceNormal, normalize(lightDirection)), 0.0);\n return wetness * (surfaceWeather.skyColor * fresnel * (0.15 + puddle * 0.85) + lightColor * highlight * 0.6);\n}\n"
name
readonlyname:"surfaceWeather"='surfaceWeather'
source
readonlysource: "\nstruct surfaceWeatherUniforms {\n wetness: f32,\n snow: f32,\n puddles: f32,\n scale: f32,\n snowColor: vec3f,\n skyColor: vec3f,\n};\n@group(3) @binding(auto) var<uniform> surfaceWeather: surfaceWeatherUniforms;\n\nfn surfaceWeather_getSnow(position: vec3f,\n normal: vec3f,\n exposure: f32) -> f32 {\n if (surfaceWeather.snow <= 0.0 || exposure <= 0.0) { return 0.0; }\n var slope: f32 = smoothstep(0.4, 0.85, normalize(normal).z);\n var variation: f32 = valueNoise_noise(position.xy / max(surfaceWeather.scale, 0.01));\n var coverage: f32 = smoothstep(variation * 0.65, variation * 0.65 + 0.35, surfaceWeather.snow);\n return coverage * slope * clamp(exposure, 0.0, 1.0);\n}\nfn surfaceWeather_getWetness(position: vec3f,\n normal: vec3f,\n exposure: f32) -> f32 {\n if (surfaceWeather.wetness <= 0.0 || exposure <= 0.0) { return 0.0; }\n return clamp(surfaceWeather.wetness, 0.0, 1.0) * clamp(exposure, 0.0, 1.0) * (1.0 - surfaceWeather_getSnow(position, normal, exposure));\n}\nfn surfaceWeather_getPuddle(position: vec3f,\n normal: vec3f,\n exposure: f32) -> f32 {\n if (surfaceWeather.wetness <= 0.0 || surfaceWeather.puddles <= 0.0 || exposure <= 0.0) { return 0.0; }\n var variation: f32 = valueNoise_noise(position.xy / max(surfaceWeather.scale, 0.01) + vec2f(8.3, 2.7));\n return surfaceWeather_getWetness(position, normal, exposure) * clamp(surfaceWeather.puddles, 0.0, 1.0) *\n smoothstep(0.8, 0.98, normalize(normal).z) * smoothstep(0.38, 0.7, variation);\n}\nfn surfaceWeather_getAlbedo(albedo: vec3f,\n position: vec3f,\n normal: vec3f,\n exposure: f32) -> vec3f {\n if ((surfaceWeather.wetness <= 0.0 && surfaceWeather.snow <= 0.0) || exposure <= 0.0) { return albedo; }\n var wetness: f32 = surfaceWeather_getWetness(position, normal, exposure);\n var snow: f32 = surfaceWeather_getSnow(position, normal, exposure);\n return mix(albedo * (1.0 - wetness * 0.38), surfaceWeather.snowColor, snow);\n}\nfn surfaceWeather_getRoughness(roughness: f32,\n position: vec3f,\n normal: vec3f,\n exposure: f32) -> f32 {\n if ((surfaceWeather.wetness <= 0.0 && surfaceWeather.snow <= 0.0) || exposure <= 0.0) { return roughness; }\n var wetness: f32 = surfaceWeather_getWetness(position, normal, exposure);\n var puddle: f32 = surfaceWeather_getPuddle(position, normal, exposure);\n var snow: f32 = surfaceWeather_getSnow(position, normal, exposure);\n return mix(mix(roughness, 0.16, max(puddle, wetness * 0.6)), 0.95, snow);\n}\n// Approximate dielectric highlights and sky tint; callers may use the albedo/roughness helpers with PBR instead.\nfn surfaceWeather_getReflection(position: vec3f,\n normal: vec3f,\n camera: vec3f,\n lightDirection: vec3f,\n lightColor: vec3f,\n exposure: f32) -> vec3f {\n if (surfaceWeather.wetness <= 0.0 || exposure <= 0.0) { return vec3f(0.0); }\n var surfaceNormal: vec3f = normalize(normal);\n var view: vec3f = normalize(camera - position);\n var halfway: vec3f = normalize(view + normalize(lightDirection));\n var wetness: f32 = surfaceWeather_getWetness(position, normal, exposure);\n var puddle: f32 = surfaceWeather_getPuddle(position, normal, exposure);\n var facing: f32 = max(dot(surfaceNormal, view), 0.0);\n var fresnel: f32 = 0.02 + 0.98 * pow(1.0 - facing, 5.0);\n var highlight: f32 = pow(max(dot(surfaceNormal, halfway), 0.0), mix(36.0, 160.0, puddle)) * max(dot(surfaceNormal, normalize(lightDirection)), 0.0);\n return wetness * (surfaceWeather.skyColor * fresnel * (0.15 + puddle * 0.85) + lightColor * highlight * 0.6);\n}\n"
uniformTypes
readonlyuniformTypes:object
uniformTypes.puddles
readonlypuddles:"f32"='f32'
uniformTypes.scale
readonlyscale:"f32"='f32'
uniformTypes.skyColor
readonlyskyColor:"vec3<f32>"='vec3<f32>'
uniformTypes.snow
readonlysnow:"f32"='f32'
uniformTypes.snowColor
readonlysnowColor:"vec3<f32>"='vec3<f32>'
uniformTypes.wetness
readonlywetness:"f32"='f32'
getUniforms()
readonlygetUniforms(props?,previousUniforms?):object
Parameters
props?
Partial<Partial<SurfaceWeatherUniforms>> = {}
previousUniforms?
SurfaceWeatherUniforms | undefined
Returns
puddles
puddles:
number
scale
scale:
number
World-anchored patch size in metres.
skyColor
skyColor: [
number,number,number]
snow
snow:
number
snowColor
snowColor: [
number,number,number]
wetness
wetness:
number