Skip to content

Commit

Permalink
Fix: SpotlightMaterial sync shader code with drei + update example (#78)
Browse files Browse the repository at this point in the history
* fix: sync shader code with drei

* fix: update spotlight example
  • Loading branch information
vis-prime authored Dec 12, 2024
1 parent 9c07f55 commit ff415d4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 39 deletions.
9 changes: 3 additions & 6 deletions .storybook/stories/volumetricSpotlight.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}

Expand All @@ -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)
}

/**
Expand Down Expand Up @@ -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)
}

/**
Expand Down
73 changes: 40 additions & 33 deletions src/materials/SpotLightMaterial.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -31,67 +32,73 @@ export const SpotLightMaterial = shaderMaterial<SpotLightMaterialProps>(
},
/* glsl */ `
varying vec3 vNormal;
varying vec3 vWorldPosition;
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.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 <logdepthbuf_vertex>
}`,
/* glsl */ `
#include <packing>
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 <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;
}
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 <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) {
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 <tonemapping_fragment>
#include <${parseInt(REVISION.replace(/\D+/g, '')) >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>
#include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>
}`
)

0 comments on commit ff415d4

Please sign in to comment.