rayzee 11.7.0 → 11.9.0
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 +31 -6
- package/dist/{ArchiveImporter-DYcRXeKE.js → ArchiveImporter-BJxszU_k.js} +2353 -1356
- package/dist/{BidirectionalIntegrator-BvjRpbTP.js → BidirectionalIntegrator-DWg66vAd.js} +302 -301
- package/dist/{BufferLayout-xPRH9jYD.js → BufferLayout-Bzgccg1o.js} +1 -0
- package/dist/{ColorManagement-oeEk7oSu.js → ColorManagement-B_HjAiy2.js} +1 -1
- package/dist/{EngineIssues-CIZnXHsF.js → EngineIssues-CfJiBaNj.js} +19 -8
- package/dist/{NeuralRetouch-ClaMiKYg.js → NeuralRetouch-BD9E-Yht.js} +2 -2
- package/dist/{NeuralSuperRes-WNEXun9s.js → NeuralSuperRes-C8Mf3tJX.js} +2 -2
- package/dist/{PathTracer-B9wZPPVL.js → PathTracer-DeE9UJ1n.js} +3530 -3402
- package/dist/{PhysicalSky-DcjItqKi.js → PhysicalSky-cKy75-oR.js} +45 -45
- package/dist/{RayzeeRenderer-p-NeE6E2.js → RayzeeRenderer-CzLyBA3G.js} +378 -374
- package/dist/SceneMetadata-C17UfOEp.js +183 -0
- package/dist/{SolarLimb-bZE6y63S.js → SolarLimb-DRYy8tln.js} +184 -172
- package/dist/{ToneMapGPU-sAs8wdgI.js → ToneMapGPU-4GPwoG_c.js} +13 -6
- package/dist/addons/archives.es.js +1 -1
- package/dist/addons/bidirectional.es.js +1 -1
- package/dist/addons/color.es.js +1 -1
- package/dist/addons/physical-sky.es.js +1 -1
- package/dist/addons/storage.es.js +1 -1
- package/dist/{openStorage-Fe9BoS1_.js → openStorage-CdyVjmps.js} +1 -1
- package/dist/rayzee-core.es.js +7 -7
- package/dist/rayzee.es.js +821 -794
- package/dist/rayzee.umd.js +112 -103
- package/dist/{sceneCachePolicy-B9w3BnaP.js → sceneCachePolicy-ywbGKHD3.js} +9 -6
- package/package.json +1 -1
- package/src/EngineDefaults.js +1 -0
- package/src/EngineIssues.js +21 -6
- package/src/Passes/AIUpscaler.js +4 -0
- package/src/Passes/OIDNDenoiser.js +8 -6
- package/src/Passes/OIDNTemporalHistory.js +1 -1
- package/src/PathTracerApp.js +10 -1
- package/src/Processor/ArchiveImporter.js +106 -27
- package/src/Processor/AssetLoader.js +22 -0
- package/src/Processor/BufferLayout.js +3 -3
- package/src/Processor/GeometryExtractor.js +12 -4
- package/src/Processor/LightSerializer.js +6 -2
- package/src/Processor/MaterialPacking.js +2 -2
- package/src/Processor/PBRT/PBRTMaterials.js +49 -13
- package/src/Processor/PBRT/PBRTParser.js +144 -22
- package/src/Processor/PBRT/PBRTSceneBuilder.js +287 -67
- package/src/Processor/PBRT/PBRTTextureBake.js +191 -9
- package/src/Processor/PBRT/index.js +19 -4
- package/src/Processor/PlatformImageLoader.js +9 -0
- package/src/Processor/SceneProcessor.js +42 -26
- package/src/Processor/TextureCreator.js +44 -4
- package/src/Processor/ToneMapCPU.js +34 -5
- package/src/Processor/ToneMapGPU.js +15 -9
- package/src/Processor/USD/USDScene.js +981 -17
- package/src/RayzeeRenderer.js +85 -28
- package/src/Stages/AutoExposure.js +21 -8
- package/src/Stages/Compositor.js +39 -1
- package/src/Stages/DenoiserSettings.js +0 -4
- package/src/Stages/LocalExposure.js +44 -18
- package/src/Stages/NRD.js +53 -24
- package/src/Stages/NormalDepth.js +12 -6
- package/src/Stages/PathTracer.js +27 -1
- package/src/Stages/PathTracerStage.js +14 -2
- package/src/Storage/SceneGraphCodec.js +6 -3
- package/src/TSL/BVHTraversal.js +33 -20
- package/src/TSL/CameraRay.js +12 -1
- package/src/TSL/Common.js +25 -8
- package/src/TSL/DebugKernel.js +3 -2
- package/src/TSL/Displacement.js +66 -113
- package/src/TSL/FinalWriteKernel.js +4 -7
- package/src/TSL/GenerateKernel.js +6 -2
- package/src/TSL/LightSplatKernel.js +7 -4
- package/src/TSL/LightsCore.js +6 -2
- package/src/TSL/LightsDirect.js +33 -11
- package/src/TSL/LightsSampling.js +45 -12
- package/src/TSL/SceneResources.js +19 -0
- package/src/TSL/ShadeKernel.js +3 -4
- package/src/TSL/Struct.js +1 -0
- package/src/integrators/BidirectionalIntegrator.js +1 -0
- package/src/managers/CameraManager.js +9 -0
- package/src/managers/DenoisingManager.js +1 -0
- package/src/managers/InteractionManager.js +6 -0
- package/src/managers/MaterialDataManager.js +11 -0
- package/src/managers/UniformManager.js +3 -1
- package/dist/SceneMetadata-D2Sh-0e-.js +0 -110
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { MeshPhysicalMaterial, Color, DoubleSide } from 'three';
|
|
12
12
|
import { namedScattering, dipoleReflectance, albedoForReflectance } from './PBRTScattering.js';
|
|
13
|
+
import { approximated, param } from './PBRTParser.js';
|
|
13
14
|
|
|
14
15
|
// Normal-incidence reflectance approximations for pbrt's named conductor spectra.
|
|
15
16
|
const METAL_ALBEDO = {
|
|
@@ -54,21 +55,37 @@ function blackbodyToRGB( kelvin ) {
|
|
|
54
55
|
|
|
55
56
|
export function pFloat( params, name, dflt ) {
|
|
56
57
|
|
|
57
|
-
const p = params
|
|
58
|
+
const p = param( params, name );
|
|
59
|
+
if ( p && p.type !== 'float' && p.type !== 'integer' ) approximated( params, name );
|
|
58
60
|
return p && typeof p.value[ 0 ] === 'number' ? p.value[ 0 ] : dflt;
|
|
59
61
|
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/** An index of refraction: a sampled spectrum ( λ value pairs ) is read at 550 nm, linearly between its samples. */
|
|
65
|
+
export function pEta( params, name, dflt ) {
|
|
66
|
+
|
|
67
|
+
const p = param( params, name );
|
|
68
|
+
if ( p?.type !== 'spectrum' || typeof p.value[ 0 ] !== 'number' ) return pFloat( params, name, dflt );
|
|
69
|
+
approximated( params, name );
|
|
70
|
+
const v = p.value;
|
|
71
|
+
if ( v.length < 2 ) return dflt;
|
|
72
|
+
let i = 2;
|
|
73
|
+
while ( i < v.length - 1 && v[ i ] < 550 ) i += 2;
|
|
74
|
+
if ( i >= v.length - 1 || v[ i - 2 ] >= 550 ) return v[ i >= v.length - 1 ? i - 1 : 1 ];
|
|
75
|
+
return v[ i - 1 ] + ( v[ i + 1 ] - v[ i - 1 ] ) * ( 550 - v[ i - 2 ] ) / ( v[ i ] - v[ i - 2 ] );
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
export function pString( params, name, dflt ) {
|
|
63
80
|
|
|
64
|
-
const p = params
|
|
81
|
+
const p = param( params, name );
|
|
65
82
|
return p && typeof p.value[ 0 ] === 'string' ? p.value[ 0 ] : dflt;
|
|
66
83
|
|
|
67
84
|
}
|
|
68
85
|
|
|
69
86
|
export function pBool( params, name, dflt ) {
|
|
70
87
|
|
|
71
|
-
const v = params
|
|
88
|
+
const v = param( params, name )?.value?.[ 0 ];
|
|
72
89
|
return v === undefined ? dflt : v === true || v === 'true';
|
|
73
90
|
|
|
74
91
|
}
|
|
@@ -80,7 +97,7 @@ export function pBool( params, name, dflt ) {
|
|
|
80
97
|
*/
|
|
81
98
|
export async function resolveSpectrum( params, name, ctx, dfltRGB = null ) {
|
|
82
99
|
|
|
83
|
-
const p = params
|
|
100
|
+
const p = param( params, name );
|
|
84
101
|
if ( ! p ) return { rgb: dfltRGB, texture: null };
|
|
85
102
|
|
|
86
103
|
// Reference to a named texture.
|
|
@@ -91,6 +108,7 @@ export async function resolveSpectrum( params, name, ctx, dfltRGB = null ) {
|
|
|
91
108
|
if ( tex && tex.texture ) return { rgb: tex.constant ?? null, texture: tex.texture };
|
|
92
109
|
if ( tex && tex.constant ) return { rgb: tex.constant, texture: null };
|
|
93
110
|
ctx.warn( `texture "${texName}" could not be resolved` );
|
|
111
|
+
approximated( params, name );
|
|
94
112
|
return { rgb: dfltRGB, texture: null };
|
|
95
113
|
|
|
96
114
|
}
|
|
@@ -110,6 +128,7 @@ export async function resolveSpectrum( params, name, ctx, dfltRGB = null ) {
|
|
|
110
128
|
|
|
111
129
|
if ( p.type === 'blackbody' ) {
|
|
112
130
|
|
|
131
|
+
approximated( params, name );
|
|
113
132
|
return { rgb: blackbodyToRGB( p.value[ 0 ] ), texture: null };
|
|
114
133
|
|
|
115
134
|
}
|
|
@@ -117,6 +136,7 @@ export async function resolveSpectrum( params, name, ctx, dfltRGB = null ) {
|
|
|
117
136
|
if ( p.type === 'spectrum' ) {
|
|
118
137
|
|
|
119
138
|
// Named spectrum (e.g. "metal-Au-eta") or sampled [lambda val ...].
|
|
139
|
+
approximated( params, name );
|
|
120
140
|
if ( typeof p.value[ 0 ] === 'string' ) {
|
|
121
141
|
|
|
122
142
|
const key = namedMetalKey( p.value[ 0 ] );
|
|
@@ -139,6 +159,7 @@ export async function resolveSpectrum( params, name, ctx, dfltRGB = null ) {
|
|
|
139
159
|
|
|
140
160
|
}
|
|
141
161
|
|
|
162
|
+
approximated( params, name );
|
|
142
163
|
return { rgb: dfltRGB, texture: null };
|
|
143
164
|
|
|
144
165
|
}
|
|
@@ -155,9 +176,10 @@ function namedMetalKey( s ) {
|
|
|
155
176
|
// A float parameter's value, or a float texture's mean (`ctx.floatTextureMean`); null when absent or unreadable.
|
|
156
177
|
async function floatOrMean( params, name, ctx ) {
|
|
157
178
|
|
|
158
|
-
const p = params
|
|
179
|
+
const p = param( params, name );
|
|
159
180
|
if ( ! p ) return null;
|
|
160
181
|
if ( typeof p.value[ 0 ] === 'number' ) return p.value[ 0 ];
|
|
182
|
+
approximated( params, name );
|
|
161
183
|
if ( p.type === 'texture' ) return ( await ctx.floatTextureMean?.( p.value[ 0 ] ) ) ?? null;
|
|
162
184
|
return null;
|
|
163
185
|
|
|
@@ -171,7 +193,7 @@ async function floatOrMean( params, name, ctx ) {
|
|
|
171
193
|
*/
|
|
172
194
|
const remapsRoughness = ( params ) => {
|
|
173
195
|
|
|
174
|
-
const remap = params
|
|
196
|
+
const remap = param( params, 'remaproughness' )?.value?.[ 0 ];
|
|
175
197
|
return remap !== false && remap !== 'false';
|
|
176
198
|
|
|
177
199
|
};
|
|
@@ -225,8 +247,14 @@ async function applyRoughness( mat, target, params, dflt, ctx, prefix = '' ) {
|
|
|
225
247
|
// A spectrum parameter as one RGB; a texture counts as its mean (`ctx.textureMeanRGB`).
|
|
226
248
|
async function spectrumMean( params, key, ctx, dflt ) {
|
|
227
249
|
|
|
228
|
-
const p = params
|
|
229
|
-
if ( p?.type === 'texture' )
|
|
250
|
+
const p = param( params, key );
|
|
251
|
+
if ( p?.type === 'texture' ) {
|
|
252
|
+
|
|
253
|
+
approximated( params, key );
|
|
254
|
+
return ( await ctx.textureMeanRGB?.( p.value[ 0 ] ) ) ?? dflt;
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
230
258
|
return ( await resolveSpectrum( params, key, ctx, dflt ) ).rgb ?? dflt;
|
|
231
259
|
|
|
232
260
|
}
|
|
@@ -243,7 +271,7 @@ const SUBSURFACE_SIGMA_S = [ 2.55, 3.21, 3.77 ];
|
|
|
243
271
|
*/
|
|
244
272
|
async function applySubsurface( mat, params, ctx ) {
|
|
245
273
|
|
|
246
|
-
const eta =
|
|
274
|
+
const eta = pEta( params, 'eta', 1.33 );
|
|
247
275
|
const scale = pFloat( params, 'scale', 1 );
|
|
248
276
|
const scaled = ( rgb ) => rgb.map( ( v ) => Math.max( 0, v * scale ) );
|
|
249
277
|
let g = pFloat( params, 'g', 0 );
|
|
@@ -353,6 +381,7 @@ export async function buildMaterial( def, ctx ) {
|
|
|
353
381
|
|
|
354
382
|
const type = def?.type || 'diffuse';
|
|
355
383
|
const params = def?.params || {};
|
|
384
|
+
ctx.trackParams?.( params, `Material ${type}`, 'type' );
|
|
356
385
|
const mat = new MeshPhysicalMaterial( { side: DoubleSide, roughness: 1, metalness: 0 } );
|
|
357
386
|
|
|
358
387
|
const setColor = ( rgb ) => {
|
|
@@ -393,7 +422,8 @@ export async function buildMaterial( def, ctx ) {
|
|
|
393
422
|
case 'metal': {
|
|
394
423
|
|
|
395
424
|
await applyConductorColor( mat, params, ctx, '', applyAlbedo, setColor );
|
|
396
|
-
|
|
425
|
+
// pbrt's roughness defaults to 0, a mirror.
|
|
426
|
+
await applyRoughness( mat, 'roughness', params, 0, ctx );
|
|
397
427
|
break;
|
|
398
428
|
|
|
399
429
|
}
|
|
@@ -415,7 +445,7 @@ export async function buildMaterial( def, ctx ) {
|
|
|
415
445
|
mat.transmission = 1;
|
|
416
446
|
mat.metalness = 0;
|
|
417
447
|
mat.color.setRGB( 1, 1, 1 );
|
|
418
|
-
mat.ior =
|
|
448
|
+
mat.ior = pEta( params, 'eta', 1.5 );
|
|
419
449
|
await applyRoughness( mat, 'roughness', params, 0, ctx );
|
|
420
450
|
mat.thickness = type === 'thindielectric' ? 0 : pFloat( params, 'thickness', 0 );
|
|
421
451
|
break;
|
|
@@ -446,7 +476,13 @@ export async function buildMaterial( def, ctx ) {
|
|
|
446
476
|
const refl = await resolveSpectrum( params, 'reflectance', ctx, [ 0.25, 0.25, 0.25 ] );
|
|
447
477
|
const base = ( v ) => Math.min( 1, unit( v ) / ( 1 - dt ) );
|
|
448
478
|
applyAlbedo( { texture: refl.texture, rgb: refl.rgb ? refl.rgb.map( base ) : ( refl.texture ? [ 1, 1, 1 ].map( base ) : null ) } );
|
|
449
|
-
if ( trans.texture )
|
|
479
|
+
if ( trans.texture ) {
|
|
480
|
+
|
|
481
|
+
ctx.warn( 'diffusetransmission: a textured "transmittance" is not supported — using 0.5' );
|
|
482
|
+
approximated( params, 'transmittance' );
|
|
483
|
+
|
|
484
|
+
}
|
|
485
|
+
|
|
450
486
|
mat.diffuseTransmission = dt;
|
|
451
487
|
mat.diffuseTransmissionColor = new Color().setRGB( ...T.map( ( v ) => ( dt > 0 ? Math.min( 1, v / dt ) : 1 ) ) );
|
|
452
488
|
mat.roughness = 1;
|
|
@@ -476,7 +512,7 @@ export async function buildMaterial( def, ctx ) {
|
|
|
476
512
|
// — physically loose but visually faithful, and crucially silent on success
|
|
477
513
|
// instead of warning per shape. Recursive: mix-in-mix terminates as the
|
|
478
514
|
// chain bottoms out at a non-mix.
|
|
479
|
-
const matNames = params
|
|
515
|
+
const matNames = param( params, 'materials' )?.value || [];
|
|
480
516
|
let t = Math.max( 0, Math.min( 1, pFloat( params, 'amount', 0.5 ) ) );
|
|
481
517
|
const defA = matNames[ 0 ] ? ctx.namedMaterials?.get( matNames[ 0 ] ) : null;
|
|
482
518
|
const defB = matNames[ 1 ] ? ctx.namedMaterials?.get( matNames[ 1 ] ) : null;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* film: { xresolution, yresolution, filename } | null,
|
|
15
15
|
* camera: { type, params, cameraToWorld:number[16] } | null,
|
|
16
16
|
* namedMaterials: Map<name, { type, params }>,
|
|
17
|
-
* namedTextures: Map<name, { dataType, class, params }>,
|
|
17
|
+
* namedTextures: Map<name, { dataType, class, params, ctm? }>, (ctm: where a position mapping was declared)
|
|
18
18
|
* shapes: [ { type, params, ctm, ctmEnd?, material, areaLight, reverseOrientation } ],
|
|
19
19
|
* lights: [ { type, params, ctm } ],
|
|
20
20
|
* instances: Map<name, { name, count, matrices, matricesEnd? }>,
|
|
@@ -68,6 +68,101 @@ const NUMERIC_STORAGE = {
|
|
|
68
68
|
rgb: Float32Array
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
// The directive `ParamUsage.translate` is in, and each directive open until `ParamUsage.finish`.
|
|
72
|
+
let current = null;
|
|
73
|
+
const scopes = new Map();
|
|
74
|
+
|
|
75
|
+
/** A directive's parameter, counted as used: every translator reads through this, as pbrt-v4's lookups mark theirs. */
|
|
76
|
+
export function param( params, name ) {
|
|
77
|
+
|
|
78
|
+
if ( current !== null && current.params === params ) current.read.push( name );
|
|
79
|
+
else if ( scopes.size !== 0 ) scopes.get( params )?.read.push( name );
|
|
80
|
+
return params?.[ name ];
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A parameter read but not honoured exactly: a texture's mean where the engine takes one value,
|
|
86
|
+
* a default for a type it cannot read.
|
|
87
|
+
*/
|
|
88
|
+
export function approximated( params, name ) {
|
|
89
|
+
|
|
90
|
+
const scope = current !== null && current.params === params ? current : scopes.get( params );
|
|
91
|
+
if ( scope ) ( scope.approximated ??= new Set() ).add( name );
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* What one load did not honour, as pbrt's ReportUnused: each translated directive's parameters that nothing looked up,
|
|
97
|
+
* or that were approximated, counted per `directive type: name`. Holds nothing per directive once it is accounted for.
|
|
98
|
+
*/
|
|
99
|
+
export class ParamUsage {
|
|
100
|
+
|
|
101
|
+
constructor() {
|
|
102
|
+
|
|
103
|
+
this.unused = new Map();
|
|
104
|
+
this.approximated = new Map();
|
|
105
|
+
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Runs `read`, which looks up every parameter it uses before it returns, and accounts for the directive at once.
|
|
110
|
+
* `consumed` names one read before, where nothing counted it. A directive left open is accounted for by `finish`.
|
|
111
|
+
*/
|
|
112
|
+
translate( params, label, read, consumed = null ) {
|
|
113
|
+
|
|
114
|
+
if ( scopes.has( params ) ) return read();
|
|
115
|
+
const outer = current;
|
|
116
|
+
const scope = current = { params, label, approximated: null, read: [ consumed ] };
|
|
117
|
+
try {
|
|
118
|
+
|
|
119
|
+
return read();
|
|
120
|
+
|
|
121
|
+
} finally {
|
|
122
|
+
|
|
123
|
+
current = outer;
|
|
124
|
+
for ( const name in params ) this._count( scope, name, ! scope.read.includes( name ) );
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Accounts for a directive read across awaits, from here to `finish`. */
|
|
131
|
+
open( params, label, consumed = null ) {
|
|
132
|
+
|
|
133
|
+
if ( params && ! scopes.has( params ) ) scopes.set( params, { usage: this, label, approximated: null, read: [ consumed ] } );
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** @returns {{unused: Object<string, number>, approximated: Object<string, number>}} */
|
|
138
|
+
finish() {
|
|
139
|
+
|
|
140
|
+
for ( const [ params, scope ] of scopes ) {
|
|
141
|
+
|
|
142
|
+
if ( scope.usage !== this ) continue;
|
|
143
|
+
scopes.delete( params );
|
|
144
|
+
for ( const name in params ) this._count( scope, name, ! scope.read.includes( name ) );
|
|
145
|
+
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const flat = ( counts ) => [ ...counts ].flatMap( ( [ label, byName ] ) => [ ...byName ].map( ( [ name, n ] ) => [ `${label}: ${name}`, n ] ) );
|
|
149
|
+
const sorted = ( counts ) => Object.fromEntries( flat( counts ).sort( ( a, b ) => ( a[ 0 ] < b[ 0 ] ? - 1 : 1 ) ) );
|
|
150
|
+
return { unused: sorted( this.unused ), approximated: sorted( this.approximated ) };
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_count( scope, name, unused ) {
|
|
155
|
+
|
|
156
|
+
const counts = scope.approximated?.has( name ) ? this.approximated : unused ? this.unused : null;
|
|
157
|
+
if ( ! counts ) return;
|
|
158
|
+
let byName = counts.get( scope.label );
|
|
159
|
+
if ( ! byName ) counts.set( scope.label, byName = new Map() );
|
|
160
|
+
byName.set( name, ( byName.get( name ) ?? 0 ) + 1 );
|
|
161
|
+
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
}
|
|
165
|
+
|
|
71
166
|
export class PBRTParser {
|
|
72
167
|
|
|
73
168
|
/**
|
|
@@ -90,6 +185,7 @@ export class PBRTParser {
|
|
|
90
185
|
// is the parse itself, so a limit applied later saves nothing.
|
|
91
186
|
this.maxPlacements = opts.maxPlacements ?? Infinity;
|
|
92
187
|
this.instanceIncludes = opts.instanceIncludes !== false;
|
|
188
|
+
this.usage = opts.usage ?? null;
|
|
93
189
|
this._includes = new Map();
|
|
94
190
|
this._stateIds = new WeakMap();
|
|
95
191
|
this._nextStateId = 1;
|
|
@@ -598,14 +694,18 @@ export class PBRTParser {
|
|
|
598
694
|
|
|
599
695
|
case 'Film': {
|
|
600
696
|
|
|
601
|
-
this._expectString( 'Film type' );
|
|
697
|
+
const type = this._expectString( 'Film type' );
|
|
602
698
|
const params = this._parseParams();
|
|
603
|
-
this.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
699
|
+
this._translate( params, `${name} ${type}`, () => {
|
|
700
|
+
|
|
701
|
+
this.ir.film = {
|
|
702
|
+
xresolution: this._num( param( params, 'xresolution' ), 1280 ),
|
|
703
|
+
yresolution: this._num( param( params, 'yresolution' ), 720 ),
|
|
704
|
+
resolutionGiven: Boolean( params.xresolution || params.yresolution ),
|
|
705
|
+
filename: this._str( param( params, 'filename' ), null )
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
} );
|
|
609
709
|
break;
|
|
610
710
|
|
|
611
711
|
}
|
|
@@ -613,18 +713,26 @@ export class PBRTParser {
|
|
|
613
713
|
// What the scene asks the renderer for; reported, not applied (PBRTSceneBuilder renderRequest).
|
|
614
714
|
case 'Integrator': {
|
|
615
715
|
|
|
616
|
-
this._expectString( 'Integrator type' );
|
|
716
|
+
const type = this._expectString( 'Integrator type' );
|
|
617
717
|
const params = this._parseParams();
|
|
618
|
-
|
|
718
|
+
this._translate( params, `${name} ${type}`, () => {
|
|
719
|
+
|
|
720
|
+
if ( params.maxdepth ) this.ir.integrator = { maxdepth: this._num( param( params, 'maxdepth' ), 5 ) };
|
|
721
|
+
|
|
722
|
+
} );
|
|
619
723
|
break;
|
|
620
724
|
|
|
621
725
|
}
|
|
622
726
|
|
|
623
727
|
case 'Sampler': {
|
|
624
728
|
|
|
625
|
-
this._expectString( 'Sampler type' );
|
|
729
|
+
const type = this._expectString( 'Sampler type' );
|
|
626
730
|
const params = this._parseParams();
|
|
627
|
-
|
|
731
|
+
this._translate( params, `${name} ${type}`, () => {
|
|
732
|
+
|
|
733
|
+
if ( params.pixelsamples ) this.ir.sampler = { pixelsamples: this._num( param( params, 'pixelsamples' ), 16 ) };
|
|
734
|
+
|
|
735
|
+
} );
|
|
628
736
|
break;
|
|
629
737
|
|
|
630
738
|
}
|
|
@@ -633,11 +741,17 @@ export class PBRTParser {
|
|
|
633
741
|
case 'PixelFilter':
|
|
634
742
|
case 'Filter':
|
|
635
743
|
case 'Accelerator':
|
|
636
|
-
case 'ColorSpace':
|
|
637
|
-
|
|
638
|
-
this.
|
|
744
|
+
case 'ColorSpace': {
|
|
745
|
+
|
|
746
|
+
const type = this._peek()?.type === TokenType.STRING ? this._next().value : '';
|
|
747
|
+
this._translate( this._parseParams(), `${name} ${type}` );
|
|
639
748
|
break;
|
|
640
749
|
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// `Option "type name" value`: one parameter, no type before it.
|
|
753
|
+
case 'Option': this._translate( this._parseParams(), name ); break;
|
|
754
|
+
|
|
641
755
|
// ── world block ──
|
|
642
756
|
case 'WorldBegin':
|
|
643
757
|
this.ctm = M.identity();
|
|
@@ -669,7 +783,14 @@ export class PBRTParser {
|
|
|
669
783
|
case 'ReverseOrientation': this.state.reverseOrientation = ! this.state.reverseOrientation; break;
|
|
670
784
|
|
|
671
785
|
// `Attribute "target" params` — v4 default-setting; ignored for MVP.
|
|
672
|
-
case 'Attribute':
|
|
786
|
+
case 'Attribute': {
|
|
787
|
+
|
|
788
|
+
const target = this._expectString( 'Attribute target' );
|
|
789
|
+
this._translate( this._parseParams(), `${name} ${target}` );
|
|
790
|
+
break;
|
|
791
|
+
|
|
792
|
+
}
|
|
793
|
+
|
|
673
794
|
case 'ActiveTransform': {
|
|
674
795
|
|
|
675
796
|
const t = this._next();
|
|
@@ -744,7 +865,9 @@ export class PBRTParser {
|
|
|
744
865
|
const dataType = this._expectString( 'Texture data type' ); // float | spectrum
|
|
745
866
|
const texClass = this._expectString( 'Texture class' ); // imagemap | scale | ...
|
|
746
867
|
const params = this._parseParams();
|
|
747
|
-
|
|
868
|
+
const def = { dataType, class: texClass, params };
|
|
869
|
+
if ( this._str( params.mapping, 'uv' ) !== 'uv' ) def.ctm = this._ctmSnapshot();
|
|
870
|
+
this.ir.namedTextures.set( texName, def );
|
|
748
871
|
break;
|
|
749
872
|
|
|
750
873
|
}
|
|
@@ -839,7 +962,7 @@ export class PBRTParser {
|
|
|
839
962
|
default:
|
|
840
963
|
this._warnUnknown( name );
|
|
841
964
|
// Best effort: swallow any trailing parameter list to stay in sync.
|
|
842
|
-
this._parseParams();
|
|
965
|
+
this._translate( this._parseParams(), name );
|
|
843
966
|
break;
|
|
844
967
|
|
|
845
968
|
}
|
|
@@ -992,11 +1115,10 @@ export class PBRTParser {
|
|
|
992
1115
|
|
|
993
1116
|
}
|
|
994
1117
|
|
|
995
|
-
|
|
1118
|
+
/** Runs `read` over a directive's parameters, and counts what it leaves unread: all of them by default. */
|
|
1119
|
+
_translate( params, label, read = () => {} ) {
|
|
996
1120
|
|
|
997
|
-
|
|
998
|
-
if ( this._peek() && this._peek().type === TokenType.STRING ) this._next();
|
|
999
|
-
this._parseParams();
|
|
1121
|
+
return this.usage ? this.usage.translate( params, label, read ) : read();
|
|
1000
1122
|
|
|
1001
1123
|
}
|
|
1002
1124
|
|