three-gpu-pathtracer 0.0.14 → 0.0.16
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/LICENSE +21 -21
- package/README.md +1004 -981
- package/build/index.module.js +7413 -6902
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +7446 -6933
- package/build/index.umd.cjs.map +1 -1
- package/package.json +73 -73
- package/src/core/DynamicPathTracingSceneGenerator.js +119 -119
- package/src/core/MaterialReducer.js +256 -256
- package/src/core/PathTracingRenderer.js +346 -346
- package/src/core/PathTracingSceneGenerator.js +69 -69
- package/src/core/QuiltPathTracingRenderer.js +223 -223
- package/src/detectors/CompatibilityDetector.js +38 -0
- package/src/detectors/MaterialCompileDetector.js +50 -0
- package/src/detectors/PrecisionDetector.js +85 -0
- package/src/detectors/PrecisionMaterial.js +160 -0
- package/src/index.js +40 -36
- package/src/materials/MaterialBase.js +56 -56
- package/src/materials/debug/GraphMaterial.js +243 -243
- package/src/materials/fullscreen/AlphaDisplayMaterial.js +50 -48
- package/src/materials/fullscreen/BlendMaterial.js +67 -67
- package/src/materials/fullscreen/DenoiseMaterial.js +142 -142
- package/src/materials/fullscreen/GradientMapMaterial.js +82 -0
- package/src/materials/pathtracing/LambertPathTracingMaterial.js +296 -296
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +118 -196
- package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +177 -179
- package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +84 -81
- package/src/materials/pathtracing/glsl/directLightContribution.glsl.js +93 -0
- package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +323 -317
- package/src/materials/pathtracing/glsl/renderStructs.glsl.js +50 -0
- package/src/materials/pathtracing/glsl/traceScene.glsl.js +52 -54
- package/src/materials/surface/AmbientOcclusionMaterial.js +207 -207
- package/src/materials/surface/FogVolumeMaterial.js +23 -23
- package/src/objects/EquirectCamera.js +13 -13
- package/src/objects/PhysicalCamera.js +42 -28
- package/src/objects/PhysicalSpotLight.js +25 -14
- package/src/objects/ShapedAreaLight.js +22 -12
- package/src/shader/bsdf/bsdfSampling.glsl.js +499 -490
- package/src/shader/bsdf/fog.glsl.js +22 -23
- package/src/shader/bsdf/ggx.glsl.js +102 -102
- package/src/shader/bsdf/iridescence.glsl.js +135 -135
- package/src/shader/bsdf/sheen.glsl.js +98 -98
- package/src/shader/common/arraySamplerTexelFetch.glsl.js +25 -25
- package/src/shader/common/bvhAnyHit.glsl.js +76 -76
- package/src/shader/common/fresnel.glsl.js +98 -98
- package/src/shader/common/intersectShapes.glsl.js +62 -62
- package/src/shader/common/math.glsl.js +81 -81
- package/src/shader/common/utils.glsl.js +116 -116
- package/src/shader/rand/pcg.glsl.js +57 -57
- package/src/shader/rand/sobol.glsl.js +256 -256
- package/src/shader/sampling/equirectSampling.glsl.js +62 -62
- package/src/shader/sampling/lightSampling.glsl.js +223 -223
- package/src/shader/sampling/shapeSampling.glsl.js +86 -86
- package/src/shader/structs/cameraStruct.glsl.js +13 -13
- package/src/shader/structs/equirectStruct.glsl.js +13 -14
- package/src/shader/structs/fogMaterialBvh.glsl.js +62 -62
- package/src/shader/structs/lightsStruct.glsl.js +78 -78
- package/src/shader/structs/materialStruct.glsl.js +207 -207
- package/src/textures/GradientEquirectTexture.js +35 -35
- package/src/textures/ProceduralEquirectTexture.js +75 -75
- package/src/uniforms/AttributesTextureArray.js +35 -35
- package/src/uniforms/EquirectHdrInfoUniform.js +269 -277
- package/src/uniforms/FloatAttributeTextureArray.js +169 -169
- package/src/uniforms/IESProfilesTexture.js +100 -100
- package/src/uniforms/LightsInfoUniformStruct.js +212 -212
- package/src/uniforms/MaterialsTexture.js +503 -503
- package/src/uniforms/PhysicalCameraUniform.js +36 -36
- package/src/uniforms/RenderTarget2DArray.js +97 -97
- package/src/uniforms/utils.js +30 -30
- package/src/utils/BlurredEnvMapGenerator.js +116 -116
- package/src/utils/GeometryPreparationUtils.js +214 -214
- package/src/utils/IESLoader.js +325 -325
- package/src/utils/SobolNumberMapGenerator.js +80 -80
- package/src/utils/UVUnwrapper.js +101 -101
- package/src/utils/macroify.js +9 -9
- package/src/workers/PathTracingSceneWorker.js +42 -42
|
@@ -1,179 +1,177 @@
|
|
|
1
|
-
export const attenuateHitGLSL = /* glsl */`
|
|
2
|
-
|
|
3
|
-
// step through multiple surface hits and accumulate color attenuation based on transmissive surfaces
|
|
4
|
-
// returns true if a solid surface was hit
|
|
5
|
-
bool attenuateHit(
|
|
6
|
-
BVH bvh,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
vec3
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
color = vec3( 1.0 );
|
|
23
|
-
|
|
24
|
-
// TODO: we should be using sobol sampling here instead of rand but the sobol bounce and path indices need to be incremented
|
|
25
|
-
// and then reset.
|
|
26
|
-
for ( int i = 0; i < traversals; i ++ ) {
|
|
27
|
-
|
|
28
|
-
int hitType = traceScene(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// TODO:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
float
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
`;
|
|
1
|
+
export const attenuateHitGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
// step through multiple surface hits and accumulate color attenuation based on transmissive surfaces
|
|
4
|
+
// returns true if a solid surface was hit
|
|
5
|
+
bool attenuateHit(
|
|
6
|
+
BVH bvh, RenderState state,
|
|
7
|
+
Ray ray, float rayDist,
|
|
8
|
+
out vec3 color
|
|
9
|
+
) {
|
|
10
|
+
|
|
11
|
+
int traversals = state.traversals;
|
|
12
|
+
int transmissiveTraversals = state.transmissiveTraversals;
|
|
13
|
+
bool isShadowRay = state.isShadowRay;
|
|
14
|
+
Material fogMaterial = state.fogMaterial;
|
|
15
|
+
|
|
16
|
+
vec3 startPoint = ray.origin;
|
|
17
|
+
|
|
18
|
+
// hit results
|
|
19
|
+
SurfaceHit surfaceHit;
|
|
20
|
+
LightRecord lightRec;
|
|
21
|
+
|
|
22
|
+
color = vec3( 1.0 );
|
|
23
|
+
|
|
24
|
+
// TODO: we should be using sobol sampling here instead of rand but the sobol bounce and path indices need to be incremented
|
|
25
|
+
// and then reset.
|
|
26
|
+
for ( int i = 0; i < traversals; i ++ ) {
|
|
27
|
+
|
|
28
|
+
int hitType = traceScene(
|
|
29
|
+
ray, bvh, lights, fogMaterial,
|
|
30
|
+
surfaceHit, lightRec
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if ( hitType == FOG_HIT ) {
|
|
34
|
+
|
|
35
|
+
return true;
|
|
36
|
+
|
|
37
|
+
} else if ( hitType == LIGHT_HIT ) {
|
|
38
|
+
|
|
39
|
+
float totalDist = distance( startPoint, ray.origin + ray.direction * lightRec.dist );
|
|
40
|
+
return totalDist < rayDist - max( totalDist, rayDist ) * 1e-4;
|
|
41
|
+
|
|
42
|
+
} else if ( hitType == SURFACE_HIT ) {
|
|
43
|
+
|
|
44
|
+
float totalDist = distance( startPoint, ray.origin + ray.direction * surfaceHit.dist );
|
|
45
|
+
if ( totalDist > rayDist ) {
|
|
46
|
+
|
|
47
|
+
return false;
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// TODO: attenuate the contribution based on the PDF of the resulting ray including refraction values
|
|
52
|
+
// Should be able to work using the material BSDF functions which will take into account specularity, etc.
|
|
53
|
+
// TODO: should we account for emissive surfaces here?
|
|
54
|
+
|
|
55
|
+
uint materialIndex = uTexelFetch1D( materialIndexAttribute, surfaceHit.faceIndices.x ).r;
|
|
56
|
+
Material material = readMaterialInfo( materials, materialIndex );
|
|
57
|
+
|
|
58
|
+
// adjust the ray to the new surface
|
|
59
|
+
bool isEntering = surfaceHit.side == 1.0;
|
|
60
|
+
ray.origin = stepRayOrigin( ray.origin, ray.direction, - surfaceHit.faceNormal, surfaceHit.dist );
|
|
61
|
+
|
|
62
|
+
#if FEATURE_FOG
|
|
63
|
+
|
|
64
|
+
if ( material.fogVolume ) {
|
|
65
|
+
|
|
66
|
+
fogMaterial = material;
|
|
67
|
+
fogMaterial.fogVolume = surfaceHit.side == 1.0;
|
|
68
|
+
i -= sign( transmissiveTraversals );
|
|
69
|
+
transmissiveTraversals --;
|
|
70
|
+
continue;
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#endif
|
|
75
|
+
|
|
76
|
+
if ( ! material.castShadow && isShadowRay ) {
|
|
77
|
+
|
|
78
|
+
continue;
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
vec2 uv = textureSampleBarycoord( attributesArray, ATTR_UV, surfaceHit.barycoord, surfaceHit.faceIndices.xyz ).xy;
|
|
83
|
+
vec4 vertexColor = textureSampleBarycoord( attributesArray, ATTR_COLOR, surfaceHit.barycoord, surfaceHit.faceIndices.xyz );
|
|
84
|
+
|
|
85
|
+
// albedo
|
|
86
|
+
vec4 albedo = vec4( material.color, material.opacity );
|
|
87
|
+
if ( material.map != - 1 ) {
|
|
88
|
+
|
|
89
|
+
vec3 uvPrime = material.mapTransform * vec3( uv, 1 );
|
|
90
|
+
albedo *= texture2D( textures, vec3( uvPrime.xy, material.map ) );
|
|
91
|
+
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if ( material.vertexColors ) {
|
|
95
|
+
|
|
96
|
+
albedo *= vertexColor;
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// alphaMap
|
|
101
|
+
if ( material.alphaMap != - 1 ) {
|
|
102
|
+
|
|
103
|
+
albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
|
|
104
|
+
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// transmission
|
|
108
|
+
float transmission = material.transmission;
|
|
109
|
+
if ( material.transmissionMap != - 1 ) {
|
|
110
|
+
|
|
111
|
+
vec3 uvPrime = material.transmissionMapTransform * vec3( uv, 1 );
|
|
112
|
+
transmission *= texture2D( textures, vec3( uvPrime.xy, material.transmissionMap ) ).r;
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// metalness
|
|
117
|
+
float metalness = material.metalness;
|
|
118
|
+
if ( material.metalnessMap != - 1 ) {
|
|
119
|
+
|
|
120
|
+
vec3 uvPrime = material.metalnessMapTransform * vec3( uv, 1 );
|
|
121
|
+
metalness *= texture2D( textures, vec3( uvPrime.xy, material.metalnessMap ) ).b;
|
|
122
|
+
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
float alphaTest = material.alphaTest;
|
|
126
|
+
bool useAlphaTest = alphaTest != 0.0;
|
|
127
|
+
float transmissionFactor = ( 1.0 - metalness ) * transmission;
|
|
128
|
+
if (
|
|
129
|
+
transmissionFactor < rand() && ! (
|
|
130
|
+
// material sidedness
|
|
131
|
+
material.side != 0.0 && surfaceHit.side == material.side
|
|
132
|
+
|
|
133
|
+
// alpha test
|
|
134
|
+
|| useAlphaTest && albedo.a < alphaTest
|
|
135
|
+
|
|
136
|
+
// opacity
|
|
137
|
+
|| material.transparent && ! useAlphaTest && albedo.a < rand()
|
|
138
|
+
)
|
|
139
|
+
) {
|
|
140
|
+
|
|
141
|
+
return true;
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if ( surfaceHit.side == 1.0 && isEntering ) {
|
|
146
|
+
|
|
147
|
+
// only attenuate by surface color on the way in
|
|
148
|
+
color *= mix( vec3( 1.0 ), albedo.rgb, transmissionFactor );
|
|
149
|
+
|
|
150
|
+
} else if ( surfaceHit.side == - 1.0 ) {
|
|
151
|
+
|
|
152
|
+
// attenuate by medium once we hit the opposite side of the model
|
|
153
|
+
color *= transmissionAttenuation( surfaceHit.dist, material.attenuationColor, material.attenuationDistance );
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
bool isTransmissiveRay = dot( ray.direction, surfaceHit.faceNormal * surfaceHit.side ) < 0.0;
|
|
158
|
+
if ( ( isTransmissiveRay || isEntering ) && transmissiveTraversals > 0 ) {
|
|
159
|
+
|
|
160
|
+
i -= sign( transmissiveTraversals );
|
|
161
|
+
transmissiveTraversals --;
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
} else {
|
|
166
|
+
|
|
167
|
+
return false;
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return true;
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
`;
|
|
@@ -1,81 +1,84 @@
|
|
|
1
|
-
export const cameraUtilsGLSL = /* glsl */`
|
|
2
|
-
|
|
3
|
-
vec3 ndcToRayOrigin( vec2 coord ) {
|
|
4
|
-
|
|
5
|
-
vec4 rayOrigin4 = cameraWorldMatrix * invProjectionMatrix * vec4( coord, - 1.0, 1.0 );
|
|
6
|
-
return rayOrigin4.xyz / rayOrigin4.w;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
vec2 ssd = vec2( 1.0 ) / resolution;
|
|
12
|
-
|
|
13
|
-
// Jitter the camera ray by finding a uv coordinate at a random sample
|
|
14
|
-
// around this pixel's UV coordinate for AA
|
|
15
|
-
vec2 ruv = sobol2( 0 );
|
|
16
|
-
vec2 jitteredUv = vUv + vec2( tentFilter( ruv.x ) * ssd.x, tentFilter( ruv.y ) * ssd.y );
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
vec4
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
apertureSample
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
1
|
+
export const cameraUtilsGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
vec3 ndcToRayOrigin( vec2 coord ) {
|
|
4
|
+
|
|
5
|
+
vec4 rayOrigin4 = cameraWorldMatrix * invProjectionMatrix * vec4( coord, - 1.0, 1.0 );
|
|
6
|
+
return rayOrigin4.xyz / rayOrigin4.w;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
Ray getCameraRay() {
|
|
10
|
+
|
|
11
|
+
vec2 ssd = vec2( 1.0 ) / resolution;
|
|
12
|
+
|
|
13
|
+
// Jitter the camera ray by finding a uv coordinate at a random sample
|
|
14
|
+
// around this pixel's UV coordinate for AA
|
|
15
|
+
vec2 ruv = sobol2( 0 );
|
|
16
|
+
vec2 jitteredUv = vUv + vec2( tentFilter( ruv.x ) * ssd.x, tentFilter( ruv.y ) * ssd.y );
|
|
17
|
+
Ray ray;
|
|
18
|
+
|
|
19
|
+
#if CAMERA_TYPE == 2
|
|
20
|
+
|
|
21
|
+
// Equirectangular projection
|
|
22
|
+
vec4 rayDirection4 = vec4( equirectUvToDirection( jitteredUv ), 0.0 );
|
|
23
|
+
vec4 rayOrigin4 = vec4( 0.0, 0.0, 0.0, 1.0 );
|
|
24
|
+
|
|
25
|
+
rayDirection4 = cameraWorldMatrix * rayDirection4;
|
|
26
|
+
rayOrigin4 = cameraWorldMatrix * rayOrigin4;
|
|
27
|
+
|
|
28
|
+
ray.direction = normalize( rayDirection4.xyz );
|
|
29
|
+
ray.origin = rayOrigin4.xyz / rayOrigin4.w;
|
|
30
|
+
|
|
31
|
+
#else
|
|
32
|
+
|
|
33
|
+
// get [- 1, 1] normalized device coordinates
|
|
34
|
+
vec2 ndc = 2.0 * jitteredUv - vec2( 1.0 );
|
|
35
|
+
ray.origin = ndcToRayOrigin( ndc );
|
|
36
|
+
|
|
37
|
+
#if CAMERA_TYPE == 1
|
|
38
|
+
|
|
39
|
+
// Orthographic projection
|
|
40
|
+
ray.direction = ( cameraWorldMatrix * vec4( 0.0, 0.0, - 1.0, 0.0 ) ).xyz;
|
|
41
|
+
ray.direction = normalize( ray.direction );
|
|
42
|
+
|
|
43
|
+
#else
|
|
44
|
+
|
|
45
|
+
// Perspective projection
|
|
46
|
+
ray.direction = normalize( mat3( cameraWorldMatrix ) * ( invProjectionMatrix * vec4( ndc, 0.0, 1.0 ) ).xyz );
|
|
47
|
+
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
#if FEATURE_DOF
|
|
53
|
+
{
|
|
54
|
+
|
|
55
|
+
// depth of field
|
|
56
|
+
vec3 focalPoint = ray.origin + normalize( ray.direction ) * physicalCamera.focusDistance;
|
|
57
|
+
|
|
58
|
+
// get the aperture sample
|
|
59
|
+
// if blades === 0 then we assume a circle
|
|
60
|
+
vec3 shapeUVW= sobol3( 1 );
|
|
61
|
+
int blades = physicalCamera.apertureBlades;
|
|
62
|
+
float anamorphicRatio = physicalCamera.anamorphicRatio;
|
|
63
|
+
vec2 apertureSample = blades == 0 ? sampleCircle( shapeUVW.xy ) : sampleRegularPolygon( blades, shapeUVW );
|
|
64
|
+
apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
|
|
65
|
+
|
|
66
|
+
// rotate the aperture shape
|
|
67
|
+
apertureSample =
|
|
68
|
+
rotateVector( apertureSample, physicalCamera.apertureRotation ) *
|
|
69
|
+
saturate( vec2( anamorphicRatio, 1.0 / anamorphicRatio ) );
|
|
70
|
+
|
|
71
|
+
// create the new ray
|
|
72
|
+
ray.origin += ( cameraWorldMatrix * vec4( apertureSample, 0.0, 0.0 ) ).xyz;
|
|
73
|
+
ray.direction = focalPoint - ray.origin;
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
ray.direction = normalize( ray.direction );
|
|
79
|
+
|
|
80
|
+
return ray;
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
`;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export const directLightContributionGLSL = /*glsl*/`
|
|
2
|
+
|
|
3
|
+
vec3 directLightContribution( vec3 worldWo, SurfaceRecord surf, RenderState state, vec3 rayOrigin ) {
|
|
4
|
+
|
|
5
|
+
// uniformly pick a light or environment map
|
|
6
|
+
if( lightsDenom != 0.0 && sobol( 5 ) < float( lights.count ) / lightsDenom ) {
|
|
7
|
+
|
|
8
|
+
// sample a light or environment
|
|
9
|
+
LightRecord lightRec = randomLightSample( lights.tex, iesProfiles, lights.count, rayOrigin, sobol3( 6 ) );
|
|
10
|
+
|
|
11
|
+
bool isSampleBelowSurface = ! surf.volumeParticle && dot( surf.faceNormal, lightRec.direction ) < 0.0;
|
|
12
|
+
if ( isSampleBelowSurface ) {
|
|
13
|
+
|
|
14
|
+
lightRec.pdf = 0.0;
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// check if a ray could even reach the light area
|
|
19
|
+
Ray lightRay;
|
|
20
|
+
lightRay.origin = rayOrigin;
|
|
21
|
+
lightRay.direction = lightRec.direction;
|
|
22
|
+
vec3 attenuatedColor;
|
|
23
|
+
if (
|
|
24
|
+
lightRec.pdf > 0.0 &&
|
|
25
|
+
isDirectionValid( lightRec.direction, surf.normal, surf.faceNormal ) &&
|
|
26
|
+
! attenuateHit( bvh, state, lightRay, lightRec.dist, attenuatedColor )
|
|
27
|
+
) {
|
|
28
|
+
|
|
29
|
+
// get the material pdf
|
|
30
|
+
vec3 sampleColor;
|
|
31
|
+
float lightMaterialPdf = bsdfResult( worldWo, lightRec.direction, surf, sampleColor );
|
|
32
|
+
bool isValidSampleColor = all( greaterThanEqual( sampleColor, vec3( 0.0 ) ) );
|
|
33
|
+
if ( lightMaterialPdf > 0.0 && isValidSampleColor ) {
|
|
34
|
+
|
|
35
|
+
// weight the direct light contribution
|
|
36
|
+
float lightPdf = lightRec.pdf / lightsDenom;
|
|
37
|
+
float misWeight = lightRec.type == SPOT_LIGHT_TYPE || lightRec.type == DIR_LIGHT_TYPE || lightRec.type == POINT_LIGHT_TYPE ? 1.0 : misHeuristic( lightPdf, lightMaterialPdf );
|
|
38
|
+
return attenuatedColor * lightRec.emission * state.throughputColor * sampleColor * misWeight / lightPdf;
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
} else {
|
|
45
|
+
|
|
46
|
+
// find a sample in the environment map to include in the contribution
|
|
47
|
+
vec3 envColor, envDirection;
|
|
48
|
+
float envPdf = sampleEquirectProbability( envMapInfo, sobol2( 7 ), envColor, envDirection );
|
|
49
|
+
envDirection = invEnvRotation3x3 * envDirection;
|
|
50
|
+
|
|
51
|
+
// this env sampling is not set up for transmissive sampling and yields overly bright
|
|
52
|
+
// results so we ignore the sample in this case.
|
|
53
|
+
// TODO: this should be improved but how? The env samples could traverse a few layers?
|
|
54
|
+
bool isSampleBelowSurface = ! surf.volumeParticle && dot( surf.faceNormal, envDirection ) < 0.0;
|
|
55
|
+
if ( isSampleBelowSurface ) {
|
|
56
|
+
|
|
57
|
+
envPdf = 0.0;
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// check if a ray could even reach the surface
|
|
62
|
+
Ray envRay;
|
|
63
|
+
envRay.origin = rayOrigin;
|
|
64
|
+
envRay.direction = envDirection;
|
|
65
|
+
vec3 attenuatedColor;
|
|
66
|
+
if (
|
|
67
|
+
envPdf > 0.0 &&
|
|
68
|
+
isDirectionValid( envDirection, surf.normal, surf.faceNormal ) &&
|
|
69
|
+
! attenuateHit( bvh, state, envRay, INFINITY, attenuatedColor )
|
|
70
|
+
) {
|
|
71
|
+
|
|
72
|
+
// get the material pdf
|
|
73
|
+
vec3 sampleColor;
|
|
74
|
+
float envMaterialPdf = bsdfResult( worldWo, envDirection, surf, sampleColor );
|
|
75
|
+
bool isValidSampleColor = all( greaterThanEqual( sampleColor, vec3( 0.0 ) ) );
|
|
76
|
+
if ( envMaterialPdf > 0.0 && isValidSampleColor ) {
|
|
77
|
+
|
|
78
|
+
// weight the direct light contribution
|
|
79
|
+
envPdf /= lightsDenom;
|
|
80
|
+
float misWeight = misHeuristic( envPdf, envMaterialPdf );
|
|
81
|
+
return attenuatedColor * environmentIntensity * envColor * state.throughputColor * sampleColor * misWeight / envPdf;
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return vec3( 0.0 );
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
`;
|