Skip to content

Commit 6bdbe8a

Browse files
authored
Merge pull request #244 from gkjohnson/consolidate-lights
Consolidate lighting information into a single texture
2 parents 029368a + 434c4a5 commit 6bdbe8a

File tree

11 files changed

+311
-399
lines changed

11 files changed

+311
-399
lines changed

README.md

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ ptMaterial.materials.updateFrom( materials, textures );
116116

117117
// update the lights
118118
ptMaterial.lights.updateFrom( lights );
119-
ptMaterial.lightCount = lights.length;
120119

121120
// set the environment map
122121
const texture = await new RGBELoader().loadAsync( envMapUrl );
@@ -524,12 +523,7 @@ _extends MaterialBase_
524523
textures: RenderTarget2DArray,
525524

526525
// Light information
527-
lights: LightsTexture,
528-
lightCount = 0: Number,
529-
530-
// Spotlight information
531-
spotLights: SpotLightsTexture,
532-
spotLightCount: Number,
526+
lights: LightsInfoUniformStruct,
533527
iesProfiles: IESProfilesTexture,
534528

535529
// Environment Map information
@@ -653,33 +647,17 @@ Updates the size and values of the texture to align with the provided set of mat
653647

654648
The "matte" and "side" values must be updated explicitly.
655649

656-
## LightsTexture
657-
658-
_extends DataTexture_
659-
660-
Helper texture uniform for encoding lights as texture data.
661-
662-
### .updateFrom
663-
664-
```js
665-
updateFrom( lights : Array<Light> ) : void
666-
```
667-
668-
Updates the size and values of the texture to align with the provided set of lights.
669-
670-
## SpotLightsTexture
671-
672-
_extends DataTexture_
650+
## LightsInfoUniformStruct
673651

674-
Helper texture uniform for encoding spot lights as texture data.
652+
Helper uniform for encoding lights as texture data with count.
675653

676654
### .updateFrom
677655

678656
```js
679-
updateFrom( lights : Array<SpotLight>, iesTextures = [] : Array<Texture> ) : void
657+
updateFrom( lights : Array<Light>, iesTextures = [] : Array<Texture> ) : void
680658
```
681659

682-
Updates the values of the texture to align with the provided set of lights and ies textures.
660+
Updates the size and values of the texture to align with the provided set of lights and IES textures.
683661

684662
## EquirectHdrInfoUniform
685663

@@ -729,6 +707,7 @@ Set of randomness and other light transport utilities for use in a shader. See t
729707

730708
- The project requires use of WebGL2.
731709
- All textures must use the same wrap and interpolation flags.
710+
- Spotlights are not supported in non-MIS rendering currently.
732711

733712
# Screenshots
734713

example/spotLights.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ async function init() {
248248

249249
scene.add( result.scene );
250250

251-
const { bvh, textures, materials, lights, spotLights } = result;
251+
const { bvh, textures, materials, lights } = result;
252252
const geometry = bvh.geometry;
253253
const material = ptRenderer.material;
254254

@@ -260,10 +260,7 @@ async function init() {
260260
material.textures.setTextures( renderer, 2048, 2048, textures );
261261
material.materials.updateFrom( materials, textures );
262262
material.iesProfiles.updateFrom( renderer, iesTextures );
263-
material.lights.updateFrom( lights );
264-
material.lightCount = lights.length;
265-
material.spotLights.updateFrom( spotLights, iesTextures );
266-
material.spotLightCount = spotLights.length;
263+
material.lights.updateFrom( lights, iesTextures );
267264
ptRenderer.material.envMapInfo.updateFrom( scene.environment );
268265

269266
generator.dispose();
@@ -397,8 +394,7 @@ function animate() {
397394
ptRenderer.material.bounces = params.bounces;
398395
ptRenderer.material.physicalCamera.updateFrom( perspectiveCamera );
399396

400-
ptRenderer.material.lights.updateFrom( lights );
401-
ptRenderer.material.spotLights.updateFrom( spotLights, iesTextures );
397+
ptRenderer.material.lights.updateFrom( lights, iesTextures );
402398

403399
// update objects
404400
perspectiveCamera.updateMatrixWorld();

src/core/DynamicPathTracingSceneGenerator.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class DynamicPathTracingSceneGenerator {
5252
const normalMapRequired = ! ! c.material.normalMap;
5353
setCommonAttributes( c.geometry, { attributes, normalMapRequired } );
5454

55-
} else if ( c.isRectAreaLight ) {
55+
} else if ( c.isRectAreaLight || c.isSpotLight ) {
5656

5757
this.lights.push( c );
5858

src/core/PathTracingSceneGenerator.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export class PathTracingSceneGenerator {
1010

1111
const meshes = [];
1212
const lights = [];
13-
const spotLights = [];
1413

1514
for ( let i = 0, l = scene.length; i < l; i ++ ) {
1615

@@ -33,14 +32,10 @@ export class PathTracingSceneGenerator {
3332

3433
meshes.push( c );
3534

36-
} else if ( c.isRectAreaLight ) {
35+
} else if ( c.isRectAreaLight || c.isSpotLight ) {
3736

3837
lights.push( c );
3938

40-
} else if ( c.isSpotLight ) {
41-
42-
spotLights.push( c );
43-
4439
}
4540

4641
} );
@@ -52,21 +47,19 @@ export class PathTracingSceneGenerator {
5247
attributes: [ 'position', 'normal', 'tangent', 'uv' ],
5348
} ),
5449
lights,
55-
spotLights
5650
};
5751

5852
}
5953

6054
generate( scene, options = {} ) {
6155

62-
const { materials, textures, geometry, lights, spotLights } = this.prepScene( scene );
56+
const { materials, textures, geometry, lights } = this.prepScene( scene );
6357
const bvhOptions = { strategy: SAH, ...options, maxLeafTris: 1 };
6458
return {
6559
scene,
6660
materials,
6761
textures,
6862
lights,
69-
spotLights,
7063
bvh: new MeshBVH( geometry, bvhOptions ),
7164
};
7265

src/index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ export * from './uniforms/MaterialsTexture.js';
1515
export * from './uniforms/RenderTarget2DArray.js';
1616
export * from './uniforms/EquirectHdrInfoUniform.js';
1717
export * from './uniforms/PhysicalCameraUniform.js';
18-
export * from './uniforms/LightsTexture.js';
19-
export * from './uniforms/SpotLightsTexture.js';
18+
export * from './uniforms/LightsInfoUniformStruct.js';
2019
export * from './uniforms/IESProfilesTexture.js';
2120

2221
// utils

src/materials/PhysicalPathTracingMaterial.js

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import { shaderLightSampling } from '../shader/shaderLightSampling.js';
1313
import { shaderUtils } from '../shader/shaderUtils.js';
1414
import { PhysicalCameraUniform } from '../uniforms/PhysicalCameraUniform.js';
1515
import { EquirectHdrInfoUniform } from '../uniforms/EquirectHdrInfoUniform.js';
16-
import { LightsTexture } from '../uniforms/LightsTexture.js';
17-
import { SpotLightsTexture } from '../uniforms/SpotLightsTexture.js';
16+
import { LightsInfoUniformStruct } from '../uniforms/LightsInfoUniformStruct.js';
1817
import { IESProfilesTexture } from '../uniforms/IESProfilesTexture.js';
1918

2019
export class PhysicalPathTracingMaterial extends MaterialBase {
@@ -56,10 +55,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
5655
materialIndexAttribute: { value: new UIntVertexAttributeTexture() },
5756
materials: { value: new MaterialsTexture() },
5857
textures: { value: new RenderTarget2DArray().texture },
59-
lights: { value: new LightsTexture() },
60-
lightCount: { value: 0 },
61-
spotLights: { value: new SpotLightsTexture() },
62-
spotLightCount: { value: 0 },
58+
lights: { value: new LightsInfoUniformStruct() },
6359
iesProfiles: { value: new IESProfilesTexture().texture },
6460
cameraWorldMatrix: { value: new Matrix4() },
6561
invProjectionMatrix: { value: new Matrix4() },
@@ -141,10 +137,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
141137
uniform int seed;
142138
uniform float opacity;
143139
uniform sampler2D materials;
144-
uniform sampler2D lights;
145-
uniform uint lightCount;
146-
uniform sampler2D spotLights;
147-
uniform uint spotLightCount;
140+
uniform LightsInfo lights;
148141
uniform sampler2DArray iesProfiles;
149142
150143
${ shaderLightSampling }
@@ -425,7 +418,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
425418
426419
bool hit = bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
427420
428-
LightSampleRec lightHit = lightsClosestHit( lights, lightCount, rayOrigin, rayDirection );
421+
LightSampleRec lightHit = lightsClosestHit( lights.tex, lights.count, rayOrigin, rayDirection );
429422
430423
if ( lightHit.hit && ( lightHit.dist < dist || !hit ) ) {
431424
@@ -437,15 +430,23 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
437430
438431
#if FEATURE_MIS
439432
440-
// weight the contribution
441-
float misWeight = misHeuristic( sampleRec.pdf, lightHit.pdf / float( lightCount + 1u ) );
442-
gl_FragColor.rgb += lightHit.emission * throughputColor * misWeight;
433+
// NOTE: we skip MIS for spotlights since we haven't fixed the forward
434+
// path tracing code path, yet
435+
if ( lightHit.type == SPOT_LIGHT_TYPE ) {
436+
437+
gl_FragColor.rgb += lightHit.emission * throughputColor;
438+
439+
} else {
440+
441+
// weight the contribution
442+
float misWeight = misHeuristic( sampleRec.pdf, lightHit.pdf / float( lights.count + 1u ) );
443+
gl_FragColor.rgb += lightHit.emission * throughputColor * misWeight;
444+
445+
}
443446
444447
#else
445448
446-
gl_FragColor.rgb +=
447-
lightHit.emission *
448-
throughputColor;
449+
gl_FragColor.rgb += lightHit.emission * throughputColor;
449450
450451
#endif
451452
@@ -468,7 +469,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
468469
// get the PDF of the hit envmap point
469470
vec3 envColor;
470471
float envPdf = envMapSample( environmentRotation * rayDirection, envMapInfo, envColor );
471-
envPdf /= float( lightCount + 1u );
472+
envPdf /= float( lights.count + 1u );
472473
473474
// and weight the contribution
474475
float misWeight = misHeuristic( sampleRec.pdf, envPdf );
@@ -789,57 +790,14 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
789790
bool isBelowSurface = dot( rayDirection, faceNormal ) < 0.0;
790791
rayOrigin = point + faceNormal * ( maxPoint + 1.0 ) * ( isBelowSurface ? - RAY_OFFSET : RAY_OFFSET );
791792
792-
// spot light sampling
793-
LightSampleRec lightSampleRec = randomSpotLightSample( spotLights, iesProfiles, spotLightCount, rayOrigin );
794-
795-
bool isSampleBelowSurface = dot( faceNormal, lightSampleRec.direction ) < 0.0;
796-
if ( isSampleBelowSurface ) {
797-
798-
lightSampleRec.pdf = 0.0;
799-
800-
}
801-
802-
// check if a ray could even reach the light area
803-
if (
804-
lightSampleRec.pdf > 0.0 &&
805-
isDirectionValid( lightSampleRec.direction, normal, faceNormal ) &&
806-
! anyCloserHit( bvh, rayOrigin, lightSampleRec.direction, lightSampleRec.dist )
807-
) {
808-
809-
// get the material pdf
810-
vec3 sampleColor;
811-
float lightMaterialPdf = bsdfResult( outgoing, clearcoatOutgoing, normalize( invBasis * lightSampleRec.direction ), normalize( clearcoatInvBasis * lightSampleRec.direction ), surfaceRec, sampleColor );
812-
bool isValidSampleColor = any( greaterThanEqual( sampleColor, vec3( 0.0 ) ) );
813-
if ( lightMaterialPdf > 0.0 && isValidSampleColor ) {
814-
815-
#if FEATURE_MIS
816-
817-
// weight the direct light contribution
818-
float lightPdf = lightSampleRec.pdf;// / float( spotLightCount );
819-
float misWeight = misHeuristic( lightPdf, lightMaterialPdf );
820-
gl_FragColor.rgb += lightSampleRec.emission * throughputColor * sampleColor * misWeight / lightPdf;
821-
822-
#else
823-
824-
gl_FragColor.rgb +=
825-
lightSampleRec.emission *
826-
throughputColor *
827-
sampleColor;
828-
829-
#endif
830-
831-
}
832-
833-
}
834-
835793
// direct env map sampling
836794
#if FEATURE_MIS
837795
838796
// uniformly pick a light or environment map
839-
if( rand() > 1.0 / float( lightCount + 1u ) ) {
797+
if( rand() > 1.0 / float( lights.count + 1u ) ) {
840798
841799
// sample a light or environment
842-
LightSampleRec lightSampleRec = randomLightSample( lights, lightCount, rayOrigin );
800+
LightSampleRec lightSampleRec = randomLightSample( lights.tex, iesProfiles, lights.count, rayOrigin );
843801
844802
bool isSampleBelowSurface = dot( faceNormal, lightSampleRec.direction ) < 0.0;
845803
if ( isSampleBelowSurface ) {
@@ -862,7 +820,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
862820
if ( lightMaterialPdf > 0.0 && isValidSampleColor ) {
863821
864822
// weight the direct light contribution
865-
float lightPdf = lightSampleRec.pdf / float( lightCount + 1u );
823+
float lightPdf = lightSampleRec.pdf / float( lights.count + 1u );
866824
float misWeight = misHeuristic( lightPdf, lightMaterialPdf );
867825
gl_FragColor.rgb += lightSampleRec.emission * throughputColor * sampleColor * misWeight / lightPdf;
868826
@@ -902,7 +860,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
902860
if ( envMaterialPdf > 0.0 && isValidSampleColor ) {
903861
904862
// weight the direct light contribution
905-
envPdf /= float( lightCount + 1u );
863+
envPdf /= float( lights.count + 1u );
906864
float misWeight = misHeuristic( envPdf, envMaterialPdf );
907865
gl_FragColor.rgb += attenuatedColor * environmentIntensity * envColor * throughputColor * sampleColor * misWeight / envPdf;
908866

0 commit comments

Comments
 (0)