Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/jsm/tsl/display/SSRNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,8 @@ class SSRNode extends TempNode {

sampleEnvReflection = () => {

if ( this._importanceEnvironment === null ) return vec3( 0 );

const envColor = vec3( 0 ).toVar();

if ( this.envImportanceSampling ) {
Expand Down
58 changes: 39 additions & 19 deletions examples/jsm/tsl/lighting/ClusteredLightsNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,15 @@ class ClusteredLightsNode extends LightsNode {
this._lightIndexes = null;
this._screenClusterIndex = null;
this._compute = null;
this._lightsTexture = null;
this._zSliceRangesTexture = null;
this._zSliceRangesData = null;

const lightsData = new Float32Array( maxLights * 4 * 2 );
this._lightsTexture = new DataTexture( lightsData, lightsData.length / 8, 2, RGBAFormat, FloatType );

// Per Z-slice light range for Z-culling (CPU-sorted, uploaded each frame)

this._zSliceRangesData = new Float32Array( zSlices * 4 );
this._zSliceRangesTexture = new DataTexture( this._zSliceRangesData, zSlices, 1, RGBAFormat, FloatType );

this._lightViewZ = new Float32Array( maxLights );
this._lightSortOrder = [];

Expand Down Expand Up @@ -138,8 +144,6 @@ class ClusteredLightsNode extends LightsNode {

const zRanges = this._zSliceRangesData;

if ( zRanges === null ) return;

const near = camera.near;
const far = camera.far;
const NZ = this.zSlices;
Expand Down Expand Up @@ -418,7 +422,7 @@ class ClusteredLightsNode extends LightsNode {

create( width, height ) {

const { tileSize, maxLights, zSlices, maxLightsPerCluster, _chunksPerCluster: chunksPerCluster } = this;
const { tileSize, zSlices, maxLightsPerCluster, _chunksPerCluster: chunksPerCluster } = this;

const bufferSize = new Vector2( width, height );

Expand All @@ -429,20 +433,25 @@ class ClusteredLightsNode extends LightsNode {

this._gridDimensions.value.set( NX, NY );

// Lights data texture (same layout as TiledLightsNode)
// release the compute pipeline and bindings built for the previous grid

const lightsData = new Float32Array( maxLights * 4 * 2 );
const lightsTexture = new DataTexture( lightsData, lightsData.length / 8, 2, RGBAFormat, FloatType );
if ( this._compute !== null ) this._compute.dispose();

// Per Z-slice light range for Z-culling (CPU-sorted, uploaded each frame)
// Per-cluster light-index storage (ivec4 chunks).

const lightIndexesLength = clusterCount * chunksPerCluster * 4;

let lightIndexes = this._lightIndexes;

const zSliceRangesData = new Float32Array( NZ * 4 );
const zSliceRangesTexture = new DataTexture( zSliceRangesData, NZ, 1, RGBAFormat, FloatType );
if ( lightIndexes === null || lightIndexes.value.array.length < lightIndexesLength ) {

// Per-cluster light-index storage (ivec4 chunks)
// TODO: Free the outgoing buffer once the renderer destroys the GPU resources of
// standalone storage attributes (`Bindings._destroyBindings()` skips storage buffers).

const lightIndexesArray = new Int32Array( clusterCount * chunksPerCluster * 4 );
const lightIndexes = attributeArray( lightIndexesArray, 'ivec4' ).setName( 'lightIndexes' );
const lightIndexesArray = new Int32Array( lightIndexesLength );
lightIndexes = attributeArray( lightIndexesArray, 'ivec4' ).setName( 'lightIndexes' );

}

// compute-side accessors (use instanceIndex)

Expand Down Expand Up @@ -528,7 +537,7 @@ class ClusteredLightsNode extends LightsNode {
const index = int( 0 ).toVar();

// Z-culling: only test lights that can reach this cluster's Z-slice
const zRange = textureLoad( zSliceRangesTexture, ivec2( cz, 0 ) );
const zRange = textureLoad( this._zSliceRangesTexture, ivec2( cz, 0 ) );
const rangeStart = int( zRange.x );
const rangeEnd = int( zRange.y );

Expand Down Expand Up @@ -589,9 +598,20 @@ class ClusteredLightsNode extends LightsNode {
this._lightIndexes = lightIndexes;
this._screenClusterIndex = screenClusterIndex;
this._compute = compute;
this._lightsTexture = lightsTexture;
this._zSliceRangesTexture = zSliceRangesTexture;
this._zSliceRangesData = zSliceRangesData;

}

/**
* Frees the GPU resources allocated by this node.
*/
dispose() {

if ( this._compute !== null ) this._compute.dispose();

this._lightsTexture.dispose();
this._zSliceRangesTexture.dispose();

super.dispose();

}

Expand Down
4 changes: 1 addition & 3 deletions examples/webgpu_postprocessing_ssr_denoise.html
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,7 @@
environmentNode: hdrTexture,
envImportanceSampling: params.ssr.envImportanceSampling,
binaryRefine: params.ssr.binaryRefine
} );
ssrNode.setEnvMap( hdrTexture );
ssrNode.toInspector( 'SSR' );
} ).toInspector( 'SSR' );

temporalReprojectNode = temporalReproject( ssrNode, scenePassDepth, scenePassNormal, scenePassVelocity, camera, {
mode: 'specular',
Expand Down
4 changes: 2 additions & 2 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -1521,9 +1521,9 @@ class WebGLRenderer {
const materialProperties = properties.get( material );
const program = materialProperties.currentProgram;

if ( program.isReady() ) {
if ( program === undefined || program.isReady() ) {

// remove any programs that report they're ready to use from the list
// stop waiting for materials that are ready to use or have been disposed
materials.delete( material );

}
Expand Down