super-three 0.163.0 → 0.164.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/build/three.cjs +473 -245
- package/build/three.module.js +473 -245
- package/build/three.module.min.js +2 -2
- package/examples/jsm/animation/CCDIKSolver.js +4 -2
- package/examples/jsm/exporters/GLTFExporter.js +45 -1
- package/examples/jsm/exporters/USDZExporter.js +7 -1
- package/examples/jsm/libs/draco/README.md +2 -2
- package/examples/jsm/loaders/EXRLoader.js +283 -99
- package/examples/jsm/loaders/GLTFLoader.js +53 -0
- package/examples/jsm/loaders/KTX2Loader.js +3 -6
- package/examples/jsm/loaders/VRMLLoader.js +1 -1
- package/examples/jsm/loaders/lwo/IFFParser.js +8 -5
- package/examples/jsm/materials/MeshGouraudMaterial.js +7 -1
- package/examples/jsm/math/Octree.js +26 -20
- package/examples/jsm/nodes/Nodes.js +4 -3
- package/examples/jsm/nodes/accessors/AccessorsUtils.js +16 -1
- package/examples/jsm/nodes/accessors/ClippingNode.js +3 -2
- package/examples/jsm/nodes/accessors/MaterialNode.js +107 -3
- package/examples/jsm/nodes/accessors/StorageBufferNode.js +9 -0
- package/examples/jsm/nodes/accessors/TextureNode.js +21 -3
- package/examples/jsm/nodes/accessors/TextureSizeNode.js +1 -1
- package/examples/jsm/nodes/code/FunctionNode.js +0 -8
- package/examples/jsm/nodes/core/Node.js +8 -0
- package/examples/jsm/nodes/core/NodeBuilder.js +5 -9
- package/examples/jsm/nodes/core/OutputStructNode.js +2 -1
- package/examples/jsm/nodes/core/PropertyNode.js +10 -0
- package/examples/jsm/nodes/display/BumpMapNode.js +7 -26
- package/examples/jsm/nodes/display/FrontFacingNode.js +13 -0
- package/examples/jsm/nodes/display/ViewportDepthNode.js +1 -1
- package/examples/jsm/nodes/display/ViewportNode.js +4 -2
- package/examples/jsm/nodes/display/ViewportTextureNode.js +4 -1
- package/examples/jsm/nodes/functions/BSDF/BRDF_GGX.js +26 -7
- package/examples/jsm/nodes/functions/BSDF/D_GGX_Anisotropic.js +28 -0
- package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated.js +1 -3
- package/examples/jsm/nodes/functions/BSDF/V_GGX_SmithCorrelated_Anisotropic.js +29 -0
- package/examples/jsm/nodes/functions/PhongLightingModel.js +1 -1
- package/examples/jsm/nodes/functions/PhysicalLightingModel.js +164 -10
- package/examples/jsm/nodes/functions/ShadowMaskModel.js +31 -0
- package/examples/jsm/nodes/lighting/AnalyticLightNode.js +18 -4
- package/examples/jsm/nodes/lighting/DirectionalLightNode.js +2 -1
- package/examples/jsm/nodes/lighting/EnvironmentNode.js +11 -2
- package/examples/jsm/nodes/lighting/IrradianceNode.js +24 -0
- package/examples/jsm/nodes/lighting/LightsNode.js +11 -1
- package/examples/jsm/nodes/lighting/PointLightNode.js +2 -1
- package/examples/jsm/nodes/lighting/SpotLightNode.js +2 -1
- package/examples/jsm/nodes/materials/Line2NodeMaterial.js +10 -6
- package/examples/jsm/nodes/materials/Materials.js +1 -0
- package/examples/jsm/nodes/materials/MeshNormalNodeMaterial.js +0 -2
- package/examples/jsm/nodes/materials/MeshPhongNodeMaterial.js +2 -2
- package/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js +76 -5
- package/examples/jsm/nodes/materials/MeshStandardNodeMaterial.js +11 -4
- package/examples/jsm/nodes/materials/NodeMaterial.js +31 -41
- package/examples/jsm/nodes/materials/ShadowNodeMaterial.js +34 -0
- package/examples/jsm/nodes/pmrem/PMREMUtils.js +1 -1
- package/examples/jsm/nodes/shadernode/ShaderNode.js +2 -8
- package/examples/jsm/physics/JoltPhysics.js +281 -0
- package/examples/jsm/postprocessing/RenderTransitionPass.js +193 -0
- package/examples/jsm/renderers/common/Background.js +3 -3
- package/examples/jsm/renderers/common/ClippingContext.js +1 -1
- package/examples/jsm/renderers/common/RenderList.js +1 -1
- package/examples/jsm/renderers/common/RenderObject.js +43 -1
- package/examples/jsm/renderers/common/Renderer.js +129 -14
- package/examples/jsm/renderers/common/Textures.js +1 -1
- package/examples/jsm/renderers/common/extras/PMREMGenerator.js +13 -17
- package/examples/jsm/renderers/common/nodes/Nodes.js +31 -47
- package/examples/jsm/renderers/webgl/WebGLBackend.js +7 -21
- package/examples/jsm/renderers/webgl/WebGLBufferRenderer.js +5 -1
- package/examples/jsm/renderers/webgl/nodes/GLSLNodeBuilder.js +6 -0
- package/examples/jsm/renderers/webgl/utils/WebGLTextureUtils.js +21 -7
- package/examples/jsm/renderers/webgl/utils/WebGLUtils.js +3 -21
- package/examples/jsm/renderers/webgpu/WebGPUBackend.js +33 -45
- package/examples/jsm/renderers/webgpu/nodes/WGSLNodeBuilder.js +16 -1
- package/examples/jsm/renderers/webgpu/utils/WebGPUAttributeUtils.js +4 -1
- package/examples/jsm/transpiler/GLSLDecoder.js +1 -1
- package/examples/jsm/transpiler/ShaderToyDecoder.js +1 -1
- package/examples/jsm/utils/SceneUtils.js +60 -1
- package/examples/jsm/webxr/OculusHandModel.js +3 -2
- package/examples/jsm/webxr/XRHandModelFactory.js +4 -2
- package/package.json +1 -1
- package/src/constants.js +1 -1
- package/src/core/RenderTarget.js +8 -0
- package/src/extras/PMREMGenerator.js +12 -11
- package/src/loaders/FileLoader.js +1 -1
- package/src/loaders/MaterialLoader.js +1 -0
- package/src/materials/Material.js +2 -0
- package/src/materials/MeshPhysicalMaterial.js +20 -0
- package/src/objects/BatchedMesh.js +23 -0
- package/src/objects/Line.js +66 -43
- package/src/renderers/WebGLRenderer.js +92 -61
- package/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js +6 -0
- package/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js +1 -0
- package/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js +17 -9
- package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
- package/src/renderers/shaders/ShaderChunk/transmission_pars_fragment.glsl.js +47 -13
- package/src/renderers/shaders/ShaderChunk.js +0 -2
- package/src/renderers/shaders/ShaderLib/meshphysical.glsl.js +4 -0
- package/src/renderers/shaders/ShaderLib.js +1 -0
- package/src/renderers/webgl/WebGLBackground.js +18 -3
- package/src/renderers/webgl/WebGLBufferRenderer.js +36 -0
- package/src/renderers/webgl/WebGLCapabilities.js +33 -1
- package/src/renderers/webgl/WebGLIndexedBufferRenderer.js +36 -0
- package/src/renderers/webgl/WebGLMaterials.js +6 -0
- package/src/renderers/webgl/WebGLProgram.js +3 -5
- package/src/renderers/webgl/WebGLPrograms.js +5 -0
- package/src/renderers/webgl/WebGLRenderStates.js +6 -2
- package/src/renderers/webgl/WebGLShadowMap.js +25 -25
- package/src/renderers/webgl/WebGLTextures.js +68 -60
- package/src/renderers/webgl/WebGLUtils.js +3 -21
- package/src/renderers/webxr/WebXRManager.js +2 -4
- package/examples/jsm/renderers/webgl-legacy/nodes/GLSL1NodeBuilder.js +0 -318
- package/examples/jsm/renderers/webgl-legacy/nodes/SlotNode.js +0 -26
- package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js +0 -792
- package/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js +0 -51
- package/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js +0 -10
|
@@ -72,7 +72,6 @@ class NodeBuilder {
|
|
|
72
72
|
this.lightsNode = null;
|
|
73
73
|
this.environmentNode = null;
|
|
74
74
|
this.fogNode = null;
|
|
75
|
-
this.toneMappingNode = null;
|
|
76
75
|
|
|
77
76
|
this.clippingContext = null;
|
|
78
77
|
|
|
@@ -1087,21 +1086,18 @@ class NodeBuilder {
|
|
|
1087
1086
|
|
|
1088
1087
|
}
|
|
1089
1088
|
|
|
1090
|
-
build(
|
|
1089
|
+
build() {
|
|
1091
1090
|
|
|
1092
1091
|
const { object, material } = this;
|
|
1093
1092
|
|
|
1094
|
-
if ( convertMaterial ) {
|
|
1095
1093
|
|
|
1096
|
-
|
|
1094
|
+
if ( material !== null ) {
|
|
1097
1095
|
|
|
1098
|
-
|
|
1096
|
+
NodeMaterial.fromMaterial( material ).build( this );
|
|
1099
1097
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
this.addFlow( 'compute', object );
|
|
1098
|
+
} else {
|
|
1103
1099
|
|
|
1104
|
-
|
|
1100
|
+
this.addFlow( 'compute', object );
|
|
1105
1101
|
|
|
1106
1102
|
}
|
|
1107
1103
|
|
|
@@ -62,11 +62,21 @@ export const sheenRoughness = nodeImmutable( PropertyNode, 'float', 'SheenRoughn
|
|
|
62
62
|
export const iridescence = nodeImmutable( PropertyNode, 'float', 'Iridescence' );
|
|
63
63
|
export const iridescenceIOR = nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' );
|
|
64
64
|
export const iridescenceThickness = nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' );
|
|
65
|
+
export const alphaT = nodeImmutable( PropertyNode, 'float', 'AlphaT' );
|
|
66
|
+
export const anisotropy = nodeImmutable( PropertyNode, 'float', 'Anisotropy' );
|
|
67
|
+
export const anisotropyT = nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' );
|
|
68
|
+
export const anisotropyB = nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' );
|
|
65
69
|
export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
|
|
70
|
+
export const specularF90 = nodeImmutable( PropertyNode, 'float', 'SpecularF90' );
|
|
66
71
|
export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
|
|
67
72
|
export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
|
|
68
73
|
export const dashSize = nodeImmutable( PropertyNode, 'float', 'dashSize' );
|
|
69
74
|
export const gapSize = nodeImmutable( PropertyNode, 'float', 'gapSize' );
|
|
70
75
|
export const pointWidth = nodeImmutable( PropertyNode, 'float', 'pointWidth' );
|
|
76
|
+
export const ior = nodeImmutable( PropertyNode, 'float', 'IOR' );
|
|
77
|
+
export const transmission = nodeImmutable( PropertyNode, 'float', 'Transmission' );
|
|
78
|
+
export const thickness = nodeImmutable( PropertyNode, 'float', 'Thickness' );
|
|
79
|
+
export const attenuationDistance = nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' );
|
|
80
|
+
export const attenuationColor = nodeImmutable( PropertyNode, 'color', 'AttenuationColor' );
|
|
71
81
|
|
|
72
82
|
addNodeClass( 'PropertyNode', PropertyNode );
|
|
@@ -9,41 +9,22 @@ import { addNodeElement, tslFn, nodeProxy, float, vec2 } from '../shadernode/Sha
|
|
|
9
9
|
// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
|
|
10
10
|
// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
|
|
11
11
|
|
|
12
|
-
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
|
13
|
-
|
|
14
12
|
const dHdxy_fwd = tslFn( ( { textureNode, bumpScale } ) => {
|
|
15
13
|
|
|
16
|
-
let texNode = textureNode;
|
|
17
|
-
|
|
18
|
-
if ( texNode.isTextureNode !== true ) {
|
|
19
|
-
|
|
20
|
-
texNode.traverse( ( node ) => {
|
|
21
|
-
|
|
22
|
-
if ( node.isTextureNode === true ) texNode = node;
|
|
23
|
-
|
|
24
|
-
} );
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if ( texNode.isTextureNode !== true ) {
|
|
29
|
-
|
|
30
|
-
throw new Error( 'THREE.TSL: dHdxy_fwd() requires a TextureNode.' );
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const Hll = float( textureNode );
|
|
35
|
-
const uvNode = texNode.uvNode || uv();
|
|
36
|
-
|
|
37
14
|
// It's used to preserve the same TextureNode instance
|
|
38
|
-
const sampleTexture = (
|
|
15
|
+
const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } );
|
|
16
|
+
|
|
17
|
+
const Hll = float( sampleTexture( ( uvNode ) => uvNode ) );
|
|
39
18
|
|
|
40
19
|
return vec2(
|
|
41
|
-
float( sampleTexture( uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
|
|
42
|
-
float( sampleTexture( uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
|
|
20
|
+
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
|
|
21
|
+
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
|
|
43
22
|
).mul( bumpScale );
|
|
44
23
|
|
|
45
24
|
} );
|
|
46
25
|
|
|
26
|
+
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
|
|
27
|
+
|
|
47
28
|
const perturbNormalArb = tslFn( ( inputs ) => {
|
|
48
29
|
|
|
49
30
|
const { surf_pos, surf_norm, dHdxy } = inputs;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Node, { addNodeClass } from '../core/Node.js';
|
|
2
2
|
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';
|
|
3
|
+
import { BackSide, WebGLCoordinateSystem } from 'three';
|
|
3
4
|
|
|
4
5
|
class FrontFacingNode extends Node {
|
|
5
6
|
|
|
@@ -13,6 +14,18 @@ class FrontFacingNode extends Node {
|
|
|
13
14
|
|
|
14
15
|
generate( builder ) {
|
|
15
16
|
|
|
17
|
+
const { renderer, material } = builder;
|
|
18
|
+
|
|
19
|
+
if ( renderer.coordinateSystem === WebGLCoordinateSystem ) {
|
|
20
|
+
|
|
21
|
+
if ( material.side === BackSide ) {
|
|
22
|
+
|
|
23
|
+
return 'false';
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
return builder.getFrontFacing();
|
|
17
30
|
|
|
18
31
|
}
|
|
@@ -75,7 +75,7 @@ export const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).
|
|
|
75
75
|
// NOTE: https://twitter.com/gonnavis/status/1377183786949959682
|
|
76
76
|
|
|
77
77
|
// -near maps to 0; -far maps to 1
|
|
78
|
-
export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div(
|
|
78
|
+
export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) );
|
|
79
79
|
|
|
80
80
|
// maps perspective depth in [ 0, 1 ] to viewZ
|
|
81
81
|
export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) );
|
|
@@ -21,7 +21,9 @@ class ViewportNode extends Node {
|
|
|
21
21
|
|
|
22
22
|
getNodeType() {
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
if ( this.scope === ViewportNode.VIEWPORT ) return 'vec4';
|
|
25
|
+
else if ( this.scope === ViewportNode.COORDINATE ) return 'vec3';
|
|
26
|
+
else return 'vec2';
|
|
25
27
|
|
|
26
28
|
}
|
|
27
29
|
|
|
@@ -99,7 +101,7 @@ class ViewportNode extends Node {
|
|
|
99
101
|
|
|
100
102
|
const resolution = builder.getNodeProperties( viewportResolution ).outputNode.build( builder );
|
|
101
103
|
|
|
102
|
-
coord = `${ builder.getType( '
|
|
104
|
+
coord = `${ builder.getType( 'vec3' ) }( ${ coord }.x, ${ resolution }.y - ${ coord }.y, ${ coord }.z )`;
|
|
103
105
|
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -58,7 +58,10 @@ class ViewportTextureNode extends TextureNode {
|
|
|
58
58
|
|
|
59
59
|
clone() {
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value );
|
|
62
|
+
viewportTextureNode.generateMipmaps = this.generateMipmaps;
|
|
63
|
+
|
|
64
|
+
return viewportTextureNode;
|
|
62
65
|
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import F_Schlick from './F_Schlick.js';
|
|
2
2
|
import V_GGX_SmithCorrelated from './V_GGX_SmithCorrelated.js';
|
|
3
|
+
import V_GGX_SmithCorrelated_Anisotropic from './V_GGX_SmithCorrelated_Anisotropic.js';
|
|
3
4
|
import D_GGX from './D_GGX.js';
|
|
5
|
+
import D_GGX_Anisotropic from './D_GGX_Anisotropic.js';
|
|
4
6
|
import { transformedNormalView } from '../../accessors/NormalNode.js';
|
|
5
7
|
import { positionViewDirection } from '../../accessors/PositionNode.js';
|
|
6
|
-
import { iridescence } from '../../core/PropertyNode.js';
|
|
7
|
-
import { tslFn } from '../../shadernode/ShaderNode.js';
|
|
8
|
+
import { iridescence, alphaT, anisotropyT, anisotropyB } from '../../core/PropertyNode.js';
|
|
9
|
+
import { tslFn, defined } from '../../shadernode/ShaderNode.js';
|
|
8
10
|
|
|
9
11
|
// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility
|
|
10
12
|
const BRDF_GGX = tslFn( ( inputs ) => {
|
|
11
13
|
|
|
12
|
-
const { lightDirection, f0, f90, roughness,
|
|
14
|
+
const { lightDirection, f0, f90, roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY } = inputs;
|
|
13
15
|
|
|
14
16
|
const normalView = inputs.normalView || transformedNormalView;
|
|
15
17
|
|
|
@@ -23,15 +25,32 @@ const BRDF_GGX = tslFn( ( inputs ) => {
|
|
|
23
25
|
const dotVH = positionViewDirection.dot( halfDir ).clamp();
|
|
24
26
|
|
|
25
27
|
let F = F_Schlick( { f0, f90, dotVH } );
|
|
28
|
+
let V, D;
|
|
26
29
|
|
|
27
|
-
if (
|
|
30
|
+
if ( defined( USE_IRIDESCENCE ) ) {
|
|
28
31
|
|
|
29
|
-
F = iridescence.mix( F,
|
|
32
|
+
F = iridescence.mix( F, f );
|
|
30
33
|
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
if ( defined( USE_ANISOTROPY ) ) {
|
|
37
|
+
|
|
38
|
+
const dotTL = anisotropyT.dot( lightDirection );
|
|
39
|
+
const dotTV = anisotropyT.dot( positionViewDirection );
|
|
40
|
+
const dotTH = anisotropyT.dot( halfDir );
|
|
41
|
+
const dotBL = anisotropyB.dot( lightDirection );
|
|
42
|
+
const dotBV = anisotropyB.dot( positionViewDirection );
|
|
43
|
+
const dotBH = anisotropyB.dot( halfDir );
|
|
44
|
+
|
|
45
|
+
V = V_GGX_SmithCorrelated_Anisotropic( { alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } );
|
|
46
|
+
D = D_GGX_Anisotropic( { alphaT, alphaB: alpha, dotNH, dotTH, dotBH } );
|
|
47
|
+
|
|
48
|
+
} else {
|
|
49
|
+
|
|
50
|
+
V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } );
|
|
51
|
+
D = D_GGX( { alpha, dotNH } );
|
|
52
|
+
|
|
53
|
+
}
|
|
35
54
|
|
|
36
55
|
return F.mul( V ).mul( D );
|
|
37
56
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { tslFn, float, vec3 } from '../../shadernode/ShaderNode.js';
|
|
2
|
+
|
|
3
|
+
const RECIPROCAL_PI = float( 1 / Math.PI );
|
|
4
|
+
|
|
5
|
+
// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf
|
|
6
|
+
|
|
7
|
+
const D_GGX_Anisotropic = tslFn( ( { alphaT, alphaB, dotNH, dotTH, dotBH } ) => {
|
|
8
|
+
|
|
9
|
+
const a2 = alphaT.mul( alphaB );
|
|
10
|
+
const v = vec3( alphaB.mul( dotTH ), alphaT.mul( dotBH ), a2.mul( dotNH ) );
|
|
11
|
+
const v2 = v.dot( v );
|
|
12
|
+
const w2 = a2.div( v2 );
|
|
13
|
+
|
|
14
|
+
return RECIPROCAL_PI.mul( a2.mul( w2.pow2() ) );
|
|
15
|
+
|
|
16
|
+
} ).setLayout( {
|
|
17
|
+
name: 'D_GGX_Anisotropic',
|
|
18
|
+
type: 'float',
|
|
19
|
+
inputs: [
|
|
20
|
+
{ name: 'alphaT', type: 'float', qualifier: 'in' },
|
|
21
|
+
{ name: 'alphaB', type: 'float', qualifier: 'in' },
|
|
22
|
+
{ name: 'dotNH', type: 'float', qualifier: 'in' },
|
|
23
|
+
{ name: 'dotTH', type: 'float', qualifier: 'in' },
|
|
24
|
+
{ name: 'dotBH', type: 'float', qualifier: 'in' }
|
|
25
|
+
]
|
|
26
|
+
} );
|
|
27
|
+
|
|
28
|
+
export default D_GGX_Anisotropic;
|
|
@@ -4,9 +4,7 @@ import { tslFn } from '../../shadernode/ShaderNode.js';
|
|
|
4
4
|
|
|
5
5
|
// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2
|
|
6
6
|
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
|
7
|
-
const V_GGX_SmithCorrelated = tslFn( (
|
|
8
|
-
|
|
9
|
-
const { alpha, dotNL, dotNV } = inputs;
|
|
7
|
+
const V_GGX_SmithCorrelated = tslFn( ( { alpha, dotNL, dotNV } ) => {
|
|
10
8
|
|
|
11
9
|
const a2 = alpha.pow2();
|
|
12
10
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { div } from '../../math/OperatorNode.js';
|
|
2
|
+
import { tslFn, vec3 } from '../../shadernode/ShaderNode.js';
|
|
3
|
+
|
|
4
|
+
// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf
|
|
5
|
+
|
|
6
|
+
const V_GGX_SmithCorrelated_Anisotropic = tslFn( ( { alphaT, alphaB, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ) => {
|
|
7
|
+
|
|
8
|
+
const gv = dotNL.mul( vec3( alphaT.mul( dotTV ), alphaB.mul( dotBV ), dotNV ).length() );
|
|
9
|
+
const gl = dotNV.mul( vec3( alphaT.mul( dotTL ), alphaB.mul( dotBL ), dotNL ).length() );
|
|
10
|
+
const v = div( 0.5, gv.add( gl ) );
|
|
11
|
+
|
|
12
|
+
return v.saturate();
|
|
13
|
+
|
|
14
|
+
} ).setLayout( {
|
|
15
|
+
name: 'V_GGX_SmithCorrelated_Anisotropic',
|
|
16
|
+
type: 'float',
|
|
17
|
+
inputs: [
|
|
18
|
+
{ name: 'alphaT', type: 'float', qualifier: 'in' },
|
|
19
|
+
{ name: 'alphaB', type: 'float', qualifier: 'in' },
|
|
20
|
+
{ name: 'dotTV', type: 'float', qualifier: 'in' },
|
|
21
|
+
{ name: 'dotBV', type: 'float', qualifier: 'in' },
|
|
22
|
+
{ name: 'dotTL', type: 'float', qualifier: 'in' },
|
|
23
|
+
{ name: 'dotBL', type: 'float', qualifier: 'in' },
|
|
24
|
+
{ name: 'dotNV', type: 'float', qualifier: 'in' },
|
|
25
|
+
{ name: 'dotNL', type: 'float', qualifier: 'in' }
|
|
26
|
+
]
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
export default V_GGX_SmithCorrelated_Anisotropic;
|
|
@@ -12,7 +12,7 @@ const G_BlinnPhong_Implicit = () => float( 0.25 );
|
|
|
12
12
|
|
|
13
13
|
const D_BlinnPhong = tslFn( ( { dotNH } ) => {
|
|
14
14
|
|
|
15
|
-
return shininess.mul( 0.5
|
|
15
|
+
return shininess.mul( float( 0.5 ) ).add( 1.0 ).mul( float( 1 / Math.PI ) ).mul( dotNH.pow( shininess ) );
|
|
16
16
|
|
|
17
17
|
} );
|
|
18
18
|
|
|
@@ -6,12 +6,135 @@ import F_Schlick from './BSDF/F_Schlick.js';
|
|
|
6
6
|
import Schlick_to_F0 from './BSDF/Schlick_to_F0.js';
|
|
7
7
|
import BRDF_Sheen from './BSDF/BRDF_Sheen.js';
|
|
8
8
|
import LightingModel from '../core/LightingModel.js';
|
|
9
|
-
import { diffuseColor, specularColor, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js';
|
|
10
|
-
import { transformedNormalView, transformedClearcoatNormalView } from '../accessors/NormalNode.js';
|
|
11
|
-
import { positionViewDirection } from '../accessors/PositionNode.js';
|
|
12
|
-
import { tslFn, float, vec3, mat3 } from '../shadernode/ShaderNode.js';
|
|
9
|
+
import { diffuseColor, specularColor, specularF90, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, ior, thickness, transmission, attenuationDistance, attenuationColor } from '../core/PropertyNode.js';
|
|
10
|
+
import { transformedNormalView, transformedClearcoatNormalView, transformedNormalWorld } from '../accessors/NormalNode.js';
|
|
11
|
+
import { positionViewDirection, positionWorld } from '../accessors/PositionNode.js';
|
|
12
|
+
import { tslFn, float, vec2, vec3, vec4, mat3, If } from '../shadernode/ShaderNode.js';
|
|
13
13
|
import { cond } from '../math/CondNode.js';
|
|
14
|
-
import { mix, smoothstep } from '../math/MathNode.js';
|
|
14
|
+
import { mix, normalize, refract, length, clamp, log2, log, exp, smoothstep } from '../math/MathNode.js';
|
|
15
|
+
import { div } from '../math/OperatorNode.js';
|
|
16
|
+
import { cameraPosition, cameraProjectionMatrix, cameraViewMatrix } from '../accessors/CameraNode.js';
|
|
17
|
+
import { modelWorldMatrix } from '../accessors/ModelNode.js';
|
|
18
|
+
import { viewportResolution } from '../display/ViewportNode.js';
|
|
19
|
+
import { viewportMipTexture } from '../display/ViewportTextureNode.js';
|
|
20
|
+
|
|
21
|
+
//
|
|
22
|
+
// Transmission
|
|
23
|
+
//
|
|
24
|
+
|
|
25
|
+
const getVolumeTransmissionRay = tslFn( ( [ n, v, thickness, ior, modelMatrix ] ) => {
|
|
26
|
+
|
|
27
|
+
// Direction of refracted light.
|
|
28
|
+
const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) );
|
|
29
|
+
|
|
30
|
+
// Compute rotation-independant scaling of the model matrix.
|
|
31
|
+
const modelScale = vec3(
|
|
32
|
+
length( modelMatrix[ 0 ].xyz ),
|
|
33
|
+
length( modelMatrix[ 1 ].xyz ),
|
|
34
|
+
length( modelMatrix[ 2 ].xyz )
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// The thickness is specified in local space.
|
|
38
|
+
return normalize( refractionVector ).mul( thickness.mul( modelScale ) );
|
|
39
|
+
|
|
40
|
+
} ).setLayout( {
|
|
41
|
+
name: 'getVolumeTransmissionRay',
|
|
42
|
+
type: 'vec3',
|
|
43
|
+
inputs: [
|
|
44
|
+
{ name: 'n', type: 'vec3' },
|
|
45
|
+
{ name: 'v', type: 'vec3' },
|
|
46
|
+
{ name: 'thickness', type: 'float' },
|
|
47
|
+
{ name: 'ior', type: 'float' },
|
|
48
|
+
{ name: 'modelMatrix', type: 'mat4' }
|
|
49
|
+
]
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
const applyIorToRoughness = tslFn( ( [ roughness, ior ] ) => {
|
|
53
|
+
|
|
54
|
+
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
|
|
55
|
+
// an IOR of 1.5 results in the default amount of microfacet refraction.
|
|
56
|
+
return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) );
|
|
57
|
+
|
|
58
|
+
} ).setLayout( {
|
|
59
|
+
name: 'applyIorToRoughness',
|
|
60
|
+
type: 'float',
|
|
61
|
+
inputs: [
|
|
62
|
+
{ name: 'roughness', type: 'float' },
|
|
63
|
+
{ name: 'ior', type: 'float' }
|
|
64
|
+
]
|
|
65
|
+
} );
|
|
66
|
+
|
|
67
|
+
const singleViewportMipTexture = viewportMipTexture();
|
|
68
|
+
|
|
69
|
+
const getTransmissionSample = tslFn( ( [ fragCoord, roughness, ior ] ) => {
|
|
70
|
+
|
|
71
|
+
const transmissionSample = singleViewportMipTexture.uv( fragCoord );
|
|
72
|
+
//const transmissionSample = viewportMipTexture( fragCoord );
|
|
73
|
+
|
|
74
|
+
const lod = log2( float( viewportResolution.x ) ).mul( applyIorToRoughness( roughness, ior ) );
|
|
75
|
+
|
|
76
|
+
return transmissionSample.bicubic( lod );
|
|
77
|
+
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
const volumeAttenuation = tslFn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => {
|
|
81
|
+
|
|
82
|
+
If( attenuationDistance.notEqual( 0 ), () => {
|
|
83
|
+
|
|
84
|
+
// Compute light attenuation using Beer's law.
|
|
85
|
+
const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance );
|
|
86
|
+
const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) );
|
|
87
|
+
|
|
88
|
+
return transmittance;
|
|
89
|
+
|
|
90
|
+
} );
|
|
91
|
+
|
|
92
|
+
// Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all.
|
|
93
|
+
return vec3( 1.0 );
|
|
94
|
+
|
|
95
|
+
} ).setLayout( {
|
|
96
|
+
name: 'volumeAttenuation',
|
|
97
|
+
type: 'vec3',
|
|
98
|
+
inputs: [
|
|
99
|
+
{ name: 'transmissionDistance', type: 'float' },
|
|
100
|
+
{ name: 'attenuationColor', type: 'vec3' },
|
|
101
|
+
{ name: 'attenuationDistance', type: 'float' }
|
|
102
|
+
]
|
|
103
|
+
} );
|
|
104
|
+
|
|
105
|
+
const getIBLVolumeRefraction = tslFn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance ] ) => {
|
|
106
|
+
|
|
107
|
+
const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );
|
|
108
|
+
const refractedRayExit = position.add( transmissionRay );
|
|
109
|
+
|
|
110
|
+
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates.
|
|
111
|
+
const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) );
|
|
112
|
+
const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar();
|
|
113
|
+
refractionCoords.addAssign( 1.0 );
|
|
114
|
+
refractionCoords.divAssign( 2.0 );
|
|
115
|
+
refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu
|
|
116
|
+
|
|
117
|
+
// Sample framebuffer to get pixel the refracted ray hits.
|
|
118
|
+
const transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );
|
|
119
|
+
const transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) );
|
|
120
|
+
const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb );
|
|
121
|
+
const dotNV = n.dot( v ).clamp();
|
|
122
|
+
|
|
123
|
+
// Get the specular component.
|
|
124
|
+
const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness
|
|
125
|
+
dotNV,
|
|
126
|
+
specularColor,
|
|
127
|
+
specularF90,
|
|
128
|
+
roughness
|
|
129
|
+
} ) );
|
|
130
|
+
|
|
131
|
+
// As less light is transmitted, the opacity should be increased. This simple approximation does a decent job
|
|
132
|
+
// of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color.
|
|
133
|
+
const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 );
|
|
134
|
+
|
|
135
|
+
return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() );
|
|
136
|
+
|
|
137
|
+
} );
|
|
15
138
|
|
|
16
139
|
//
|
|
17
140
|
// Iridescence
|
|
@@ -172,13 +295,15 @@ const clearcoatF90 = vec3( 1 );
|
|
|
172
295
|
|
|
173
296
|
class PhysicalLightingModel extends LightingModel {
|
|
174
297
|
|
|
175
|
-
constructor( clearcoat = false, sheen = false, iridescence = false ) {
|
|
298
|
+
constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false ) {
|
|
176
299
|
|
|
177
300
|
super();
|
|
178
301
|
|
|
179
302
|
this.clearcoat = clearcoat;
|
|
180
303
|
this.sheen = sheen;
|
|
181
304
|
this.iridescence = iridescence;
|
|
305
|
+
this.anisotropy = anisotropy;
|
|
306
|
+
this.transmission = transmission;
|
|
182
307
|
|
|
183
308
|
this.clearcoatRadiance = null;
|
|
184
309
|
this.clearcoatSpecularDirect = null;
|
|
@@ -190,7 +315,7 @@ class PhysicalLightingModel extends LightingModel {
|
|
|
190
315
|
|
|
191
316
|
}
|
|
192
317
|
|
|
193
|
-
start(
|
|
318
|
+
start( context ) {
|
|
194
319
|
|
|
195
320
|
if ( this.clearcoat === true ) {
|
|
196
321
|
|
|
@@ -223,13 +348,42 @@ class PhysicalLightingModel extends LightingModel {
|
|
|
223
348
|
|
|
224
349
|
}
|
|
225
350
|
|
|
351
|
+
if ( this.transmission === true ) {
|
|
352
|
+
|
|
353
|
+
const position = positionWorld;
|
|
354
|
+
const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX
|
|
355
|
+
const n = transformedNormalWorld;
|
|
356
|
+
|
|
357
|
+
context.backdrop = getIBLVolumeRefraction(
|
|
358
|
+
n,
|
|
359
|
+
v,
|
|
360
|
+
roughness,
|
|
361
|
+
diffuseColor,
|
|
362
|
+
specularColor,
|
|
363
|
+
specularF90, // specularF90
|
|
364
|
+
position, // positionWorld
|
|
365
|
+
modelWorldMatrix, // modelMatrix
|
|
366
|
+
cameraViewMatrix, // viewMatrix
|
|
367
|
+
cameraProjectionMatrix, // projMatrix
|
|
368
|
+
ior,
|
|
369
|
+
thickness,
|
|
370
|
+
attenuationColor,
|
|
371
|
+
attenuationDistance
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
context.backdropAlpha = transmission;
|
|
375
|
+
|
|
376
|
+
diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) );
|
|
377
|
+
|
|
378
|
+
}
|
|
379
|
+
|
|
226
380
|
}
|
|
227
381
|
|
|
228
382
|
// Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
|
|
229
383
|
// Approximates multiscattering in order to preserve energy.
|
|
230
384
|
// http://www.jcgt.org/published/0008/01/03/
|
|
231
385
|
|
|
232
|
-
computeMultiscattering( singleScatter, multiScatter, specularF90
|
|
386
|
+
computeMultiscattering( singleScatter, multiScatter, specularF90 ) {
|
|
233
387
|
|
|
234
388
|
const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
|
|
235
389
|
|
|
@@ -272,7 +426,7 @@ class PhysicalLightingModel extends LightingModel {
|
|
|
272
426
|
|
|
273
427
|
reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
|
|
274
428
|
|
|
275
|
-
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence,
|
|
429
|
+
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) );
|
|
276
430
|
|
|
277
431
|
}
|
|
278
432
|
|
|
@@ -318,7 +472,7 @@ class PhysicalLightingModel extends LightingModel {
|
|
|
318
472
|
const multiScattering = vec3().temp( 'multiScattering' );
|
|
319
473
|
const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
|
|
320
474
|
|
|
321
|
-
this.computeMultiscattering( singleScattering, multiScattering );
|
|
475
|
+
this.computeMultiscattering( singleScattering, multiScattering, specularF90 );
|
|
322
476
|
|
|
323
477
|
const totalScattering = singleScattering.add( multiScattering );
|
|
324
478
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import LightingModel from '../core/LightingModel.js';
|
|
2
|
+
import { diffuseColor } from '../core/PropertyNode.js';
|
|
3
|
+
import { float } from '../shadernode/ShaderNode.js';
|
|
4
|
+
|
|
5
|
+
class ShadowMaskModel extends LightingModel {
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
|
|
9
|
+
super();
|
|
10
|
+
|
|
11
|
+
this.shadowNode = float( 1 ).toVar( 'shadowMask' );
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
direct( { shadowMask } ) {
|
|
16
|
+
|
|
17
|
+
this.shadowNode.mulAssign( shadowMask );
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
finish( context ) {
|
|
22
|
+
|
|
23
|
+
diffuseColor.a.mulAssign( this.shadowNode.oneMinus() );
|
|
24
|
+
|
|
25
|
+
context.outgoingLight.rgb.assign( diffuseColor.rgb ); // TODO: Optimize LightsNode to avoid this assignment
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default ShadowMaskModel;
|