three-gpu-pathtracer 0.0.23 → 0.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-gpu-pathtracer",
3
- "version": "0.0.23",
3
+ "version": "0.0.24",
4
4
  "description": "Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.",
5
5
  "module": "src/index.js",
6
6
  "main": "build/index.umd.cjs",
@@ -30,35 +30,35 @@
30
30
  "tracer"
31
31
  ],
32
32
  "devDependencies": {
33
- "@lookingglass/webxr": "^0.3.1",
33
+ "@lookingglass/webxr": "^0.6.0",
34
34
  "@monogrid/gainmap-js": "^3.0.5",
35
- "@types/node": "^20.12.7",
36
- "@types/three": "^0.163.0",
37
- "@typescript-eslint/parser": "^6.21.0",
35
+ "@types/node": "^24.3.1",
36
+ "@types/three": "^0.181.0",
37
+ "@typescript-eslint/eslint-plugin": "^8.40.0",
38
38
  "canvas-capture": "^2.0.5",
39
- "eslint": "^7.32.0",
39
+ "eslint": "^8.56.0",
40
40
  "eslint-config-mdcs": "^5.0.0",
41
41
  "node-fetch": "^3.2.9",
42
- "parcel": "^2.12.0",
43
42
  "pixelmatch": "^5.3.0",
44
43
  "pngjs": "^6.0.0",
45
44
  "process": "^0.11.10",
46
45
  "puppeteer": "^15.4.0",
47
46
  "rollup": "^2.70.0",
48
47
  "simple-git": "^3.10.0",
49
- "three": "^0.163.0",
50
- "three-mesh-bvh": "^0.7.4",
51
- "typescript": "5.3.3",
48
+ "three": "^0.181.1",
49
+ "three-mesh-bvh": "^0.9.5",
50
+ "typescript": "^5.9.2",
51
+ "vite": "^6.2.2",
52
52
  "yargs": "^17.5.1"
53
53
  },
54
54
  "peerDependencies": {
55
- "three": ">=0.151.0",
55
+ "three": ">=0.180.0",
56
56
  "three-mesh-bvh": ">=0.7.4",
57
57
  "xatlas-web": "^0.1.0"
58
58
  },
59
59
  "scripts": {
60
- "start": "cd example && parcel serve ./*.html --dist-dir ./dev-bundle/ --no-cache --no-hmr",
61
- "build-examples": "cd example && parcel build ./*.html --dist-dir ./bundle/ --public-url . --no-cache --no-content-hash",
60
+ "start": "vite --config ./vite.config.js",
61
+ "build-examples": "vite build --config ./vite.config.js",
62
62
  "update-screenshots": "node ./scripts/push-screenshots.js",
63
63
  "screenshot-diff": "node ./scripts/regression-test.js",
64
64
  "build": "rollup -c",
@@ -95,6 +95,7 @@ export class PathTracingSceneGenerator {
95
95
  this._bvhWorker = null;
96
96
  this._pendingGenerate = null;
97
97
  this._buildAsync = false;
98
+ this._materialUuids = null;
98
99
 
99
100
  }
100
101
 
@@ -176,12 +177,29 @@ export class PathTracingSceneGenerator {
176
177
  // generate the geometry
177
178
  const result = staticGeometryGenerator.generate( geometry );
178
179
  const materials = result.materials;
180
+ let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== length;
181
+ if ( ! needsMaterialIndexUpdate ) {
182
+
183
+ for ( let i = 0, length = materials.length; i < length; i ++ ) {
184
+
185
+ const material = materials[ i ];
186
+ if ( material.uuid !== this._materialUuids[ i ] ) {
187
+
188
+ needsMaterialIndexUpdate = true;
189
+ break;
190
+
191
+ }
192
+
193
+ }
194
+
195
+ }
196
+
179
197
  const textures = getTextures( materials );
180
198
  const { lights, iesTextures } = getLights( objects );
181
-
182
- if ( result.changeType !== NO_CHANGE ) {
199
+ if ( needsMaterialIndexUpdate ) {
183
200
 
184
201
  updateMaterialIndexAttribute( geometry, materials, materials );
202
+ this._materialUuids = materials.map( material => material.uuid );
185
203
 
186
204
  }
187
205
 
@@ -225,6 +243,7 @@ export class PathTracingSceneGenerator {
225
243
  return {
226
244
  bvhChanged: result.changeType !== NO_CHANGE,
227
245
  bvh: this.bvh,
246
+ needsMaterialIndexUpdate,
228
247
  lights,
229
248
  iesTextures,
230
249
  geometry,
@@ -306,7 +306,7 @@ export class WebGLPathTracer {
306
306
  }
307
307
 
308
308
  // update scene environment
309
- material.environmentIntensity = scene.environmentIntensity ?? 1;
309
+ material.environmentIntensity = scene.environment !== null ? ( scene.environmentIntensity ?? 1 ) : 0;
310
310
  material.environmentRotation.makeRotationFromEuler( scene.environmentRotation ).invert();
311
311
  if ( this._previousEnvironment !== scene.environment ) {
312
312
 
@@ -326,10 +326,6 @@ export class WebGLPathTracer {
326
326
 
327
327
  }
328
328
 
329
- } else {
330
-
331
- material.environmentIntensity = 0;
332
-
333
329
  }
334
330
 
335
331
  }
@@ -347,6 +343,7 @@ export class WebGLPathTracer {
347
343
  geometry,
348
344
  bvh,
349
345
  bvhChanged,
346
+ needsMaterialIndexUpdate,
350
347
  } = results;
351
348
 
352
349
  this._materials = materials;
@@ -364,6 +361,10 @@ export class WebGLPathTracer {
364
361
  geometry.attributes.color,
365
362
  );
366
363
 
364
+ }
365
+
366
+ if ( needsMaterialIndexUpdate ) {
367
+
367
368
  material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
368
369
 
369
370
  }
@@ -494,8 +495,8 @@ export class WebGLPathTracer {
494
495
 
495
496
  dispose() {
496
497
 
497
- this._renderQuad.dispose();
498
- this._renderQuad.material.dispose();
498
+ this._quad.dispose();
499
+ this._quad.material.dispose();
499
500
  this._pathTracer.dispose();
500
501
 
501
502
  }
@@ -205,7 +205,20 @@ export function mergeGeometries( geometries, options = {}, targetGeometry = new
205
205
  const attr = geometry.getAttribute( key );
206
206
  if ( ! skip ) {
207
207
 
208
- copyAttributeContents( attr, targetAttribute, offset );
208
+ if ( key === 'color' && targetAttribute.itemSize !== attr.itemSize ) {
209
+
210
+ // make sure the color attribute is aligned with itemSize 3 to 4
211
+ for ( let index = offset, l = attr.count; index < l; index ++ ) {
212
+
213
+ attr.setXYZW( index, targetAttribute.getX( index ), targetAttribute.getY( index ), targetAttribute.getZ( index ), 1.0 );
214
+
215
+ }
216
+
217
+ } else {
218
+
219
+ copyAttributeContents( attr, targetAttribute, offset );
220
+
221
+ }
209
222
 
210
223
  }
211
224
 
package/src/index.d.ts CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  Scene,
22
22
  PMREMGenerator
23
23
  } from 'three';
24
- import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass';
24
+ import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
25
25
  import { MeshBVH, MeshBVHOptions } from 'three-mesh-bvh';
26
26
 
27
27
  // three.js type augmentation
@@ -57,6 +57,7 @@ export interface PathTracingSceneGeneratorResult {
57
57
  lights: Array<Light>;
58
58
  iesTextures: Array<DataTexture>;
59
59
  geometry: BufferGeometry;
60
+ needsMaterialIndexUpdate: boolean;
60
61
  materials: Array<Material>;
61
62
  textures: Array<Texture>;
62
63
  objects: Array<Object3D>;
@@ -10,7 +10,7 @@ import { PhysicalCameraUniform } from '../../uniforms/PhysicalCameraUniform.js';
10
10
  import { EquirectHdrInfoUniform } from '../../uniforms/EquirectHdrInfoUniform.js';
11
11
  import { LightsInfoUniformStruct } from '../../uniforms/LightsInfoUniformStruct.js';
12
12
  import { AttributesTextureArray } from '../../uniforms/AttributesTextureArray.js';
13
- import { MaterialsTexture } from '../../uniforms/MaterialsTexture.js';
13
+ import { MaterialsTexture, MATERIAL_PIXELS } from '../../uniforms/MaterialsTexture.js';
14
14
  import { RenderTarget2DArray } from '../../uniforms/RenderTarget2DArray.js';
15
15
  import { StratifiedSamplesTexture } from '../../uniforms/StratifiedSamplesTexture.js';
16
16
  import { BlueNoiseTexture } from '../../textures/BlueNoiseTexture.js';
@@ -66,6 +66,7 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
66
66
  ATTR_TANGENT: 1,
67
67
  ATTR_UV: 2,
68
68
  ATTR_COLOR: 3,
69
+ MATERIAL_PIXELS: MATERIAL_PIXELS,
69
70
  },
70
71
 
71
72
  uniforms: {
@@ -97,7 +97,8 @@ export const attenuate_hit_function = /* glsl */`
97
97
  // alphaMap
98
98
  if ( material.alphaMap != - 1 ) {
99
99
 
100
- albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
100
+ vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
101
+ albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
101
102
 
102
103
  }
103
104
 
@@ -60,7 +60,7 @@ export const camera_util_functions = /* glsl */`
60
60
  vec3 shapeUVW= rand3( 1 );
61
61
  int blades = physicalCamera.apertureBlades;
62
62
  float anamorphicRatio = physicalCamera.anamorphicRatio;
63
- vec2 apertureSample = blades == 0 ? sampleCircle( shapeUVW.xy ) : sampleRegularPolygon( blades, shapeUVW );
63
+ vec2 apertureSample = sampleAperture( blades, shapeUVW );
64
64
  apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
65
65
 
66
66
  // rotate the aperture shape
@@ -48,7 +48,8 @@ export const get_surface_record_function = /* glsl */`
48
48
  // alphaMap
49
49
  if ( material.alphaMap != - 1 ) {
50
50
 
51
- albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
51
+ vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
52
+ albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
52
53
 
53
54
  }
54
55
 
@@ -1,6 +1,7 @@
1
1
  import { TangentSpaceNormalMap, Vector2 } from 'three';
2
2
  import { MaterialBase } from '../MaterialBase.js';
3
3
  import { MeshBVHUniformStruct, BVHShaderGLSL } from 'three-mesh-bvh';
4
+ import { MATERIAL_PIXELS } from '../../uniforms/MaterialsTexture.js';
4
5
 
5
6
  import * as StructsGLSL from '../../shader/structs/index.js';
6
7
  import * as SamplingGLSL from '../../shader/sampling/index.js';
@@ -43,6 +44,7 @@ export class AmbientOcclusionMaterial extends MaterialBase {
43
44
 
44
45
  defines: {
45
46
  SAMPLES: 10,
47
+ MATERIAL_PIXELS: MATERIAL_PIXELS,
46
48
  },
47
49
 
48
50
  uniforms: {
@@ -7,7 +7,7 @@ export const inside_fog_volume_function = /* glsl */`
7
7
  // returns whether the given material is a fog material or not
8
8
  bool isMaterialFogVolume( sampler2D materials, uint materialIndex ) {
9
9
 
10
- uint i = materialIndex * 45u;
10
+ uint i = materialIndex * uint( MATERIAL_PIXELS );
11
11
  vec4 s14 = texelFetch1D( materials, i + 14u );
12
12
  return bool( int( s14.b ) & 4 );
13
13
 
@@ -81,6 +81,7 @@ export const material_struct = /* glsl */ `
81
81
  mat3 iridescenceThicknessMapTransform;
82
82
  mat3 specularColorMapTransform;
83
83
  mat3 specularIntensityMapTransform;
84
+ mat3 alphaMapTransform;
84
85
 
85
86
  };
86
87
 
@@ -101,7 +102,7 @@ export const material_struct = /* glsl */ `
101
102
 
102
103
  Material readMaterialInfo( sampler2D tex, uint index ) {
103
104
 
104
- uint i = index * 45u;
105
+ uint i = index * uint( MATERIAL_PIXELS );
105
106
 
106
107
  vec4 s0 = texelFetch1D( tex, i + 0u );
107
108
  vec4 s1 = texelFetch1D( tex, i + 1u );
@@ -200,6 +201,7 @@ export const material_struct = /* glsl */ `
200
201
  m.iridescenceThicknessMapTransform = m.iridescenceThicknessMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 24u );
201
202
  m.specularColorMapTransform = m.specularColorMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 26u );
202
203
  m.specularIntensityMapTransform = m.specularIntensityMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 28u );
204
+ m.alphaMapTransform = m.alphaMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 30u );
203
205
 
204
206
  return m;
205
207
 
@@ -2,7 +2,7 @@ import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, FrontSide, Bac
2
2
  import { getTextureHash } from '../core/utils/sceneUpdateUtils.js';
3
3
  import { bufferToHash } from '../utils/bufferToHash.js';
4
4
 
5
- const MATERIAL_PIXELS = 45;
5
+ export const MATERIAL_PIXELS = 47;
6
6
  const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
7
7
 
8
8
  class MaterialFeatures {
@@ -427,6 +427,9 @@ export class MaterialsTexture extends DataTexture {
427
427
  // specularIntensityMap transform 43
428
428
  index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
429
429
 
430
+ // alphaMap transform 45
431
+ index += writeTextureMatrixToArray( m, 'alphaMap', floatArray, index );
432
+
430
433
  }
431
434
 
432
435
  // check if the contents have changed