From ff415d4062885a7385848d3a9f5d464ed311c232 Mon Sep 17 00:00:00 2001 From: VishaL <119810373+vis-prime@users.noreply.github.com> Date: Fri, 13 Dec 2024 00:08:27 +0530 Subject: [PATCH] Fix: SpotlightMaterial sync shader code with drei + update example (#78) * fix: sync shader code with drei * fix: update spotlight example --- .../stories/volumetricSpotlight.stories.ts | 9 +-- src/materials/SpotLightMaterial.ts | 73 ++++++++++--------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/.storybook/stories/volumetricSpotlight.stories.ts b/.storybook/stories/volumetricSpotlight.stories.ts index 5bb21cf..17d8518 100644 --- a/.storybook/stories/volumetricSpotlight.stories.ts +++ b/.storybook/stories/volumetricSpotlight.stories.ts @@ -127,9 +127,6 @@ function setupSpotlight() { * Create depthTexture and DepthRender target */ function updateDepthTargets() { - renderer.getSize(rendererSize) - rendererSize.multiplyScalar(renderer.getPixelRatio()) - if (depthTexture) depthTexture.dispose() depthTexture = new DepthTexture(volumeParams.depthResolution, volumeParams.depthResolution) depthTexture.format = DepthFormat @@ -151,8 +148,8 @@ function updateDepthTargets() { window.addEventListener('resize', depthOnResize) } else { volumeMaterial.depth = null - volumeMaterial.resolution.set(0, 0) window.removeEventListener('resize', depthOnResize) + volumeMaterial.resolution.set(0, 0) } } @@ -173,7 +170,7 @@ function renderDepth() { function depthOnResize() { renderer.getSize(rendererSize) rendererSize.multiplyScalar(renderer.getPixelRatio()) - volumeMaterial.resolution.copy(renderer.getSize(rendererSize)) + volumeMaterial.resolution.copy(rendererSize) } /** @@ -259,7 +256,7 @@ function addSpotLightGui(gui: GUI) { }) volFolder.add(volumeParams, 'useDepth').onChange(updateDepthTargets) - volFolder.add(volumeParams, 'depthResolution', 128, 2048, 1).onChange(updateDepthTargets) + volFolder.add(volumeParams, 'depthResolution', 128, 2048, 128).onChange(updateDepthTargets) } /** diff --git a/src/materials/SpotLightMaterial.ts b/src/materials/SpotLightMaterial.ts index dbc3c56..b2ad862 100644 --- a/src/materials/SpotLightMaterial.ts +++ b/src/materials/SpotLightMaterial.ts @@ -1,5 +1,6 @@ -import { Color, Vector2, Vector3, REVISION, type Texture } from 'three' +import { Color, Vector2, Vector3, type Texture } from 'three' import { shaderMaterial } from '../core/shaderMaterial' +import { version } from '../helpers/constants' type SpotLightMaterialProps = { depth: Texture | null @@ -31,67 +32,73 @@ export const SpotLightMaterial = shaderMaterial( }, /* glsl */ ` varying vec3 vNormal; - varying vec3 vWorldPosition; varying float vViewZ; varying float vIntensity; uniform vec3 spotPosition; uniform float attenuation; + #include + #include + void main() { // compute intensity - vNormal = normalize( normalMatrix * normal ); - vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); - vWorldPosition = worldPosition.xyz; + vNormal = normalize(normalMatrix * normal); + vec4 worldPosition = modelMatrix * vec4(position, 1); 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; + vIntensity = 1.0 - saturate(distance(worldPosition.xyz, spotPosition) / attenuation); + + gl_Position = projectionMatrix * viewPosition; + + #include }`, /* glsl */ ` - #include - varying vec3 vNormal; - varying vec3 vWorldPosition; + varying float vViewZ; + varying float vIntensity; + 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); + #include + #include + + 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; } - 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); - } - 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; + void main() { + #include + + 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) { - intensity *= smoothstep(0., 1., vViewZ - d); + vec2 uv = gl_FragCoord.xy / resolution; + intensity *= smoothstep(0.0, 1.0, vViewZ - readDepth(depth, uv)); } + gl_FragColor = vec4(lightColor, intensity * opacity); #include - #include <${parseInt(REVISION.replace(/\D+/g, '')) >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}> + #include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}> }` )