rayzee 5.1.0 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/rayzee.es.js +842 -833
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +41 -41
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/Pipeline/RenderStage.js +0 -1
- package/src/Processor/AssetLoader.js +2 -5
- package/src/Processor/EquirectHDRInfo.js +42 -5
- package/src/Processor/SceneProcessor.js +2 -2
- package/src/TSL/BVHTraversal.js +1 -1
- package/src/TSL/Debugger.js +2 -1
- package/src/TSL/LightsCore.js +1 -1
- package/src/TSL/LightsDirect.js +9 -7
- package/src/TSL/LightsSampling.js +3 -2
- package/src/TSL/PathTracerCore.js +4 -3
- package/src/managers/EnvironmentManager.js +1 -1
package/package.json
CHANGED
|
@@ -142,7 +142,6 @@ export class RenderStage {
|
|
|
142
142
|
|
|
143
143
|
const renderMode = context.getState( 'renderMode' ) || 0;
|
|
144
144
|
const tileRenderingComplete = context.getState( 'tileRenderingComplete' );
|
|
145
|
-
const frame = context.getState( 'frame' ) || 0;
|
|
146
145
|
|
|
147
146
|
switch ( this.executionMode ) {
|
|
148
147
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box3, Vector3, RectAreaLight, Color, FloatType, LinearFilter, EquirectangularReflectionMapping,
|
|
1
|
+
import { Box3, Vector3, RectAreaLight, Color, FloatType, LinearFilter, EquirectangularReflectionMapping,
|
|
2
2
|
TextureLoader, Mesh, MeshStandardMaterial, MeshPhysicalMaterial, CircleGeometry, Points, PointsMaterial, LoadingManager, EventDispatcher
|
|
3
3
|
} from 'three';
|
|
4
4
|
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
|
@@ -171,8 +171,6 @@ export class AssetLoader extends EventDispatcher {
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
texture.generateMipmaps = true;
|
|
174
|
-
// texture.minFilter = LinearMipmapLinearFilter;
|
|
175
|
-
// texture.magFilter = LinearFilter;
|
|
176
174
|
|
|
177
175
|
this.applyEnvironmentToScene( texture );
|
|
178
176
|
this.dispatchEvent( { type: 'load', texture } );
|
|
@@ -353,7 +351,7 @@ export class AssetLoader extends EventDispatcher {
|
|
|
353
351
|
|
|
354
352
|
}
|
|
355
353
|
|
|
356
|
-
async findAndLoadModelFromZip( zip
|
|
354
|
+
async findAndLoadModelFromZip( zip ) {
|
|
357
355
|
|
|
358
356
|
const mainModelFiles = [
|
|
359
357
|
'scene.gltf', 'scene.glb', 'model.gltf', 'model.glb',
|
|
@@ -459,7 +457,6 @@ export class AssetLoader extends EventDispatcher {
|
|
|
459
457
|
if ( extension === 'gltf' ) {
|
|
460
458
|
|
|
461
459
|
const gltfContent = strFromU8( fileContent );
|
|
462
|
-
const gltfJson = JSON.parse( gltfContent );
|
|
463
460
|
const manager = new LoadingManager();
|
|
464
461
|
const gltfDir = filePath.split( '/' ).slice( 0, - 1 ).join( '/' );
|
|
465
462
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataUtils, HalfFloatType, FloatType } from 'three';
|
|
1
|
+
import { DataUtils, HalfFloatType, FloatType, SRGBColorSpace } from 'three';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Binary search to find the closest index
|
|
@@ -38,18 +38,35 @@ function colorToLuminance( r, g, b ) {
|
|
|
38
38
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* sRGB to linear conversion (IEC 61966-2-1 transfer function)
|
|
43
|
+
*/
|
|
44
|
+
function sRGBToLinear( c ) {
|
|
45
|
+
|
|
46
|
+
return c <= 0.04045 ? c / 12.92 : ( ( c + 0.055 ) / 1.055 ) ** 2.4;
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
/**
|
|
42
51
|
* Extract Float32 RGBA pixel data from an environment map.
|
|
43
|
-
* Handles HalfFloat/integer type conversion
|
|
52
|
+
* Handles HalfFloat/integer type conversion, canvas extraction for
|
|
53
|
+
* non-DataTexture images (JPG/PNG), sRGB-to-linear conversion, and Y-flip.
|
|
44
54
|
* @returns {{ floatData: Float32Array, width: number, height: number }}
|
|
45
55
|
*/
|
|
46
56
|
export function extractFloatData( envMap ) {
|
|
47
57
|
|
|
48
|
-
const { width, height
|
|
58
|
+
const { width, height } = envMap.image;
|
|
59
|
+
let data = envMap.image.data;
|
|
60
|
+
let needsSRGBToLinear = false;
|
|
49
61
|
|
|
62
|
+
// No CPU-accessible data — extract from HTMLImageElement / ImageBitmap via canvas
|
|
50
63
|
if ( ! data ) {
|
|
51
64
|
|
|
52
|
-
|
|
65
|
+
const canvas = new OffscreenCanvas( width, height );
|
|
66
|
+
const ctx = canvas.getContext( '2d' );
|
|
67
|
+
ctx.drawImage( envMap.image, 0, 0, width, height );
|
|
68
|
+
data = ctx.getImageData( 0, 0, width, height ).data;
|
|
69
|
+
needsSRGBToLinear = true;
|
|
53
70
|
|
|
54
71
|
}
|
|
55
72
|
|
|
@@ -72,7 +89,7 @@ export function extractFloatData( envMap ) {
|
|
|
72
89
|
|
|
73
90
|
} else {
|
|
74
91
|
|
|
75
|
-
// Integer types (Uint8, Int16, etc.)
|
|
92
|
+
// Integer types (Uint8, Uint8Clamped, Int16, etc.)
|
|
76
93
|
let maxIntValue;
|
|
77
94
|
if ( data instanceof Int8Array || data instanceof Int16Array || data instanceof Int32Array ) {
|
|
78
95
|
|
|
@@ -93,6 +110,26 @@ export function extractFloatData( envMap ) {
|
|
|
93
110
|
|
|
94
111
|
}
|
|
95
112
|
|
|
113
|
+
// Also flag sRGB conversion for DataTextures explicitly marked as sRGB
|
|
114
|
+
if ( ! needsSRGBToLinear && envMap.colorSpace === SRGBColorSpace ) {
|
|
115
|
+
|
|
116
|
+
needsSRGBToLinear = true;
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Convert sRGB to linear so CDF luminance matches GPU-sampled linear values
|
|
121
|
+
if ( needsSRGBToLinear ) {
|
|
122
|
+
|
|
123
|
+
for ( let i = 0, l = floatData.length; i < l; i += 4 ) {
|
|
124
|
+
|
|
125
|
+
floatData[ i ] = sRGBToLinear( floatData[ i ] );
|
|
126
|
+
floatData[ i + 1 ] = sRGBToLinear( floatData[ i + 1 ] );
|
|
127
|
+
floatData[ i + 2 ] = sRGBToLinear( floatData[ i + 2 ] );
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
}
|
|
132
|
+
|
|
96
133
|
// Remove Y-flip for CDF computation
|
|
97
134
|
if ( envMap.flipY ) {
|
|
98
135
|
|
|
@@ -820,8 +820,8 @@ export class SceneProcessor {
|
|
|
820
820
|
|
|
821
821
|
// Factory method for creating any additional scene elements
|
|
822
822
|
// Currently returns an empty array by default
|
|
823
|
-
const white = new Color( 0xffffff );
|
|
824
|
-
const black = new Color( 0x000000 );
|
|
823
|
+
// const white = new Color( 0xffffff );
|
|
824
|
+
// const black = new Color( 0x000000 );
|
|
825
825
|
return [
|
|
826
826
|
// { position: new Vector3( - 4, 2, 0 ), radius: 0.8, material: { color: white, emissive: black, emissiveIntensity: 0, roughness: 1.0 } },
|
|
827
827
|
// { position: new Vector3( - 1.5, 2, 0 ), radius: 0.8, material: { color: white, emissive: black, emissiveIntensity: 0, roughness: 1.0 } },
|
package/src/TSL/BVHTraversal.js
CHANGED
|
@@ -268,7 +268,7 @@ export const traverseBVH = Fn( ( [
|
|
|
268
268
|
} );
|
|
269
269
|
|
|
270
270
|
// If we found a very close hit, we can terminate early
|
|
271
|
-
If( closestHit.didHit.and( closestHit.dst.lessThan(
|
|
271
|
+
If( closestHit.didHit.and( closestHit.dst.lessThan( 1e-6 ) ), () => {
|
|
272
272
|
|
|
273
273
|
Break();
|
|
274
274
|
|
package/src/TSL/Debugger.js
CHANGED
|
@@ -356,7 +356,8 @@ export const TraceDebugMode = Fn( ( [
|
|
|
356
356
|
const bounceDir = cosineWeightedSample( { N: normalA, xi } ).toVar();
|
|
357
357
|
|
|
358
358
|
// Trace secondary ray from the hit point (offset along normal to avoid self-intersection)
|
|
359
|
-
const
|
|
359
|
+
const debugEps = max( float( 1e-4 ), length( hitInfo.hitPoint ).mul( 1e-6 ) );
|
|
360
|
+
const bounceOrigin = hitInfo.hitPoint.add( normalA.mul( debugEps ) ).toVar();
|
|
360
361
|
const bounceRay = Ray( { origin: bounceOrigin, direction: bounceDir } );
|
|
361
362
|
|
|
362
363
|
const bounceHit = HitInfo.wrap( traverseBVH(
|
package/src/TSL/LightsCore.js
CHANGED
|
@@ -257,7 +257,7 @@ export const intersectAreaLight = Fn( ( [ light, rayOrigin, rayDirection ] ) =>
|
|
|
257
257
|
const t = dot( light.position.sub( rayOrigin ), normal ).mul( invDenom ).toVar();
|
|
258
258
|
|
|
259
259
|
// Skip intersections behind the ray
|
|
260
|
-
If( t.greaterThan(
|
|
260
|
+
If( t.greaterThan( 1e-5 ), () => {
|
|
261
261
|
|
|
262
262
|
// Optimized rectangle test using vector rejection
|
|
263
263
|
const hitPoint = rayOrigin.add( rayDirection.mul( t ) );
|
package/src/TSL/LightsDirect.js
CHANGED
|
@@ -142,8 +142,9 @@ export const traceShadowRay = Fn( ( [
|
|
|
142
142
|
} );
|
|
143
143
|
|
|
144
144
|
// Continue ray past transmissive surface
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
const transEps = max( float( 1e-5 ), length( shadowHit.hitPoint ).mul( 1e-6 ) );
|
|
146
|
+
rayOrigin.assign( shadowHit.hitPoint.add( dir.mul( transEps ) ) );
|
|
147
|
+
remainingDist.subAssign( shadowHit.dst.add( transEps ) );
|
|
147
148
|
|
|
148
149
|
} ).ElseIf( shadowMaterial.transparent, () => {
|
|
149
150
|
|
|
@@ -158,8 +159,9 @@ export const traceShadowRay = Fn( ( [
|
|
|
158
159
|
} );
|
|
159
160
|
|
|
160
161
|
// Continue ray past transparent surface
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
const alphaEps = max( float( 1e-5 ), length( shadowHit.hitPoint ).mul( 1e-6 ) );
|
|
163
|
+
rayOrigin.assign( shadowHit.hitPoint.add( dir.mul( alphaEps ) ) );
|
|
164
|
+
remainingDist.subAssign( shadowHit.dst.add( alphaEps ) );
|
|
163
165
|
|
|
164
166
|
} ).Else( () => {
|
|
165
167
|
|
|
@@ -257,7 +259,7 @@ export const estimateLightImportance = Fn( ( [ light, hitPoint, normal, material
|
|
|
257
259
|
|
|
258
260
|
If( lightFacing.greaterThan( 0.0 ), () => {
|
|
259
261
|
|
|
260
|
-
const solidAngle = light.area.div( max( distSq,
|
|
262
|
+
const solidAngle = light.area.div( max( distSq, 1e-4 ) );
|
|
261
263
|
const power = light.intensity.mul( dot( light.color, REC709_LUMINANCE_COEFFICIENTS ) ).mul( light.area );
|
|
262
264
|
|
|
263
265
|
// Material-aware weighting
|
|
@@ -659,7 +661,7 @@ export const calculatePointLightContribution = Fn( ( [
|
|
|
659
661
|
const rayOffset = calculateRayOffset( hitPoint, normal, material );
|
|
660
662
|
const rayOrigin = hitPoint.add( rayOffset );
|
|
661
663
|
|
|
662
|
-
const visibility = traceShadowRayFn( rayOrigin, lightDir, distance.
|
|
664
|
+
const visibility = traceShadowRayFn( rayOrigin, lightDir, distance.mul( 0.999 ), rngState );
|
|
663
665
|
|
|
664
666
|
If( visibility.greaterThan( 0.0 ), () => {
|
|
665
667
|
|
|
@@ -711,7 +713,7 @@ export const calculateSpotLightContribution = Fn( ( [
|
|
|
711
713
|
const rayOffset = calculateRayOffset( hitPoint, normal, material );
|
|
712
714
|
const rayOrigin = hitPoint.add( rayOffset );
|
|
713
715
|
|
|
714
|
-
const visibility = traceShadowRayFn( rayOrigin, lightDir, distance.
|
|
716
|
+
const visibility = traceShadowRayFn( rayOrigin, lightDir, distance.mul( 0.999 ), rngState );
|
|
715
717
|
|
|
716
718
|
If( visibility.greaterThan( 0.0 ), () => {
|
|
717
719
|
|
|
@@ -71,6 +71,7 @@ import {
|
|
|
71
71
|
calculatePointLightImportance,
|
|
72
72
|
calculateSpotLightImportance,
|
|
73
73
|
traceShadowRay,
|
|
74
|
+
calculateRayOffset,
|
|
74
75
|
} from './LightsDirect.js';
|
|
75
76
|
|
|
76
77
|
import { traverseBVHShadow } from './BVHTraversal.js';
|
|
@@ -940,7 +941,7 @@ export const calculateDirectLightingUnified = Fn( ( [
|
|
|
940
941
|
] ) => {
|
|
941
942
|
|
|
942
943
|
const totalContribution = vec3( 0.0 ).toVar();
|
|
943
|
-
const rayOrigin = hitPoint.add(
|
|
944
|
+
const rayOrigin = hitPoint.add( calculateRayOffset( hitPoint, hitNormal, material ) ).toVar();
|
|
944
945
|
|
|
945
946
|
// Early exit for highly emissive surfaces
|
|
946
947
|
If( material.emissiveIntensity.lessThanEqual( 10.0 ), () => {
|
|
@@ -1041,7 +1042,7 @@ export const calculateDirectLightingUnified = Fn( ( [
|
|
|
1041
1042
|
|
|
1042
1043
|
If( NoL.greaterThan( 0.0 ).and( lightImportance.mul( NoL ).greaterThan( importanceThreshold ) ).and( isDirectionValid( { direction: lightSample.direction, surfaceNormal: hitNormal } ) ), () => {
|
|
1043
1044
|
|
|
1044
|
-
const shadowDistance = min( lightSample.distance.
|
|
1045
|
+
const shadowDistance = min( lightSample.distance.mul( 0.999 ), float( 1000.0 ) ).toVar();
|
|
1045
1046
|
const visibility = traceShadowRay(
|
|
1046
1047
|
rayOrigin, lightSample.direction, shadowDistance, rngState,
|
|
1047
1048
|
traverseBVHShadow,
|
|
@@ -880,7 +880,8 @@ export const Trace = Fn( ( [
|
|
|
880
880
|
// For transmission: offset along the old ray direction to push through the surface
|
|
881
881
|
const reflectOffsetDir = select( interaction.entering, N, N.negate() );
|
|
882
882
|
const offsetDir = select( interaction.didReflect, reflectOffsetDir, rayDirection );
|
|
883
|
-
|
|
883
|
+
const bounceEps = max( float( 1e-4 ), length( hitInfo.hitPoint ).mul( 1e-6 ) );
|
|
884
|
+
rayOrigin.assign( hitInfo.hitPoint.add( offsetDir.mul( bounceEps ) ) );
|
|
884
885
|
rayDirection.assign( interaction.direction );
|
|
885
886
|
|
|
886
887
|
stateIsPrimaryRay.assign( tslBool( false ) );
|
|
@@ -1054,7 +1055,7 @@ export const Trace = Fn( ( [
|
|
|
1054
1055
|
|
|
1055
1056
|
const rayOffset = calculateRayOffset( hitInfo.hitPoint, N, material );
|
|
1056
1057
|
const rayOrigin = hitInfo.hitPoint.add( rayOffset );
|
|
1057
|
-
const shadowDist = emissiveSample.distance.
|
|
1058
|
+
const shadowDist = emissiveSample.distance.mul( 0.999 );
|
|
1058
1059
|
const visibility = traceShadowRayWrapped( rayOrigin, emissiveSample.direction, shadowDist, rngState );
|
|
1059
1060
|
|
|
1060
1061
|
If( visibility.greaterThan( 0.0 ), () => {
|
|
@@ -1137,7 +1138,7 @@ export const Trace = Fn( ( [
|
|
|
1137
1138
|
throughput.mulAssign( indirectResult.throughput );
|
|
1138
1139
|
|
|
1139
1140
|
// Prepare for next bounce
|
|
1140
|
-
rayOrigin.assign( hitInfo.hitPoint.add(
|
|
1141
|
+
rayOrigin.assign( hitInfo.hitPoint.add( calculateRayOffset( hitInfo.hitPoint, N, material ) ) );
|
|
1141
1142
|
rayDirection.assign( indirectResult.direction );
|
|
1142
1143
|
prevBouncePdf.assign( indirectResult.combinedPdf );
|
|
1143
1144
|
|
|
@@ -312,7 +312,7 @@ export class EnvironmentManager {
|
|
|
312
312
|
const startTime = performance.now();
|
|
313
313
|
const textureForCDF = this.scene.environment;
|
|
314
314
|
|
|
315
|
-
if ( ! textureForCDF.image
|
|
315
|
+
if ( ! textureForCDF.image ) {
|
|
316
316
|
|
|
317
317
|
this._updateCDFStorageBuffers();
|
|
318
318
|
this.uniforms.set( 'envTotalSum', 0.0 );
|