@@ -124,6 +124,11 @@ struct TriangleHit {
124124 t : f32 ,
125125}
126126
127+ struct Scatter {
128+ wi : vec3f ,
129+ throughput : vec3f ,
130+ }
131+
127132fn rayColor (primaryRay : Ray , rngState : ptr <function , u32 >) -> vec3f {
128133 var ray = primaryRay ;
129134
@@ -133,10 +138,9 @@ fn rayColor(primaryRay: Ray, rngState: ptr<function, u32>) -> vec3f {
133138 var intersection : Intersection ;
134139 if rayIntersectBvh (ray , T_MAX , & intersection ) {
135140 let p = intersection . p ;
136- let scatterDirection = sampleLambertian (intersection , rngState );
137- let scatterThroughput = UNIFORM_HEMISPHERE_MULTIPLIER * evalLambertian (intersection , scatterDirection );
138- ray = Ray (p , scatterDirection );
139- throughput *= scatterThroughput ;
141+ let scatter = evalImplicitLambertian (intersection , rngState );
142+ ray = Ray (p , scatter . wi );
143+ throughput *= scatter . throughput ;
140144 } else {
141145 let unitDirection = normalize (ray . direction );
142146 let t = 0 .5f * (unitDirection . y + 1f );
@@ -156,17 +160,16 @@ fn generateCameraRay(camera: Camera, rngState: ptr<function, u32>, u: f32, v: f3
156160 return Ray (origin , direction );
157161}
158162
159- fn sampleLambertian (hit : Intersection , rngState : ptr <function , u32 >) -> vec3f {
160- let v = rngNextInUnitHemisphere (rngState );
163+ fn evalImplicitLambertian (hit : Intersection , rngState : ptr <function , u32 >) -> Scatter {
164+ let v = rngNextInCosineWeightedHemisphere (rngState );
161165 let onb = pixarOnb (hit . n );
162- return onb * v ;
163- }
166+ let wi = onb * v ;
164167
165- fn evalLambertian (hit : Intersection , wi : vec3f ) -> vec3f {
166168 let textureDesc = textureDescriptors [textureDescriptorIndices [hit . triangleIdx ]];
167169 let uv = hit . uv ;
168170 let albedo = textureLookup (textureDesc , uv );
169- return albedo * FRAC_1_PI * max (EPSILON , dot (hit . n , wi ));
171+
172+ return Scatter (wi , albedo );
170173}
171174
172175fn pixarOnb (n : vec3f ) -> mat3x3f {
@@ -352,16 +355,15 @@ fn textureLookup(desc: TextureDescriptor, uv: vec2f) -> vec3f {
352355}
353356
354357@must_use
355- fn rngNextInUnitHemisphere (state : ptr <function , u32 >) -> vec3f {
358+ fn rngNextInCosineWeightedHemisphere (state : ptr <function , u32 >) -> vec3f {
356359 let r1 = rngNextFloat (state );
357360 let r2 = rngNextFloat (state );
361+ let sqrtR2 = sqrt (r2 );
358362
363+ let z = sqrt (1f - r2 );
359364 let phi = 2f * PI * r1 ;
360- let sinTheta = sqrt (1f - r2 * r2 );
361-
362- let x = cos (phi ) * sinTheta ;
363- let y = sin (phi ) * sinTheta ;
364- let z = r2 ;
365+ let x = cos (phi ) * sqrtR2 ;
366+ let y = sin (phi ) * sqrtR2 ;
365367
366368 return vec3 (x , y , z );
367369}
0 commit comments