diff --git a/src/materials/SpotLightMaterial.tsx b/src/materials/SpotLightMaterial.tsx index e97f02105..53615df77 100644 --- a/src/materials/SpotLightMaterial.tsx +++ b/src/materials/SpotLightMaterial.tsx @@ -18,70 +18,78 @@ export class SpotLightMaterial extends THREE.ShaderMaterial { transparent: true, depthWrite: false, vertexShader: /* glsl */ ` - varying vec3 vNormal; - varying vec3 vWorldPosition; - varying float vViewZ; - varying float vIntensity; - uniform vec3 spotPosition; - uniform float attenuation; - - void main() { - // compute intensity - vNormal = normalize( normalMatrix * normal ); - vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); - vWorldPosition = worldPosition.xyz; - vec4 viewPosition = viewMatrix * worldPosition; - vViewZ = viewPosition.z; - float intensity = distance(worldPosition.xyz, spotPosition) / attenuation; - intensity = 1.0 - clamp(intensity, 0.0, 1.0); - vIntensity = intensity; - // set gl_Position - gl_Position = projectionMatrix * viewPosition; - - }`, - fragmentShader: /* glsl */ ` - #include <packing> - - varying vec3 vNormal; - varying vec3 vWorldPosition; - uniform vec3 lightColor; - uniform vec3 spotPosition; - uniform float attenuation; - uniform float anglePower; - uniform sampler2D depth; - uniform vec2 resolution; - uniform float cameraNear; - uniform float cameraFar; - varying float vViewZ; - varying float vIntensity; - uniform float opacity; - - float readDepth( sampler2D depthSampler, vec2 coord ) { - float fragCoordZ = texture2D( depthSampler, coord ).x; - float viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar); - return viewZ; - } - - void main() { - float d = 1.0; - bool isSoft = resolution[0] > 0.0 && resolution[1] > 0.0; - if (isSoft) { - vec2 sUv = gl_FragCoord.xy / resolution; - d = readDepth(depth, sUv); + varying vec3 vNormal; + varying float vViewZ; + varying float vIntensity; + uniform vec3 spotPosition; + uniform float attenuation; + + #include <common> + #include <logdepthbuf_pars_vertex> + + void main() { + // compute intensity + vNormal = normalize(normalMatrix * normal); + vec4 worldPosition = modelMatrix * vec4(position, 1); + vec4 viewPosition = viewMatrix * worldPosition; + vViewZ = viewPosition.z; + + vIntensity = 1.0 - saturate(distance(worldPosition.xyz, spotPosition) / attenuation); + + gl_Position = projectionMatrix * viewPosition; + + #include <logdepthbuf_vertex> } - float intensity = vIntensity; - vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z)); - float angleIntensity = pow( dot(normal, vec3(0.0, 0.0, 1.0)), anglePower ); - intensity *= angleIntensity; - // fades when z is close to sampled depth, meaning the cone is intersecting existing geometry - if (isSoft) { - intensity *= smoothstep(0., 1., vViewZ - d); + `, + fragmentShader: /* glsl */ ` + varying vec3 vNormal; + varying float vViewZ; + varying float vIntensity; + + uniform vec3 lightColor; + uniform float anglePower; + uniform sampler2D depth; + uniform vec2 resolution; + uniform float cameraNear; + uniform float cameraFar; + uniform float opacity; + + #include <packing> + #include <logdepthbuf_pars_fragment> + + float readDepth(sampler2D depthSampler, vec2 uv) { + float fragCoordZ = texture(depthSampler, uv).r; + + // https://github.com/mrdoob/three.js/issues/23072 + #ifdef USE_LOGDEPTHBUF + float viewZ = 1.0 - exp2(fragCoordZ * log(cameraFar + 1.0) / log(2.0)); + #else + float viewZ = perspectiveDepthToViewZ(fragCoordZ, cameraNear, cameraFar); + #endif + + return viewZ; } - gl_FragColor = vec4(lightColor, intensity * opacity); - #include <tonemapping_fragment> - #include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}> - }`, + void main() { + #include <logdepthbuf_fragment> + + vec3 normal = vec3(vNormal.x, vNormal.y, abs(vNormal.z)); + float angleIntensity = pow(dot(normal, vec3(0, 0, 1)), anglePower); + float intensity = vIntensity * angleIntensity; + + // fades when z is close to sampled depth, meaning the cone is intersecting existing geometry + bool isSoft = resolution[0] > 0.0 && resolution[1] > 0.0; + if (isSoft) { + vec2 uv = gl_FragCoord.xy / resolution; + intensity *= smoothstep(0.0, 1.0, vViewZ - readDepth(depth, uv)); + } + + gl_FragColor = vec4(lightColor, intensity * opacity); + + #include <tonemapping_fragment> + #include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}> + } + `, }) } }