rayzee 8.5.0 → 8.6.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 +60 -4
- package/dist/{DLSSNeural-BNSJ8V3z.js → DLSSNeural-BhBCBgKf.js} +5 -5
- package/dist/{DLSSSuperRes-BoEW89Cl.js → DLSSSuperRes-BCA7F_k5.js} +5 -5
- package/dist/ToneMapGPU-BzcLheoR.js +533 -0
- package/dist/rayzee.es.js +27198 -9047
- package/dist/rayzee.umd.js +255 -187
- package/package.json +1 -1
- package/src/AssetConfig.js +15 -2
- package/src/Color/BakedViews.js +134 -0
- package/src/Color/BuiltinViews.js +261 -0
- package/src/Color/ColorManagement.js +1130 -0
- package/src/Color/ColorSpaces.js +432 -0
- package/src/Color/Displays.js +19 -0
- package/src/Color/InputColorSpaces.js +243 -0
- package/src/Color/LutBake.js +371 -0
- package/src/Color/OcioRuntime.js +338 -0
- package/src/Color/OcioViews.js +419 -0
- package/src/Color/ViewTransforms.js +323 -0
- package/src/Color/WorkingMatrix.js +86 -0
- package/src/EngineDefaults.js +55 -3
- package/src/EngineIssues.js +3 -0
- package/src/Passes/AIUpscaler.js +16 -7
- package/src/PathTracerApp.js +227 -7
- package/src/Processor/AssetLoader.js +1 -2
- package/src/Processor/EmissiveTriangleBuilder.js +34 -2
- package/src/Processor/GeometryExtractor.js +151 -138
- package/src/Processor/LightSerializer.js +8 -3
- package/src/Processor/MaterialPacking.js +168 -0
- package/src/Processor/PackedRayBuffer.js +6 -2
- package/src/Processor/ProceduralSky.js +4 -0
- package/src/Processor/SceneProcessor.js +25 -1
- package/src/Processor/SimpleSky.js +8 -0
- package/src/Processor/TextureCreator.js +137 -91
- package/src/Processor/TextureReadback.js +92 -0
- package/src/Processor/ToneMapCPU.js +80 -165
- package/src/Processor/ToneMapGPU.js +122 -151
- package/src/RenderSettings.js +1 -0
- package/src/Stages/Compositor.js +11 -2
- package/src/Stages/PathTracer.js +2 -0
- package/src/Stages/PathTracerStage.js +1 -1
- package/src/TSL/Common.js +15 -0
- package/src/TSL/Debugger.js +2 -3
- package/src/TSL/EmissiveSampling.js +6 -8
- package/src/TSL/ExtendKernel.js +9 -0
- package/src/TSL/Fresnel.js +23 -1
- package/src/TSL/HitFacet.js +102 -0
- package/src/TSL/LightsDirect.js +12 -33
- package/src/TSL/LightsSampling.js +15 -7
- package/src/TSL/MaterialEvaluation.js +26 -19
- package/src/TSL/MaterialProperties.js +74 -37
- package/src/TSL/MaterialTransmission.js +2 -3
- package/src/TSL/ShadeKernel.js +34 -21
- package/src/TSL/ShadowTerminator.js +125 -0
- package/src/TSL/Struct.js +9 -0
- package/src/TSL/Subsurface.js +2 -3
- package/src/index.js +29 -1
- package/src/managers/EnvironmentManager.js +20 -0
- package/src/managers/MaterialDataManager.js +118 -208
- package/src/managers/UniformManager.js +1 -0
- package/dist/ToneMapGPU-DzqSyzTx.js +0 -341
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BufferAttribute, Vector3, Vector2, Color, Matrix3, Matrix4, FrontSide, BackSide, DoubleSide, RGBAFormat } from "three";
|
|
2
2
|
import {
|
|
3
|
-
TEXTURE_CONSTANTS, TRIANGLE_DATA_LAYOUT, packNormalOct, packTriangleFlags
|
|
3
|
+
TEXTURE_CONSTANTS, TRIANGLE_DATA_LAYOUT, MATERIAL_DEFAULTS, packNormalOct, packTriangleFlags
|
|
4
4
|
} from '../EngineDefaults.js';
|
|
5
5
|
import { ISSUE_CODES } from '../EngineIssues.js';
|
|
6
6
|
import { ChunkedRecords, SHARED_MEMORY_AVAILABLE } from './ChunkedRecords.js';
|
|
@@ -10,6 +10,20 @@ const log = createLogger( 'geometry' );
|
|
|
10
10
|
|
|
11
11
|
const MAX_TEXTURES_LIMIT = TEXTURE_CONSTANTS.MAX_TEXTURES_LIMIT;
|
|
12
12
|
|
|
13
|
+
const COLOR_DEFAULTS = new Set( [ 'color', 'emissive', 'attenuationColor', 'sheenColor', 'specularColor', 'subsurfaceColor' ] );
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Where a packed material value came from: the three.js material carried it, a legacy-type
|
|
17
|
+
* conversion (Basic/Lambert/Phong/Toon) produced it, the engine filled it from
|
|
18
|
+
* MATERIAL_DEFAULTS, or a host set it at runtime through setMaterialProperty.
|
|
19
|
+
*/
|
|
20
|
+
export const MATERIAL_VALUE_SOURCE = Object.freeze( {
|
|
21
|
+
MATERIAL: 'material',
|
|
22
|
+
MAPPED: 'mapped',
|
|
23
|
+
DEFAULT: 'default',
|
|
24
|
+
HOST: 'host',
|
|
25
|
+
} );
|
|
26
|
+
|
|
13
27
|
const IDENTITY_ELEMENTS = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ];
|
|
14
28
|
|
|
15
29
|
function isIdentityElements( e ) {
|
|
@@ -19,6 +33,36 @@ function isIdentityElements( e ) {
|
|
|
19
33
|
|
|
20
34
|
}
|
|
21
35
|
|
|
36
|
+
/**
|
|
37
|
+
* The texture that feeds each GPU map slot. Re-packing texture indices without this loses the
|
|
38
|
+
* unlit routing (a MeshBasicMaterial's map is also its emission map).
|
|
39
|
+
* @param {import('three').Material} material
|
|
40
|
+
* @returns {Object<string, import('three').Texture|undefined>}
|
|
41
|
+
*/
|
|
42
|
+
export function resolveMaterialTextures( material ) {
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
map: material.map,
|
|
46
|
+
normalMap: material.normalMap,
|
|
47
|
+
bumpMap: material.bumpMap,
|
|
48
|
+
roughnessMap: material.roughnessMap,
|
|
49
|
+
metalnessMap: material.metalnessMap,
|
|
50
|
+
emissiveMap: material.emissiveMap ?? ( material.isMeshBasicMaterial ? material.map : undefined ),
|
|
51
|
+
displacementMap: material.displacementMap,
|
|
52
|
+
anisotropyMap: material.anisotropyMap,
|
|
53
|
+
clearcoatMap: material.clearcoatMap,
|
|
54
|
+
clearcoatRoughnessMap: material.clearcoatRoughnessMap,
|
|
55
|
+
transmissionMap: material.transmissionMap,
|
|
56
|
+
sheenColorMap: material.sheenColorMap,
|
|
57
|
+
sheenRoughnessMap: material.sheenRoughnessMap,
|
|
58
|
+
specularIntensityMap: material.specularIntensityMap,
|
|
59
|
+
specularColorMap: material.specularColorMap,
|
|
60
|
+
iridescenceMap: material.iridescenceMap,
|
|
61
|
+
iridescenceThicknessMap: material.iridescenceThicknessMap,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
22
66
|
/**
|
|
23
67
|
* glTF 2.0 alphaMode for a three.js material: 0 OPAQUE, 1 MASK, 2 BLEND.
|
|
24
68
|
*
|
|
@@ -734,43 +778,15 @@ export class GeometryExtractor {
|
|
|
734
778
|
|
|
735
779
|
getPhysicalDefaults() {
|
|
736
780
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
thickness: 0.1,
|
|
747
|
-
attenuationColor: new Color( 0xffffff ),
|
|
748
|
-
attenuationDistance: Infinity, // No attenuation by default
|
|
749
|
-
dispersion: 0.0,
|
|
750
|
-
sheen: 0.0,
|
|
751
|
-
sheenRoughness: 1.0,
|
|
752
|
-
sheenColor: new Color( 0x000000 ),
|
|
753
|
-
specularIntensity: 1.0,
|
|
754
|
-
specularColor: new Color( 0xffffff ),
|
|
755
|
-
clearcoat: 0.0,
|
|
756
|
-
clearcoatRoughness: 0.0,
|
|
757
|
-
iridescence: 0.0,
|
|
758
|
-
iridescenceIOR: 1.3,
|
|
759
|
-
iridescenceThicknessRange: [ 100, 400 ],
|
|
760
|
-
normalScale: { x: 1, y: 1 },
|
|
761
|
-
bumpScale: 1.0,
|
|
762
|
-
displacementScale: 1.0,
|
|
763
|
-
alphaTest: 0.0,
|
|
764
|
-
// Subsurface scattering (no native MeshPhysicalMaterial equivalent)
|
|
765
|
-
subsurface: 0.0,
|
|
766
|
-
subsurfaceColor: new Color( 0xffffff ),
|
|
767
|
-
subsurfaceRadius: [ 1.0, 0.2, 0.1 ], // skin-like: red travels furthest
|
|
768
|
-
subsurfaceRadiusScale: 1.0,
|
|
769
|
-
subsurfaceAnisotropy: 0.0,
|
|
770
|
-
// Surface specular anisotropy (native MeshPhysicalMaterial / KHR_materials_anisotropy)
|
|
771
|
-
anisotropy: 0.0,
|
|
772
|
-
anisotropyRotation: 0.0
|
|
773
|
-
};
|
|
781
|
+
const defaults = {};
|
|
782
|
+
for ( const [ key, value ] of Object.entries( MATERIAL_DEFAULTS ) ) {
|
|
783
|
+
|
|
784
|
+
defaults[ key ] = COLOR_DEFAULTS.has( key ) ? new Color().fromArray( value ) : Array.isArray( value ) ? [ ...value ] : value;
|
|
785
|
+
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
defaults.normalScale = { x: MATERIAL_DEFAULTS.normalScale[ 0 ], y: MATERIAL_DEFAULTS.normalScale[ 1 ] };
|
|
789
|
+
return defaults;
|
|
774
790
|
|
|
775
791
|
}
|
|
776
792
|
|
|
@@ -782,12 +798,13 @@ export class GeometryExtractor {
|
|
|
782
798
|
switch ( materialType ) {
|
|
783
799
|
|
|
784
800
|
case 'basic':
|
|
785
|
-
//
|
|
801
|
+
// Unlit (GLTFLoader's KHR_materials_unlit): colour and texture are emission, nothing reflects.
|
|
786
802
|
mapped.emissive = material.color.clone();
|
|
787
803
|
mapped.emissiveIntensity = 1.0;
|
|
788
|
-
mapped.color = new Color( 0x000000 );
|
|
804
|
+
mapped.color = new Color( 0x000000 );
|
|
789
805
|
mapped.roughness = 1.0;
|
|
790
806
|
mapped.metalness = 0.0;
|
|
807
|
+
mapped.specularIntensity = 0.0;
|
|
791
808
|
break;
|
|
792
809
|
|
|
793
810
|
case 'lambert':
|
|
@@ -807,14 +824,14 @@ export class GeometryExtractor {
|
|
|
807
824
|
|
|
808
825
|
}
|
|
809
826
|
|
|
810
|
-
//
|
|
827
|
+
// Strength in specularIntensity, hue alone in specularColor; carrying it in both squared it.
|
|
811
828
|
if ( material.specular ) {
|
|
812
829
|
|
|
813
|
-
const
|
|
814
|
-
|
|
815
|
-
|
|
830
|
+
const s = material.specular;
|
|
831
|
+
const specularLuminance = s.r * 0.299 + s.g * 0.587 + s.b * 0.114;
|
|
832
|
+
const peak = Math.max( s.r, s.g, s.b );
|
|
816
833
|
mapped.specularIntensity = Math.min( specularLuminance * 2.0, 1.0 );
|
|
817
|
-
mapped.specularColor =
|
|
834
|
+
mapped.specularColor = peak > 0 ? s.clone().multiplyScalar( 1 / peak ) : new Color( 1, 1, 1 );
|
|
818
835
|
|
|
819
836
|
}
|
|
820
837
|
|
|
@@ -842,121 +859,117 @@ export class GeometryExtractor {
|
|
|
842
859
|
const defaults = this.getPhysicalDefaults();
|
|
843
860
|
const materialType = this.getMaterialType( material );
|
|
844
861
|
const legacyMapping = this.mapLegacyMaterialToPhysical( material, materialType );
|
|
862
|
+
const textures = resolveMaterialTextures( material );
|
|
863
|
+
const sources = {};
|
|
845
864
|
|
|
846
|
-
|
|
847
|
-
// over the metal Fresnel hack: glTF defaults metallicFactor to 1, which otherwise stamps
|
|
848
|
-
// 2.5 onto water/glass authored as MeshStandardMaterial.
|
|
849
|
-
const isTransmissive = ( material.transmission ?? 0.0 ) > 0.0;
|
|
850
|
-
const isMetallic = ( material.metalness ?? legacyMapping.metalness ?? 0.0 ) > 0.1;
|
|
851
|
-
const defaultIOR = ( isMetallic && ! isTransmissive ) ? 2.5 : defaults.ior;
|
|
865
|
+
const pick = ( key ) => {
|
|
852
866
|
|
|
853
|
-
|
|
854
|
-
let baseColor = material.color || new Color( 0xffffff );
|
|
855
|
-
if ( materialType === 'basic' && ! material.map ) {
|
|
867
|
+
if ( legacyMapping[ key ] !== undefined ) {
|
|
856
868
|
|
|
857
|
-
|
|
858
|
-
|
|
869
|
+
sources[ key ] = MATERIAL_VALUE_SOURCE.MAPPED;
|
|
870
|
+
return legacyMapping[ key ];
|
|
859
871
|
|
|
860
|
-
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if ( material[ key ] !== undefined && material[ key ] !== null ) {
|
|
875
|
+
|
|
876
|
+
sources[ key ] = MATERIAL_VALUE_SOURCE.MATERIAL;
|
|
877
|
+
return material[ key ];
|
|
878
|
+
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
sources[ key ] = MATERIAL_VALUE_SOURCE.DEFAULT;
|
|
882
|
+
return defaults[ key ];
|
|
883
|
+
|
|
884
|
+
};
|
|
885
|
+
|
|
886
|
+
for ( const key of [ 'transparent', 'alphaMode', 'side', 'depthWrite' ] ) sources[ key ] = MATERIAL_VALUE_SOURCE.MATERIAL;
|
|
861
887
|
|
|
862
888
|
return {
|
|
863
889
|
uuid: material.uuid,
|
|
864
890
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
emissiveIntensity: legacyMapping.emissiveIntensity ?? material.emissiveIntensity ?? defaults.emissiveIntensity,
|
|
891
|
+
color: pick( 'color' ),
|
|
892
|
+
emissive: pick( 'emissive' ),
|
|
893
|
+
emissiveIntensity: pick( 'emissiveIntensity' ),
|
|
869
894
|
|
|
870
|
-
// Surface properties
|
|
871
895
|
// Floor at 0.02 (the sampler's own VNDF-PDF clamp, MaterialProperties.js) rather than
|
|
872
896
|
// 0.05, so near-mirror metals stay sharp without entering a new firefly regime.
|
|
873
|
-
roughness: Math.max( 0.02,
|
|
874
|
-
metalness:
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
specularColor: legacyMapping.specularColor ?? material.specularColor ?? defaults.specularColor,
|
|
911
|
-
|
|
912
|
-
// Surface detail properties
|
|
913
|
-
normalScale: material.normalScale ?? defaults.normalScale,
|
|
914
|
-
bumpScale: material.bumpScale ?? defaults.bumpScale,
|
|
915
|
-
displacementScale: material.displacementScale ?? defaults.displacementScale,
|
|
916
|
-
|
|
917
|
-
// Transparency and alpha
|
|
897
|
+
roughness: Math.max( 0.02, pick( 'roughness' ) ),
|
|
898
|
+
metalness: pick( 'metalness' ),
|
|
899
|
+
|
|
900
|
+
ior: pick( 'ior' ),
|
|
901
|
+
opacity: pick( 'opacity' ),
|
|
902
|
+
|
|
903
|
+
transmission: pick( 'transmission' ),
|
|
904
|
+
thickness: pick( 'thickness' ),
|
|
905
|
+
attenuationColor: pick( 'attenuationColor' ),
|
|
906
|
+
attenuationDistance: pick( 'attenuationDistance' ),
|
|
907
|
+
|
|
908
|
+
dispersion: pick( 'dispersion' ),
|
|
909
|
+
sheen: pick( 'sheen' ),
|
|
910
|
+
sheenRoughness: pick( 'sheenRoughness' ),
|
|
911
|
+
sheenColor: pick( 'sheenColor' ),
|
|
912
|
+
clearcoat: pick( 'clearcoat' ),
|
|
913
|
+
clearcoatRoughness: pick( 'clearcoatRoughness' ),
|
|
914
|
+
iridescence: pick( 'iridescence' ),
|
|
915
|
+
iridescenceIOR: pick( 'iridescenceIOR' ),
|
|
916
|
+
iridescenceThicknessRange: pick( 'iridescenceThicknessRange' ),
|
|
917
|
+
|
|
918
|
+
subsurface: pick( 'subsurface' ),
|
|
919
|
+
subsurfaceColor: pick( 'subsurfaceColor' ),
|
|
920
|
+
subsurfaceRadius: pick( 'subsurfaceRadius' ),
|
|
921
|
+
subsurfaceRadiusScale: pick( 'subsurfaceRadiusScale' ),
|
|
922
|
+
subsurfaceAnisotropy: pick( 'subsurfaceAnisotropy' ),
|
|
923
|
+
|
|
924
|
+
anisotropy: pick( 'anisotropy' ),
|
|
925
|
+
anisotropyRotation: pick( 'anisotropyRotation' ),
|
|
926
|
+
|
|
927
|
+
specularIntensity: pick( 'specularIntensity' ),
|
|
928
|
+
specularColor: pick( 'specularColor' ),
|
|
929
|
+
|
|
930
|
+
normalScale: pick( 'normalScale' ),
|
|
931
|
+
bumpScale: pick( 'bumpScale' ),
|
|
932
|
+
displacementScale: pick( 'displacementScale' ),
|
|
933
|
+
|
|
918
934
|
transparent: material.transparent ? 1 : 0,
|
|
919
|
-
alphaTest:
|
|
935
|
+
alphaTest: pick( 'alphaTest' ),
|
|
920
936
|
alphaMode: deriveAlphaMode( material ),
|
|
921
937
|
|
|
922
|
-
// Rendering properties
|
|
923
938
|
side: this.getMaterialSide( material ),
|
|
924
939
|
depthWrite: material.depthWrite ?? true ? 1 : 0,
|
|
925
940
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
anisotropyMap: this.processTexture( material.anisotropyMap, this.anisotropyMaps ),
|
|
941
|
+
map: this.processTexture( textures.map, this.maps ),
|
|
942
|
+
normalMap: this.processTexture( textures.normalMap, this.normalMaps ),
|
|
943
|
+
bumpMap: this.processTexture( textures.bumpMap, this.bumpMaps ),
|
|
944
|
+
roughnessMap: this.processTexture( textures.roughnessMap, this.roughnessMaps ),
|
|
945
|
+
metalnessMap: this.processTexture( textures.metalnessMap, this.metalnessMaps ),
|
|
946
|
+
emissiveMap: this.processTexture( textures.emissiveMap, this.emissiveMaps ),
|
|
947
|
+
displacementMap: this.processTexture( textures.displacementMap, this.displacementMaps ),
|
|
948
|
+
anisotropyMap: this.processTexture( textures.anisotropyMap, this.anisotropyMaps ),
|
|
935
949
|
|
|
936
950
|
// Advanced texture maps (MeshPhysicalMaterial only). Folded into their scalar factors
|
|
937
951
|
// in ShadeKernel (applyExtensionMaps). thicknessMap stays dropped — thickness has no
|
|
938
952
|
// render effect yet (see gap-plan Phase 4.4).
|
|
939
|
-
clearcoatMap: this.processTexture(
|
|
940
|
-
clearcoatRoughnessMap: this.processTexture(
|
|
941
|
-
transmissionMap: this.processTexture(
|
|
953
|
+
clearcoatMap: this.processTexture( textures.clearcoatMap, this.clearcoatMaps ),
|
|
954
|
+
clearcoatRoughnessMap: this.processTexture( textures.clearcoatRoughnessMap, this.clearcoatRoughnessMaps ),
|
|
955
|
+
transmissionMap: this.processTexture( textures.transmissionMap, this.transmissionMaps ),
|
|
942
956
|
thicknessMap: this.processTexture( material.thicknessMap, [] ),
|
|
943
|
-
sheenColorMap: this.processTexture(
|
|
944
|
-
sheenRoughnessMap: this.processTexture(
|
|
945
|
-
specularIntensityMap: this.processTexture(
|
|
946
|
-
specularColorMap: this.processTexture(
|
|
947
|
-
iridescenceMap: this.processTexture(
|
|
948
|
-
iridescenceThicknessMap: this.processTexture(
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
// Material type for debugging/optimization
|
|
957
|
+
sheenColorMap: this.processTexture( textures.sheenColorMap, this.sheenColorMaps ),
|
|
958
|
+
sheenRoughnessMap: this.processTexture( textures.sheenRoughnessMap, this.sheenRoughnessMaps ),
|
|
959
|
+
specularIntensityMap: this.processTexture( textures.specularIntensityMap, this.specularIntensityMaps ),
|
|
960
|
+
specularColorMap: this.processTexture( textures.specularColorMap, this.specularColorMaps ),
|
|
961
|
+
iridescenceMap: this.processTexture( textures.iridescenceMap, this.iridescenceMaps ),
|
|
962
|
+
iridescenceThicknessMap: this.processTexture( textures.iridescenceThicknessMap, this.iridescenceThicknessMaps ),
|
|
963
|
+
|
|
964
|
+
mapMatrix: this.getTextureMatrix( textures.map ),
|
|
965
|
+
normalMapMatrices: this.getTextureMatrix( textures.normalMap ),
|
|
966
|
+
bumpMapMatrices: this.getTextureMatrix( textures.bumpMap ),
|
|
967
|
+
roughnessMapMatrices: this.getTextureMatrix( textures.roughnessMap ),
|
|
968
|
+
metalnessMapMatrices: this.getTextureMatrix( textures.metalnessMap ),
|
|
969
|
+
emissiveMapMatrices: this.getTextureMatrix( textures.emissiveMap ),
|
|
970
|
+
displacementMapMatrices: this.getTextureMatrix( textures.displacementMap ),
|
|
971
|
+
|
|
972
|
+
sources,
|
|
960
973
|
originalType: materialType
|
|
961
974
|
};
|
|
962
975
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Vector3, Quaternion } from 'three';
|
|
2
2
|
import { blackbodyToLinearRGB } from './blackbody.js';
|
|
3
|
+
import { convertLinearTriple } from '../Color/WorkingMatrix.js';
|
|
3
4
|
|
|
4
5
|
// Point & spot lights specify Power in Watts; the shader uses radiant intensity
|
|
5
6
|
// (W/sr) as `intensity / dist²`, so convert with I = P / 4π (isotropic emitter),
|
|
@@ -15,15 +16,19 @@ function effectiveEmission( light ) {
|
|
|
15
16
|
const exposure = Number.isFinite( ud.exposure ) ? ud.exposure : 0;
|
|
16
17
|
const intensity = light.intensity * Math.pow( 2, exposure );
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
const rgb = [ light.color.r, light.color.g, light.color.b ];
|
|
19
20
|
if ( ud.useTemperature ) {
|
|
20
21
|
|
|
21
22
|
const [ tr, tg, tb ] = blackbodyToLinearRGB( ud.temperature ?? 6500 );
|
|
22
|
-
|
|
23
|
+
rgb[ 0 ] *= tr; rgb[ 1 ] *= tg; rgb[ 2 ] *= tb;
|
|
23
24
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
// A light colour is authored against sRGB primaries, like everything else three.js hands over.
|
|
28
|
+
// Rendering in a wider working space without converting it tints every surface it touches.
|
|
29
|
+
convertLinearTriple( rgb );
|
|
30
|
+
|
|
31
|
+
return { r: rgb[ 0 ], g: rgb[ 1 ], b: rgb[ 2 ], intensity };
|
|
27
32
|
|
|
28
33
|
}
|
|
29
34
|
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { MATERIAL_DATA_LAYOUT as M, MATERIAL_DEFAULTS as D, normalizeAttenuationDistance } from '../EngineDefaults.js';
|
|
2
|
+
|
|
3
|
+
// The first 8 Matrix3 elements; the GPU rebuilds the 9th (always 1).
|
|
4
|
+
const IDENTITY_UV = [ 1, 0, 0, 0, 1, 0, 0, 0 ];
|
|
5
|
+
|
|
6
|
+
const TRANSFORMS = [
|
|
7
|
+
[ 'mapMatrix', M.ALBEDO_TRANSFORM ],
|
|
8
|
+
[ 'normalMapMatrices', M.NORMAL_TRANSFORM ],
|
|
9
|
+
[ 'roughnessMapMatrices', M.ROUGHNESS_TRANSFORM ],
|
|
10
|
+
[ 'metalnessMapMatrices', M.METALNESS_TRANSFORM ],
|
|
11
|
+
[ 'emissiveMapMatrices', M.EMISSIVE_TRANSFORM ],
|
|
12
|
+
[ 'bumpMapMatrices', M.BUMP_TRANSFORM ],
|
|
13
|
+
[ 'displacementMapMatrices', M.DISPLACEMENT_TRANSFORM ],
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
/** Floats no field writes; the packer gives them fixed values. */
|
|
17
|
+
export const MATERIAL_RESERVED_FLOATS = Object.freeze( [
|
|
18
|
+
M.VISIBLE, M.SHEEN_COLOR + 3, M.DISPLACEMENT_MAP_INDEX + 1,
|
|
19
|
+
M.SPECULAR_COLOR_MAP_INDEX + 1, M.SPECULAR_COLOR_MAP_INDEX + 2, M.SPECULAR_COLOR_MAP_INDEX + 3,
|
|
20
|
+
] );
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Weights and roughnesses, [0, 1] in glTF and three.js. Past 1 an energy split like
|
|
24
|
+
* 1 − clearcoat·E goes negative: a glTF chrome with clearcoatFactor 4 added negative light.
|
|
25
|
+
*/
|
|
26
|
+
export const UNIT_RANGE_PROPERTIES = Object.freeze( new Set( [
|
|
27
|
+
'metalness', 'roughness', 'transmission', 'opacity', 'clearcoat', 'clearcoatRoughness',
|
|
28
|
+
'sheen', 'sheenRoughness', 'specularIntensity', 'iridescence', 'subsurface', 'anisotropy',
|
|
29
|
+
] ) );
|
|
30
|
+
|
|
31
|
+
export const clampUnit = ( value ) => Math.min( Math.max( value, 0 ), 1 );
|
|
32
|
+
|
|
33
|
+
function num( value, fallback ) {
|
|
34
|
+
|
|
35
|
+
const n = typeof value === 'boolean' ? + value : value;
|
|
36
|
+
return Number.isFinite( n ) ? n : fallback;
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mapIndex( value ) {
|
|
41
|
+
|
|
42
|
+
return Number.isInteger( value ) ? value : - 1;
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function writeTriple( data, at, value, fallback ) {
|
|
47
|
+
|
|
48
|
+
const r = value?.r ?? value?.[ 0 ] ?? value?.x;
|
|
49
|
+
const g = value?.g ?? value?.[ 1 ] ?? value?.y;
|
|
50
|
+
const b = value?.b ?? value?.[ 2 ] ?? value?.z;
|
|
51
|
+
data[ at ] = num( r, fallback[ 0 ] );
|
|
52
|
+
data[ at + 1 ] = num( g, fallback[ 1 ] );
|
|
53
|
+
data[ at + 2 ] = num( b, fallback[ 2 ] );
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The one writer of a material block, for the scene upload and runtime edits alike. A missing or
|
|
59
|
+
* non-finite field gets MATERIAL_DEFAULTS.
|
|
60
|
+
* @param {Float32Array} data
|
|
61
|
+
* @param {number} base - float offset of the material's block
|
|
62
|
+
* @param {Object} mat - a GeometryExtractor.createMaterialObject() result, or any subset of it
|
|
63
|
+
*/
|
|
64
|
+
export function packMaterial( data, base, mat ) {
|
|
65
|
+
|
|
66
|
+
const s = ( offset, value, fallback ) => {
|
|
67
|
+
|
|
68
|
+
data[ base + offset ] = num( value, fallback );
|
|
69
|
+
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const u = ( offset, value, fallback ) => {
|
|
73
|
+
|
|
74
|
+
data[ base + offset ] = clampUnit( num( value, fallback ) );
|
|
75
|
+
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
s( M.IOR, mat.ior, D.ior );
|
|
79
|
+
u( M.TRANSMISSION, mat.transmission, D.transmission );
|
|
80
|
+
s( M.THICKNESS, mat.thickness, D.thickness );
|
|
81
|
+
s( M.EMISSIVE_INTENSITY, mat.emissiveIntensity, D.emissiveIntensity );
|
|
82
|
+
|
|
83
|
+
writeTriple( data, base + M.ATTENUATION_COLOR, mat.attenuationColor, D.attenuationColor );
|
|
84
|
+
data[ base + M.ATTENUATION_DISTANCE ] = normalizeAttenuationDistance( mat.attenuationDistance ?? D.attenuationDistance );
|
|
85
|
+
|
|
86
|
+
u( M.OPACITY, mat.opacity, D.opacity );
|
|
87
|
+
s( M.SIDE, mat.side, D.side );
|
|
88
|
+
s( M.TRANSPARENT, mat.transparent, D.transparent );
|
|
89
|
+
s( M.ALPHA_TEST, mat.alphaTest, D.alphaTest );
|
|
90
|
+
|
|
91
|
+
s( M.ALPHA_MODE, mat.alphaMode, D.alphaMode );
|
|
92
|
+
s( M.DEPTH_WRITE, mat.depthWrite, D.depthWrite );
|
|
93
|
+
const normalScale = mat.normalScale;
|
|
94
|
+
const uniformScale = typeof normalScale === 'number' ? normalScale : undefined;
|
|
95
|
+
s( M.NORMAL_SCALE, uniformScale ?? normalScale?.x ?? normalScale?.[ 0 ], D.normalScale[ 0 ] );
|
|
96
|
+
s( M.NORMAL_SCALE + 1, uniformScale ?? normalScale?.y ?? normalScale?.[ 1 ], D.normalScale[ 1 ] );
|
|
97
|
+
|
|
98
|
+
writeTriple( data, base + M.COLOR, mat.color, D.color );
|
|
99
|
+
u( M.METALNESS, mat.metalness, D.metalness );
|
|
100
|
+
|
|
101
|
+
writeTriple( data, base + M.EMISSIVE, mat.emissive, D.emissive );
|
|
102
|
+
u( M.ROUGHNESS, mat.roughness, D.roughness );
|
|
103
|
+
|
|
104
|
+
data[ base + M.ALBEDO_MAP_INDEX ] = mapIndex( mat.map );
|
|
105
|
+
data[ base + M.NORMAL_MAP_INDEX ] = mapIndex( mat.normalMap );
|
|
106
|
+
data[ base + M.ROUGHNESS_MAP_INDEX ] = mapIndex( mat.roughnessMap );
|
|
107
|
+
data[ base + M.METALNESS_MAP_INDEX ] = mapIndex( mat.metalnessMap );
|
|
108
|
+
|
|
109
|
+
data[ base + M.EMISSIVE_MAP_INDEX ] = mapIndex( mat.emissiveMap );
|
|
110
|
+
data[ base + M.BUMP_MAP_INDEX ] = mapIndex( mat.bumpMap );
|
|
111
|
+
u( M.CLEARCOAT, mat.clearcoat, D.clearcoat );
|
|
112
|
+
u( M.CLEARCOAT_ROUGHNESS, mat.clearcoatRoughness, D.clearcoatRoughness );
|
|
113
|
+
|
|
114
|
+
s( M.DISPERSION, mat.dispersion, D.dispersion );
|
|
115
|
+
u( M.SHEEN, mat.sheen, D.sheen );
|
|
116
|
+
u( M.SHEEN_ROUGHNESS, mat.sheenRoughness, D.sheenRoughness );
|
|
117
|
+
|
|
118
|
+
writeTriple( data, base + M.SHEEN_COLOR, mat.sheenColor, D.sheenColor );
|
|
119
|
+
|
|
120
|
+
u( M.SPECULAR_INTENSITY, mat.specularIntensity, D.specularIntensity );
|
|
121
|
+
writeTriple( data, base + M.SPECULAR_COLOR, mat.specularColor, D.specularColor );
|
|
122
|
+
|
|
123
|
+
u( M.IRIDESCENCE, mat.iridescence, D.iridescence );
|
|
124
|
+
s( M.IRIDESCENCE_IOR, mat.iridescenceIOR, D.iridescenceIOR );
|
|
125
|
+
s( M.IRIDESCENCE_THICKNESS_RANGE, mat.iridescenceThicknessRange?.[ 0 ], D.iridescenceThicknessRange[ 0 ] );
|
|
126
|
+
s( M.IRIDESCENCE_THICKNESS_RANGE + 1, mat.iridescenceThicknessRange?.[ 1 ], D.iridescenceThicknessRange[ 1 ] );
|
|
127
|
+
|
|
128
|
+
s( M.BUMP_SCALE, mat.bumpScale, D.bumpScale );
|
|
129
|
+
s( M.DISPLACEMENT_SCALE, mat.displacementScale, D.displacementScale );
|
|
130
|
+
data[ base + M.DISPLACEMENT_MAP_INDEX ] = mapIndex( mat.displacementMap );
|
|
131
|
+
|
|
132
|
+
for ( const [ key, offset ] of TRANSFORMS ) {
|
|
133
|
+
|
|
134
|
+
const matrix = mat[ key ];
|
|
135
|
+
for ( let i = 0; i < 8; i ++ ) data[ base + offset + i ] = num( matrix?.[ i ], IDENTITY_UV[ i ] );
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
writeTriple( data, base + M.SUBSURFACE_COLOR, mat.subsurfaceColor, D.subsurfaceColor );
|
|
140
|
+
u( M.SUBSURFACE, mat.subsurface, D.subsurface );
|
|
141
|
+
writeTriple( data, base + M.SUBSURFACE_RADIUS, mat.subsurfaceRadius, D.subsurfaceRadius );
|
|
142
|
+
s( M.SUBSURFACE_RADIUS_SCALE, mat.subsurfaceRadiusScale, D.subsurfaceRadiusScale );
|
|
143
|
+
|
|
144
|
+
s( M.SUBSURFACE_ANISOTROPY, mat.subsurfaceAnisotropy, D.subsurfaceAnisotropy );
|
|
145
|
+
u( M.ANISOTROPY, mat.anisotropy, D.anisotropy );
|
|
146
|
+
s( M.ANISOTROPY_ROTATION, mat.anisotropyRotation, D.anisotropyRotation );
|
|
147
|
+
data[ base + M.ANISOTROPY_MAP_INDEX ] = mapIndex( mat.anisotropyMap );
|
|
148
|
+
|
|
149
|
+
data[ base + M.TRANSMISSION_MAP_INDEX ] = mapIndex( mat.transmissionMap );
|
|
150
|
+
data[ base + M.CLEARCOAT_MAP_INDEX ] = mapIndex( mat.clearcoatMap );
|
|
151
|
+
data[ base + M.CLEARCOAT_ROUGHNESS_MAP_INDEX ] = mapIndex( mat.clearcoatRoughnessMap );
|
|
152
|
+
data[ base + M.SHEEN_COLOR_MAP_INDEX ] = mapIndex( mat.sheenColorMap );
|
|
153
|
+
|
|
154
|
+
data[ base + M.SHEEN_ROUGHNESS_MAP_INDEX ] = mapIndex( mat.sheenRoughnessMap );
|
|
155
|
+
data[ base + M.IRIDESCENCE_MAP_INDEX ] = mapIndex( mat.iridescenceMap );
|
|
156
|
+
data[ base + M.IRIDESCENCE_THICKNESS_MAP_INDEX ] = mapIndex( mat.iridescenceThicknessMap );
|
|
157
|
+
data[ base + M.SPECULAR_INTENSITY_MAP_INDEX ] = mapIndex( mat.specularIntensityMap );
|
|
158
|
+
|
|
159
|
+
data[ base + M.SPECULAR_COLOR_MAP_INDEX ] = mapIndex( mat.specularColorMap );
|
|
160
|
+
|
|
161
|
+
data[ base + M.VISIBLE ] = 1;
|
|
162
|
+
data[ base + M.SHEEN_COLOR + 3 ] = 1;
|
|
163
|
+
data[ base + M.DISPLACEMENT_MAP_INDEX + 1 ] = 0;
|
|
164
|
+
data[ base + M.SPECULAR_COLOR_MAP_INDEX + 1 ] = 0;
|
|
165
|
+
data[ base + M.SPECULAR_COLOR_MAP_INDEX + 2 ] = 0;
|
|
166
|
+
data[ base + M.SPECULAR_COLOR_MAP_INDEX + 3 ] = 0;
|
|
167
|
+
|
|
168
|
+
}
|
|
@@ -281,12 +281,16 @@ export const readHitMaterialIndex = ( buf, id ) =>
|
|
|
281
281
|
export const readHitInstanceLeaf = ( buf, id ) =>
|
|
282
282
|
int( buf.element( soa( id, HIT.NORMAL_MAT ) ).z ).sub( int( 1 ) );
|
|
283
283
|
|
|
284
|
-
|
|
284
|
+
/** Facet normal and terminator lift, packed by HitFacet.packHitFacet. */
|
|
285
|
+
export const readHitFacet = ( buf, id ) =>
|
|
286
|
+
buf.element( soa( id, HIT.NORMAL_MAT ) ).w;
|
|
287
|
+
|
|
288
|
+
export const writeHitPacked = ( buf, id, distance, triIndex, baryU, baryV, normal, matIndex, instanceLeaf, facet = uint( 0 ) ) => {
|
|
285
289
|
|
|
286
290
|
buf.element( soa( id, HIT.DIST_TRI_BARY ) )
|
|
287
291
|
.assign( uvec4( floatBitsToUint( distance ), triIndex, floatBitsToUint( baryU ), floatBitsToUint( baryV ) ) );
|
|
288
292
|
buf.element( soa( id, HIT.NORMAL_MAT ) )
|
|
289
|
-
.assign( uvec4( packNormalOct( normal ), matIndex, instanceLeaf,
|
|
293
|
+
.assign( uvec4( packNormalOct( normal ), matIndex, instanceLeaf, facet ) );
|
|
290
294
|
|
|
291
295
|
};
|
|
292
296
|
|
|
@@ -248,6 +248,10 @@ export class ProceduralSky {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
this._texture.needsUpdate = true;
|
|
251
|
+
// Fresh linear Rec.709 pixels in a reused texture. Colour management records which space a
|
|
252
|
+
// texture's pixels hold so it never converts them twice; left in place, that record would
|
|
253
|
+
// claim these were already converted and they never would be.
|
|
254
|
+
delete this._texture.userData?.__rayzeeColorSpace;
|
|
251
255
|
this.lastRenderTime = performance.now() - startTime;
|
|
252
256
|
|
|
253
257
|
return this._texture;
|
|
@@ -2163,7 +2163,7 @@ export class SceneProcessor {
|
|
|
2163
2163
|
|
|
2164
2164
|
if ( this.materialData ) {
|
|
2165
2165
|
|
|
2166
|
-
pathTracer.materialData.setMaterialData( this.materialData );
|
|
2166
|
+
pathTracer.materialData.setMaterialData( this.materialData, this.materials.map( m => m.sources ) );
|
|
2167
2167
|
|
|
2168
2168
|
} else {
|
|
2169
2169
|
|
|
@@ -2240,6 +2240,30 @@ export class SceneProcessor {
|
|
|
2240
2240
|
|
|
2241
2241
|
}
|
|
2242
2242
|
|
|
2243
|
+
/**
|
|
2244
|
+
* Re-read every emitter's colour, after the working space changed.
|
|
2245
|
+
*
|
|
2246
|
+
* `rebuildMaterials` re-packs the material buffer but leaves this list alone, and next-event
|
|
2247
|
+
* estimation lights the scene from this list — so without a rebuild, emitters would be seen in
|
|
2248
|
+
* the new space and cast light in the old one.
|
|
2249
|
+
*
|
|
2250
|
+
* @returns {object|null} GPU upload payload
|
|
2251
|
+
*/
|
|
2252
|
+
rebuildEmissiveColors() {
|
|
2253
|
+
|
|
2254
|
+
if ( ! this.emissiveTriangleBuilder || ! this.triangleCount ) return null;
|
|
2255
|
+
|
|
2256
|
+
this.emissiveTriangleBuilder.extractEmissiveTriangles(
|
|
2257
|
+
this.triangles,
|
|
2258
|
+
this.materials,
|
|
2259
|
+
this.triangleCount,
|
|
2260
|
+
this.instanceTable ?? null
|
|
2261
|
+
);
|
|
2262
|
+
this.emissiveTriangleBuilder.createEmissiveRawData();
|
|
2263
|
+
return this._collectEmissivePayload();
|
|
2264
|
+
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2243
2267
|
/**
|
|
2244
2268
|
* Re-derive the sampled emissive set from per-mesh visibility.
|
|
2245
2269
|
* @param {Set<number>|Iterable<number>} hiddenMeshIndices - meshIndex values that are world-hidden
|
|
@@ -87,6 +87,10 @@ export class SimpleSky {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
this._texture.needsUpdate = true;
|
|
90
|
+
// Fresh linear Rec.709 pixels in a reused texture. Colour management records which space a
|
|
91
|
+
// texture's pixels hold so it never converts them twice; left in place, that record would
|
|
92
|
+
// claim these were already converted and they never would be.
|
|
93
|
+
delete this._texture.userData?.__rayzeeColorSpace;
|
|
90
94
|
this.lastRenderTime = performance.now() - startTime;
|
|
91
95
|
return this._texture;
|
|
92
96
|
|
|
@@ -120,6 +124,10 @@ export class SimpleSky {
|
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
this._texture.needsUpdate = true;
|
|
127
|
+
// Fresh linear Rec.709 pixels in a reused texture. Colour management records which space a
|
|
128
|
+
// texture's pixels hold so it never converts them twice; left in place, that record would
|
|
129
|
+
// claim these were already converted and they never would be.
|
|
130
|
+
delete this._texture.userData?.__rayzeeColorSpace;
|
|
123
131
|
this.lastRenderTime = performance.now() - startTime;
|
|
124
132
|
return this._texture;
|
|
125
133
|
|