-
-
Notifications
You must be signed in to change notification settings - Fork 36.3k
LightProbeVolume: Add position-dependent diffuse Global Illumination #33125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mrdoob
wants to merge
22
commits into
dev
Choose a base branch
from
gi
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
626d40a
IrradianceProbeGrid: Add position-dependent diffuse GI
mrdoob 7150518
IrradianceProbeGrid: Add examples
mrdoob 1d3a6ba
Rename IrradianceProbeGrid to LightProbeVolume
mrdoob 4b5df93
LightProbeVolume: Use scene.add() API
mrdoob d495e9c
LightProbeVolume: Update complex example with two-room layout
mrdoob 9ee109e
LightProbeVolume: Upgrade from L1 to L2 Spherical Harmonics
mrdoob bd1f65f
LightProbeVolume: Avoid per-fragment inverse(viewMatrix)
mrdoob 38bab39
LightProbeVolume: Increase lookSpeed in Sponza example
mrdoob 0b6d13d
LightProbeVolume: Simplify view-to-world position transform
mrdoob 6d670ad
LightProbeVolumeHelper: Add tonemapping and colorspace conversion
mrdoob 1426bca
Remove webgl_lightprobes_usd example
mrdoob 1cc496e
LightProbeVolume: Use texture atlas approach.
Mugen87 17253fd
Clean up.
Mugen87 77fe75d
Improve nomenclature.
Mugen87 1553bb1
LightProbeVolume: Clean up.
Mugen87 6212bfd
LightProbeVolume: More clean up.
Mugen87 a3b01bb
LightProveVolume: Remove useless check for coordinate system.
Mugen87 fe13d18
E2E: Update screenshots.
Mugen87 bd68af1
LightProbeVolume: Update API to use width/height/depth.
mrdoob f001b26
LightProbeVolume: Improve examples and update screenshots.
mrdoob b8d8990
LightProbeVolume: Add progress bar to Sponza example.
mrdoob f00eea2
Updated builds.
mrdoob File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,221 @@ | ||
| import { | ||
| InstancedBufferAttribute, | ||
| InstancedMesh, | ||
| Matrix4, | ||
| ShaderMaterial, | ||
| SphereGeometry, | ||
| Vector3 | ||
| } from 'three'; | ||
|
|
||
| /** | ||
| * Visualizes an {@link LightProbeVolume} by rendering a sphere at each | ||
| * probe position, shaded with the probe's L1 spherical harmonics. | ||
| * | ||
| * Uses a single `InstancedMesh` draw call for all probes. | ||
| * | ||
| * ```js | ||
| * const helper = new LightProbeVolumeHelper( probeGrid ); | ||
| * scene.add( helper ); | ||
| * ``` | ||
| * | ||
| * @augments InstancedMesh | ||
| * @three_import import { LightProbeVolumeHelper } from 'three/addons/helpers/LightProbeVolumeHelper.js'; | ||
| */ | ||
| class LightProbeVolumeHelper extends InstancedMesh { | ||
|
|
||
| /** | ||
| * Constructs a new irradiance probe grid helper. | ||
| * | ||
| * @param {LightProbeVolume} probeGrid - The probe grid to visualize. | ||
| * @param {number} [sphereSize=0.12] - The radius of each probe sphere. | ||
| */ | ||
| constructor( probeGrid, sphereSize = 0.12 ) { | ||
|
|
||
| const geometry = new SphereGeometry( sphereSize, 16, 16 ); | ||
|
|
||
| const material = new ShaderMaterial( { | ||
|
|
||
| uniforms: { | ||
|
|
||
| probeGridSH: { value: null }, | ||
| probeGridResolution: { value: new Vector3() }, | ||
|
|
||
| }, | ||
|
|
||
| vertexShader: /* glsl */` | ||
|
|
||
| attribute vec3 instanceUVW; | ||
|
|
||
| varying vec3 vWorldNormal; | ||
| varying vec3 vUVW; | ||
|
|
||
| void main() { | ||
|
|
||
| vUVW = instanceUVW; | ||
| vWorldNormal = normalize( mat3( modelMatrix ) * normal ); | ||
| gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4( position, 1.0 ); | ||
|
|
||
| } | ||
|
|
||
| `, | ||
|
|
||
| fragmentShader: /* glsl */` | ||
|
|
||
| precision highp sampler3D; | ||
|
|
||
| uniform sampler3D probeGridSH; | ||
| uniform vec3 probeGridResolution; | ||
|
|
||
| varying vec3 vWorldNormal; | ||
| varying vec3 vUVW; | ||
|
|
||
| void main() { | ||
|
|
||
| // Atlas UV mapping — must match light_probe_volume_pars_fragment.glsl.js | ||
| float nz = probeGridResolution.z; | ||
| float paddedSlices = nz + 2.0; | ||
| float atlasDepth = 7.0 * paddedSlices; | ||
| float uvZBase = vUVW.z * nz + 1.0; | ||
|
|
||
| vec4 s0 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase ) / atlasDepth ) ); | ||
| vec4 s1 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + paddedSlices ) / atlasDepth ) ); | ||
| vec4 s2 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + 2.0 * paddedSlices ) / atlasDepth ) ); | ||
| vec4 s3 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + 3.0 * paddedSlices ) / atlasDepth ) ); | ||
| vec4 s4 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + 4.0 * paddedSlices ) / atlasDepth ) ); | ||
| vec4 s5 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + 5.0 * paddedSlices ) / atlasDepth ) ); | ||
| vec4 s6 = texture( probeGridSH, vec3( vUVW.xy, ( uvZBase + 6.0 * paddedSlices ) / atlasDepth ) ); | ||
|
|
||
| // Unpack 9 vec3 SH L2 coefficients | ||
|
|
||
| vec3 c0 = s0.xyz; | ||
| vec3 c1 = vec3( s0.w, s1.xy ); | ||
| vec3 c2 = vec3( s1.zw, s2.x ); | ||
| vec3 c3 = s2.yzw; | ||
| vec3 c4 = s3.xyz; | ||
| vec3 c5 = vec3( s3.w, s4.xy ); | ||
| vec3 c6 = vec3( s4.zw, s5.x ); | ||
| vec3 c7 = s5.yzw; | ||
| vec3 c8 = s6.xyz; | ||
|
|
||
| vec3 n = normalize( vWorldNormal ); | ||
|
|
||
| float x = n.x, y = n.y, z = n.z; | ||
|
|
||
| // band 0 | ||
| vec3 result = c0 * 0.886227; | ||
|
|
||
| // band 1, | ||
| result += c1 * 2.0 * 0.511664 * y; | ||
| result += c2 * 2.0 * 0.511664 * z; | ||
| result += c3 * 2.0 * 0.511664 * x; | ||
|
|
||
| // band 2, | ||
| result += c4 * 2.0 * 0.429043 * x * y; | ||
| result += c5 * 2.0 * 0.429043 * y * z; | ||
| result += c6 * ( 0.743125 * z * z - 0.247708 ); | ||
| result += c7 * 2.0 * 0.429043 * x * z; | ||
| result += c8 * 0.429043 * ( x * x - y * y ); | ||
|
|
||
| gl_FragColor = vec4( max( result, vec3( 0.0 ) ), 1.0 ); | ||
|
|
||
| #include <tonemapping_fragment> | ||
| #include <colorspace_fragment> | ||
|
|
||
| } | ||
|
|
||
| ` | ||
|
|
||
| } ); | ||
|
|
||
| const res = probeGrid.resolution; | ||
| const count = res.x * res.y * res.z; | ||
|
|
||
| super( geometry, material, count ); | ||
|
|
||
| /** | ||
| * The probe grid to visualize. | ||
| * | ||
| * @type {LightProbeVolume} | ||
| */ | ||
| this.probeGrid = probeGrid; | ||
|
|
||
| this.type = 'LightProbeVolumeHelper'; | ||
|
|
||
| this.update(); | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Rebuilds instance matrices and UVW attributes from the current probe grid. | ||
| * Call this after changing `probeGrid` or after re-baking. | ||
| */ | ||
| update() { | ||
|
|
||
| const probeGrid = this.probeGrid; | ||
| const res = probeGrid.resolution; | ||
| const count = res.x * res.y * res.z; | ||
|
|
||
| // Resize instance matrix buffer if needed | ||
|
|
||
| if ( this.instanceMatrix.count !== count ) { | ||
|
|
||
| this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); | ||
|
|
||
| } | ||
|
|
||
| this.count = count; | ||
|
|
||
| const uvwArray = new Float32Array( count * 3 ); | ||
| const matrix = new Matrix4(); | ||
| const probePos = new Vector3(); | ||
|
|
||
| let i = 0; | ||
|
|
||
| for ( let iz = 0; iz < res.z; iz ++ ) { | ||
|
|
||
| for ( let iy = 0; iy < res.y; iy ++ ) { | ||
|
|
||
| for ( let ix = 0; ix < res.x; ix ++ ) { | ||
|
|
||
| // Remap to texel centers (must match light_probe_volume_pars_fragment.glsl.js) | ||
| uvwArray[ i * 3 ] = ( ix + 0.5 ) / res.x; | ||
| uvwArray[ i * 3 + 1 ] = ( iy + 0.5 ) / res.y; | ||
| uvwArray[ i * 3 + 2 ] = ( iz + 0.5 ) / res.z; | ||
|
|
||
| probeGrid.getProbePosition( ix, iy, iz, probePos ); | ||
| matrix.makeTranslation( probePos.x, probePos.y, probePos.z ); | ||
| this.setMatrixAt( i, matrix ); | ||
|
|
||
| i ++; | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| this.instanceMatrix.needsUpdate = true; | ||
|
|
||
| this.geometry.setAttribute( 'instanceUVW', new InstancedBufferAttribute( uvwArray, 3 ) ); | ||
|
|
||
| // Update texture uniforms | ||
|
|
||
| this.material.uniforms.probeGridSH.value = probeGrid.texture; | ||
| this.material.uniforms.probeGridResolution.value.copy( probeGrid.resolution ); | ||
|
|
||
| } | ||
|
|
||
| /** | ||
| * Frees the GPU-related resources allocated by this instance. Call this | ||
| * method whenever this instance is no longer used in your app. | ||
| */ | ||
| dispose() { | ||
|
|
||
| this.geometry.dispose(); | ||
| this.material.dispose(); | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| export { LightProbeVolumeHelper }; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.