three-gpu-pathtracer 0.0.12 → 0.0.14
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 +102 -7
- package/build/index.module.js +2891 -2065
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +2886 -2062
- package/build/index.umd.cjs.map +1 -1
- package/package.json +2 -1
- package/src/core/PathTracingRenderer.js +87 -16
- package/src/core/PathTracingSceneGenerator.js +1 -1
- package/src/core/QuiltPathTracingRenderer.js +223 -0
- package/src/index.js +5 -8
- package/src/materials/{GraphMaterial.js → debug/GraphMaterial.js} +1 -1
- package/src/materials/{AlphaDisplayMaterial.js → fullscreen/AlphaDisplayMaterial.js} +1 -1
- package/src/materials/{BlendMaterial.js → fullscreen/BlendMaterial.js} +1 -1
- package/src/materials/{DenoiseMaterial.js → fullscreen/DenoiseMaterial.js} +1 -1
- package/src/materials/{LambertPathTracingMaterial.js → pathtracing/LambertPathTracingMaterial.js} +18 -7
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +635 -0
- package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +179 -0
- package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +81 -0
- package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +317 -0
- package/src/materials/pathtracing/glsl/traceScene.glsl.js +54 -0
- package/src/materials/{AmbientOcclusionMaterial.js → surface/AmbientOcclusionMaterial.js} +16 -8
- package/src/materials/surface/FogVolumeMaterial.js +23 -0
- package/src/shader/bsdf/bsdfSampling.glsl.js +490 -0
- package/src/shader/bsdf/fog.glsl.js +23 -0
- package/src/shader/bsdf/ggx.glsl.js +102 -0
- package/src/shader/bsdf/iridescence.glsl.js +135 -0
- package/src/shader/bsdf/sheen.glsl.js +98 -0
- package/src/shader/{shaderLayerTexelFetchFunctions.js → common/arraySamplerTexelFetch.glsl.js} +1 -1
- package/src/shader/common/bvhAnyHit.glsl.js +76 -0
- package/src/shader/common/fresnel.glsl.js +98 -0
- package/src/shader/common/intersectShapes.glsl.js +62 -0
- package/src/shader/common/math.glsl.js +81 -0
- package/src/shader/common/utils.glsl.js +116 -0
- package/src/shader/{shaderRandFunctions.js → rand/pcg.glsl.js} +1 -1
- package/src/shader/{shaderSobolSampling.js → rand/sobol.glsl.js} +3 -3
- package/src/shader/sampling/equirectSampling.glsl.js +62 -0
- package/src/shader/sampling/lightSampling.glsl.js +223 -0
- package/src/shader/sampling/shapeSampling.glsl.js +86 -0
- package/src/shader/structs/cameraStruct.glsl.js +13 -0
- package/src/shader/structs/equirectStruct.glsl.js +14 -0
- package/src/shader/structs/fogMaterialBvh.glsl.js +62 -0
- package/src/shader/structs/lightsStruct.glsl.js +78 -0
- package/src/shader/{shaderStructs.js → structs/materialStruct.glsl.js} +5 -123
- package/src/uniforms/EquirectHdrInfoUniform.js +29 -11
- package/src/uniforms/LightsInfoUniformStruct.js +9 -4
- package/src/uniforms/MaterialsTexture.js +80 -3
- package/src/utils/BlurredEnvMapGenerator.js +2 -2
- package/src/utils/SobolNumberMapGenerator.js +3 -3
- package/src/utils/macroify.js +9 -0
- package/src/materials/PhysicalPathTracingMaterial.js +0 -982
- package/src/shader/shaderBvhAnyHit.js +0 -76
- package/src/shader/shaderEnvMapSampling.js +0 -58
- package/src/shader/shaderGGXFunctions.js +0 -100
- package/src/shader/shaderIridescenceFunctions.js +0 -130
- package/src/shader/shaderLightSampling.js +0 -229
- package/src/shader/shaderMaterialSampling.js +0 -506
- package/src/shader/shaderSheenFunctions.js +0 -98
- package/src/shader/shaderUtils.js +0 -361
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const equirectSamplingGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
// samples the the given environment map in the given direction
|
|
4
|
+
vec3 sampleEquirectColor( sampler2D envMap, vec3 direction ) {
|
|
5
|
+
|
|
6
|
+
return texture2D( envMap, equirectDirectionToUv( direction ) ).rgb;
|
|
7
|
+
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// gets the pdf of the given direction to sample
|
|
11
|
+
float equirectDirectionPdf( vec3 direction ) {
|
|
12
|
+
|
|
13
|
+
vec2 uv = equirectDirectionToUv( direction );
|
|
14
|
+
float theta = uv.y * PI;
|
|
15
|
+
float sinTheta = sin( theta );
|
|
16
|
+
if ( sinTheta == 0.0 ) {
|
|
17
|
+
|
|
18
|
+
return 0.0;
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return 1.0 / ( 2.0 * PI * PI * sinTheta );
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// samples the color given env map with CDF and returns the pdf of the direction
|
|
27
|
+
float sampleEquirect( EquirectHdrInfo info, vec3 direction, out vec3 color ) {
|
|
28
|
+
|
|
29
|
+
vec2 uv = equirectDirectionToUv( direction );
|
|
30
|
+
color = texture2D( info.map, uv ).rgb;
|
|
31
|
+
|
|
32
|
+
float totalSum = info.totalSumWhole + info.totalSumDecimal;
|
|
33
|
+
float lum = luminance( color );
|
|
34
|
+
ivec2 resolution = textureSize( info.map, 0 );
|
|
35
|
+
float pdf = lum / totalSum;
|
|
36
|
+
|
|
37
|
+
return float( resolution.x * resolution.y ) * pdf * equirectDirectionPdf( direction );
|
|
38
|
+
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// samples a direction of the envmap with color and retrieves pdf
|
|
42
|
+
float sampleEquirectProbability( EquirectHdrInfo info, vec2 r, out vec3 color, out vec3 direction ) {
|
|
43
|
+
|
|
44
|
+
// sample env map cdf
|
|
45
|
+
float v = texture2D( info.marginalWeights, vec2( r.x, 0.0 ) ).x;
|
|
46
|
+
float u = texture2D( info.conditionalWeights, vec2( r.y, v ) ).x;
|
|
47
|
+
vec2 uv = vec2( u, v );
|
|
48
|
+
|
|
49
|
+
vec3 derivedDirection = equirectUvToDirection( uv );
|
|
50
|
+
direction = derivedDirection;
|
|
51
|
+
color = texture2D( info.map, uv ).rgb;
|
|
52
|
+
|
|
53
|
+
float totalSum = info.totalSumWhole + info.totalSumDecimal;
|
|
54
|
+
float lum = luminance( color );
|
|
55
|
+
ivec2 resolution = textureSize( info.map, 0 );
|
|
56
|
+
float pdf = lum / totalSum;
|
|
57
|
+
|
|
58
|
+
return float( resolution.x * resolution.y ) * pdf * equirectDirectionPdf( direction );
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
`;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
export const lightSamplingGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
float getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {
|
|
4
|
+
|
|
5
|
+
return smoothstep( coneCosine, penumbraCosine, angleCosine );
|
|
6
|
+
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
float getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
|
|
10
|
+
|
|
11
|
+
// based upon Frostbite 3 Moving to Physically-based Rendering
|
|
12
|
+
// page 32, equation 26: E[window1]
|
|
13
|
+
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
|
|
14
|
+
float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), EPSILON );
|
|
15
|
+
|
|
16
|
+
if ( cutoffDistance > 0.0 ) {
|
|
17
|
+
|
|
18
|
+
distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return distanceFalloff;
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
float getPhotometricAttenuation( sampler2DArray iesProfiles, int iesProfile, vec3 posToLight, vec3 lightDir, vec3 u, vec3 v ) {
|
|
27
|
+
|
|
28
|
+
float cosTheta = dot( posToLight, lightDir );
|
|
29
|
+
float angle = acos( cosTheta ) * ( 1.0 / PI );
|
|
30
|
+
|
|
31
|
+
return texture2D( iesProfiles, vec3( 0.0, angle, iesProfile ) ).r;
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
struct LightSampleRecord {
|
|
36
|
+
|
|
37
|
+
float dist;
|
|
38
|
+
vec3 direction;
|
|
39
|
+
float pdf;
|
|
40
|
+
vec3 emission;
|
|
41
|
+
int type;
|
|
42
|
+
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
bool lightsClosestHit( sampler2D lights, uint lightCount, vec3 rayOrigin, vec3 rayDirection, out LightSampleRecord lightSampleRec ) {
|
|
46
|
+
|
|
47
|
+
bool didHit = false;
|
|
48
|
+
uint l;
|
|
49
|
+
for ( l = 0u; l < lightCount; l ++ ) {
|
|
50
|
+
|
|
51
|
+
Light light = readLightInfo( lights, l );
|
|
52
|
+
|
|
53
|
+
vec3 u = light.u;
|
|
54
|
+
vec3 v = light.v;
|
|
55
|
+
|
|
56
|
+
// check for backface
|
|
57
|
+
vec3 normal = normalize( cross( u, v ) );
|
|
58
|
+
if ( dot( normal, rayDirection ) < 0.0 ) {
|
|
59
|
+
|
|
60
|
+
continue;
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
u *= 1.0 / dot( u, u );
|
|
65
|
+
v *= 1.0 / dot( v, v );
|
|
66
|
+
|
|
67
|
+
float dist;
|
|
68
|
+
|
|
69
|
+
// MIS / light intersection is not supported for punctual lights.
|
|
70
|
+
if(
|
|
71
|
+
( light.type == RECT_AREA_LIGHT_TYPE && intersectsRectangle( light.position, normal, u, v, rayOrigin, rayDirection, dist ) ) ||
|
|
72
|
+
( light.type == CIRC_AREA_LIGHT_TYPE && intersectsCircle( light.position, normal, u, v, rayOrigin, rayDirection, dist ) )
|
|
73
|
+
) {
|
|
74
|
+
|
|
75
|
+
if ( ! didHit || dist < lightSampleRec.dist ) {
|
|
76
|
+
|
|
77
|
+
float cosTheta = dot( rayDirection, normal );
|
|
78
|
+
didHit = true;
|
|
79
|
+
lightSampleRec.dist = dist;
|
|
80
|
+
lightSampleRec.pdf = ( dist * dist ) / ( light.area * cosTheta );
|
|
81
|
+
lightSampleRec.emission = light.color * light.intensity;
|
|
82
|
+
lightSampleRec.direction = rayDirection;
|
|
83
|
+
lightSampleRec.type = light.type;
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return didHit;
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
LightSampleRecord randomAreaLightSample( Light light, vec3 rayOrigin, vec2 ruv ) {
|
|
96
|
+
|
|
97
|
+
LightSampleRecord lightSampleRec;
|
|
98
|
+
lightSampleRec.type = light.type;
|
|
99
|
+
|
|
100
|
+
lightSampleRec.emission = light.color * light.intensity;
|
|
101
|
+
|
|
102
|
+
vec3 randomPos;
|
|
103
|
+
if( light.type == RECT_AREA_LIGHT_TYPE ) {
|
|
104
|
+
|
|
105
|
+
// rectangular area light
|
|
106
|
+
randomPos = light.position + light.u * ( ruv.x - 0.5 ) + light.v * ( ruv.y - 0.5 );
|
|
107
|
+
|
|
108
|
+
} else if( light.type == CIRC_AREA_LIGHT_TYPE ) {
|
|
109
|
+
|
|
110
|
+
// circular area light
|
|
111
|
+
float r = 0.5 * sqrt( ruv.x );
|
|
112
|
+
float theta = ruv.y * 2.0 * PI;
|
|
113
|
+
float x = r * cos( theta );
|
|
114
|
+
float y = r * sin( theta );
|
|
115
|
+
|
|
116
|
+
randomPos = light.position + light.u * x + light.v * y;
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
vec3 toLight = randomPos - rayOrigin;
|
|
121
|
+
float lightDistSq = dot( toLight, toLight );
|
|
122
|
+
lightSampleRec.dist = sqrt( lightDistSq );
|
|
123
|
+
|
|
124
|
+
vec3 direction = toLight / lightSampleRec.dist;
|
|
125
|
+
lightSampleRec.direction = direction;
|
|
126
|
+
|
|
127
|
+
vec3 lightNormal = normalize( cross( light.u, light.v ) );
|
|
128
|
+
lightSampleRec.pdf = lightDistSq / ( light.area * dot( direction, lightNormal ) );
|
|
129
|
+
|
|
130
|
+
return lightSampleRec;
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
LightSampleRecord randomSpotLightSample( Light light, sampler2DArray iesProfiles, vec3 rayOrigin, vec2 ruv ) {
|
|
135
|
+
|
|
136
|
+
float radius = light.radius * sqrt( ruv.x );
|
|
137
|
+
float theta = ruv.y * 2.0 * PI;
|
|
138
|
+
float x = radius * cos( theta );
|
|
139
|
+
float y = radius * sin( theta );
|
|
140
|
+
|
|
141
|
+
vec3 u = light.u;
|
|
142
|
+
vec3 v = light.v;
|
|
143
|
+
vec3 normal = normalize( cross( u, v ) );
|
|
144
|
+
|
|
145
|
+
float angle = acos( light.coneCos );
|
|
146
|
+
float angleTan = tan( angle );
|
|
147
|
+
float startDistance = light.radius / max( angleTan, EPSILON );
|
|
148
|
+
|
|
149
|
+
vec3 randomPos = light.position - normal * startDistance + u * x + v * y;
|
|
150
|
+
vec3 toLight = randomPos - rayOrigin;
|
|
151
|
+
float lightDistSq = dot( toLight, toLight );
|
|
152
|
+
float dist = sqrt( lightDistSq );
|
|
153
|
+
|
|
154
|
+
vec3 direction = toLight / max( dist, EPSILON );
|
|
155
|
+
float cosTheta = dot( direction, normal );
|
|
156
|
+
|
|
157
|
+
float spotAttenuation = light.iesProfile != - 1 ?
|
|
158
|
+
getPhotometricAttenuation( iesProfiles, light.iesProfile, direction, normal, u, v ) :
|
|
159
|
+
getSpotAttenuation( light.coneCos, light.penumbraCos, cosTheta );
|
|
160
|
+
|
|
161
|
+
float distanceAttenuation = getDistanceAttenuation( dist, light.distance, light.decay );
|
|
162
|
+
LightSampleRecord lightSampleRec;
|
|
163
|
+
lightSampleRec.type = light.type;
|
|
164
|
+
lightSampleRec.dist = dist;
|
|
165
|
+
lightSampleRec.direction = direction;
|
|
166
|
+
lightSampleRec.emission = light.color * light.intensity * distanceAttenuation * spotAttenuation;
|
|
167
|
+
lightSampleRec.pdf = 1.0;
|
|
168
|
+
|
|
169
|
+
return lightSampleRec;
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
LightSampleRecord randomLightSample( sampler2D lights, sampler2DArray iesProfiles, uint lightCount, vec3 rayOrigin, vec3 ruv ) {
|
|
174
|
+
|
|
175
|
+
// pick a random light
|
|
176
|
+
uint l = uint( ruv.x * float( lightCount ) );
|
|
177
|
+
Light light = readLightInfo( lights, l );
|
|
178
|
+
|
|
179
|
+
if ( light.type == SPOT_LIGHT_TYPE ) {
|
|
180
|
+
|
|
181
|
+
return randomSpotLightSample( light, iesProfiles, rayOrigin, ruv.yz );
|
|
182
|
+
|
|
183
|
+
} else if ( light.type == POINT_LIGHT_TYPE ) {
|
|
184
|
+
|
|
185
|
+
vec3 lightRay = light.u - rayOrigin;
|
|
186
|
+
float lightDist = length( lightRay );
|
|
187
|
+
float cutoffDistance = light.distance;
|
|
188
|
+
float distanceFalloff = 1.0 / max( pow( lightDist, light.decay ), 0.01 );
|
|
189
|
+
if ( cutoffDistance > 0.0 ) {
|
|
190
|
+
|
|
191
|
+
distanceFalloff *= pow2( saturate( 1.0 - pow4( lightDist / cutoffDistance ) ) );
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
LightSampleRecord rec;
|
|
196
|
+
rec.direction = normalize( lightRay );
|
|
197
|
+
rec.dist = length( lightRay );
|
|
198
|
+
rec.pdf = 1.0;
|
|
199
|
+
rec.emission = light.color * light.intensity * distanceFalloff;
|
|
200
|
+
rec.type = light.type;
|
|
201
|
+
return rec;
|
|
202
|
+
|
|
203
|
+
} else if ( light.type == DIR_LIGHT_TYPE ) {
|
|
204
|
+
|
|
205
|
+
LightSampleRecord rec;
|
|
206
|
+
rec.dist = 1e10;
|
|
207
|
+
rec.direction = light.u;
|
|
208
|
+
rec.pdf = 1.0;
|
|
209
|
+
rec.emission = light.color * light.intensity;
|
|
210
|
+
rec.type = light.type;
|
|
211
|
+
|
|
212
|
+
return rec;
|
|
213
|
+
|
|
214
|
+
} else {
|
|
215
|
+
|
|
216
|
+
// sample the light
|
|
217
|
+
return randomAreaLightSample( light, rayOrigin, ruv.yz );
|
|
218
|
+
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
`;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const shapeSamplingGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
vec3 sampleHemisphere( vec3 n, vec2 uv ) {
|
|
4
|
+
|
|
5
|
+
// https://www.rorydriscoll.com/2009/01/07/better-sampling/
|
|
6
|
+
// https://graphics.pixar.com/library/OrthonormalB/paper.pdf
|
|
7
|
+
float sign = n.z == 0.0 ? 1.0 : sign( n.z );
|
|
8
|
+
float a = - 1.0 / ( sign + n.z );
|
|
9
|
+
float b = n.x * n.y * a;
|
|
10
|
+
vec3 b1 = vec3( 1.0 + sign * n.x * n.x * a, sign * b, - sign * n.x );
|
|
11
|
+
vec3 b2 = vec3( b, sign + n.y * n.y * a, - n.y );
|
|
12
|
+
|
|
13
|
+
float r = sqrt( uv.x );
|
|
14
|
+
float theta = 2.0 * PI * uv.y;
|
|
15
|
+
float x = r * cos( theta );
|
|
16
|
+
float y = r * sin( theta );
|
|
17
|
+
return x * b1 + y * b2 + sqrt( 1.0 - uv.x ) * n;
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
vec2 sampleTriangle( vec2 a, vec2 b, vec2 c, vec2 r ) {
|
|
22
|
+
|
|
23
|
+
// get the edges of the triangle and the diagonal across the
|
|
24
|
+
// center of the parallelogram
|
|
25
|
+
vec2 e1 = a - b;
|
|
26
|
+
vec2 e2 = c - b;
|
|
27
|
+
vec2 diag = normalize( e1 + e2 );
|
|
28
|
+
|
|
29
|
+
// pick the point in the parallelogram
|
|
30
|
+
if ( r.x + r.y > 1.0 ) {
|
|
31
|
+
|
|
32
|
+
r = vec2( 1.0 ) - r;
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return e1 * r.x + e2 * r.y;
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
vec2 sampleCircle( vec2 uv ) {
|
|
41
|
+
|
|
42
|
+
float angle = 2.0 * PI * uv.x;
|
|
43
|
+
float radius = sqrt( uv.y );
|
|
44
|
+
return vec2( cos( angle ), sin( angle ) ) * radius;
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
vec3 sampleSphere( vec2 uv ) {
|
|
49
|
+
|
|
50
|
+
float u = ( uv.x - 0.5 ) * 2.0;
|
|
51
|
+
float t = uv.y * PI * 2.0;
|
|
52
|
+
float f = sqrt( 1.0 - u * u );
|
|
53
|
+
|
|
54
|
+
return vec3( f * cos( t ), f * sin( t ), u );
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
vec2 sampleRegularPolygon( int sides, vec3 uvw ) {
|
|
59
|
+
|
|
60
|
+
sides = max( sides, 3 );
|
|
61
|
+
|
|
62
|
+
vec3 r = uvw;
|
|
63
|
+
float anglePerSegment = 2.0 * PI / float( sides );
|
|
64
|
+
float segment = floor( float( sides ) * r.x );
|
|
65
|
+
|
|
66
|
+
float angle1 = anglePerSegment * segment;
|
|
67
|
+
float angle2 = angle1 + anglePerSegment;
|
|
68
|
+
vec2 a = vec2( sin( angle1 ), cos( angle1 ) );
|
|
69
|
+
vec2 b = vec2( 0.0, 0.0 );
|
|
70
|
+
vec2 c = vec2( sin( angle2 ), cos( angle2 ) );
|
|
71
|
+
|
|
72
|
+
return sampleTriangle( a, b, c, r.yz );
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// samples an aperture shape with the given number of sides. 0 means circle
|
|
77
|
+
vec2 sampleAperture( int blades, vec3 uvw ) {
|
|
78
|
+
|
|
79
|
+
return blades == 0 ?
|
|
80
|
+
sampleCircle( uvw.xy ) :
|
|
81
|
+
sampleRegularPolygon( blades, uvw );
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const fogMaterialBvhGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
#ifndef FOG_CHECK_ITERATIONS
|
|
4
|
+
#define FOG_CHECK_ITERATIONS 30
|
|
5
|
+
#endif
|
|
6
|
+
|
|
7
|
+
// returns whether the given material is a fog material or not
|
|
8
|
+
bool isMaterialFogVolume( sampler2D materials, uint materialIndex ) {
|
|
9
|
+
|
|
10
|
+
uint i = materialIndex * 45u;
|
|
11
|
+
vec4 s14 = texelFetch1D( materials, i + 14u );
|
|
12
|
+
return bool( int( s14.b ) & 4 );
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// returns true if we're within the first fog volume we hit
|
|
17
|
+
bool bvhIntersectFogVolumeHit(
|
|
18
|
+
BVH bvh, vec3 rayOrigin, vec3 rayDirection,
|
|
19
|
+
usampler2D materialIndexAttribute, sampler2D materials,
|
|
20
|
+
out Material material
|
|
21
|
+
) {
|
|
22
|
+
|
|
23
|
+
material.fogVolume = false;
|
|
24
|
+
|
|
25
|
+
for ( int i = 0; i < FOG_CHECK_ITERATIONS; i ++ ) {
|
|
26
|
+
|
|
27
|
+
// find nearest hit
|
|
28
|
+
uvec4 faceIndices = uvec4( 0u );
|
|
29
|
+
vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
|
|
30
|
+
vec3 barycoord = vec3( 0.0 );
|
|
31
|
+
float side = 1.0;
|
|
32
|
+
float dist = 0.0;
|
|
33
|
+
bool hit = bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
|
|
34
|
+
if ( hit ) {
|
|
35
|
+
|
|
36
|
+
// if it's a fog volume return whether we hit the front or back face
|
|
37
|
+
uint materialIndex = uTexelFetch1D( materialIndexAttribute, faceIndices.x ).r;
|
|
38
|
+
if ( isMaterialFogVolume( materials, materialIndex ) ) {
|
|
39
|
+
|
|
40
|
+
material = readMaterialInfo( materials, materialIndex );
|
|
41
|
+
return side == - 1.0;
|
|
42
|
+
|
|
43
|
+
} else {
|
|
44
|
+
|
|
45
|
+
// move the ray forward
|
|
46
|
+
rayOrigin = stepRayOrigin( rayOrigin, rayDirection, - faceNormal, dist );
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
} else {
|
|
51
|
+
|
|
52
|
+
return false;
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return false;
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
`;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export const lightsStructGLSL = /* glsl */`
|
|
2
|
+
|
|
3
|
+
#define RECT_AREA_LIGHT_TYPE 0
|
|
4
|
+
#define CIRC_AREA_LIGHT_TYPE 1
|
|
5
|
+
#define SPOT_LIGHT_TYPE 2
|
|
6
|
+
#define DIR_LIGHT_TYPE 3
|
|
7
|
+
#define POINT_LIGHT_TYPE 4
|
|
8
|
+
|
|
9
|
+
struct LightsInfo {
|
|
10
|
+
|
|
11
|
+
sampler2D tex;
|
|
12
|
+
uint count;
|
|
13
|
+
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
struct Light {
|
|
17
|
+
|
|
18
|
+
vec3 position;
|
|
19
|
+
int type;
|
|
20
|
+
|
|
21
|
+
vec3 color;
|
|
22
|
+
float intensity;
|
|
23
|
+
|
|
24
|
+
vec3 u;
|
|
25
|
+
vec3 v;
|
|
26
|
+
float area;
|
|
27
|
+
|
|
28
|
+
// spot light fields
|
|
29
|
+
float radius;
|
|
30
|
+
float near;
|
|
31
|
+
float decay;
|
|
32
|
+
float distance;
|
|
33
|
+
float coneCos;
|
|
34
|
+
float penumbraCos;
|
|
35
|
+
int iesProfile;
|
|
36
|
+
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
Light readLightInfo( sampler2D tex, uint index ) {
|
|
40
|
+
|
|
41
|
+
uint i = index * 6u;
|
|
42
|
+
|
|
43
|
+
vec4 s0 = texelFetch1D( tex, i + 0u );
|
|
44
|
+
vec4 s1 = texelFetch1D( tex, i + 1u );
|
|
45
|
+
vec4 s2 = texelFetch1D( tex, i + 2u );
|
|
46
|
+
vec4 s3 = texelFetch1D( tex, i + 3u );
|
|
47
|
+
|
|
48
|
+
Light l;
|
|
49
|
+
l.position = s0.rgb;
|
|
50
|
+
l.type = int( round( s0.a ) );
|
|
51
|
+
|
|
52
|
+
l.color = s1.rgb;
|
|
53
|
+
l.intensity = s1.a;
|
|
54
|
+
|
|
55
|
+
l.u = s2.rgb;
|
|
56
|
+
l.v = s3.rgb;
|
|
57
|
+
l.area = s3.a;
|
|
58
|
+
|
|
59
|
+
if ( l.type == SPOT_LIGHT_TYPE || l.type == POINT_LIGHT_TYPE ) {
|
|
60
|
+
|
|
61
|
+
vec4 s4 = texelFetch1D( tex, i + 4u );
|
|
62
|
+
vec4 s5 = texelFetch1D( tex, i + 5u );
|
|
63
|
+
l.radius = s4.r;
|
|
64
|
+
l.near = s4.g;
|
|
65
|
+
l.decay = s4.b;
|
|
66
|
+
l.distance = s4.a;
|
|
67
|
+
|
|
68
|
+
l.coneCos = s5.r;
|
|
69
|
+
l.penumbraCos = s5.g;
|
|
70
|
+
l.iesProfile = int( round ( s5.b ) );
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return l;
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
`;
|
|
@@ -1,25 +1,4 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
struct PhysicalCamera {
|
|
4
|
-
|
|
5
|
-
float focusDistance;
|
|
6
|
-
float anamorphicRatio;
|
|
7
|
-
float bokehSize;
|
|
8
|
-
int apertureBlades;
|
|
9
|
-
float apertureRotation;
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
struct EquirectHdrInfo {
|
|
14
|
-
|
|
15
|
-
sampler2D marginalWeights;
|
|
16
|
-
sampler2D conditionalWeights;
|
|
17
|
-
sampler2D map;
|
|
18
|
-
|
|
19
|
-
float totalSumWhole;
|
|
20
|
-
float totalSumDecimal;
|
|
21
|
-
|
|
22
|
-
};
|
|
1
|
+
export const materialStructGLSL = /* glsl */ `
|
|
23
2
|
|
|
24
3
|
struct Material {
|
|
25
4
|
|
|
@@ -76,6 +55,7 @@ export const shaderMaterialStructs = /* glsl */ `
|
|
|
76
55
|
float side;
|
|
77
56
|
bool matte;
|
|
78
57
|
|
|
58
|
+
float sheen;
|
|
79
59
|
vec3 sheenColor;
|
|
80
60
|
int sheenColorMap;
|
|
81
61
|
float sheenRoughness;
|
|
@@ -84,6 +64,7 @@ export const shaderMaterialStructs = /* glsl */ `
|
|
|
84
64
|
bool vertexColors;
|
|
85
65
|
bool flatShading;
|
|
86
66
|
bool transparent;
|
|
67
|
+
bool fogVolume;
|
|
87
68
|
|
|
88
69
|
mat3 mapTransform;
|
|
89
70
|
mat3 metalnessMapTransform;
|
|
@@ -165,6 +146,7 @@ export const shaderMaterialStructs = /* glsl */ `
|
|
|
165
146
|
m.clearcoatNormalMap = int( round( s5.a ) );
|
|
166
147
|
m.clearcoatNormalScale = s6.rg;
|
|
167
148
|
|
|
149
|
+
m.sheen = s6.a;
|
|
168
150
|
m.sheenColor = s7.rgb;
|
|
169
151
|
m.sheenColorMap = int( round( s7.a ) );
|
|
170
152
|
m.sheenRoughness = s8.r;
|
|
@@ -197,6 +179,7 @@ export const shaderMaterialStructs = /* glsl */ `
|
|
|
197
179
|
m.castShadow = ! bool( s14.g );
|
|
198
180
|
m.vertexColors = bool( int( s14.b ) & 1 );
|
|
199
181
|
m.flatShading = bool( int( s14.b ) & 2 );
|
|
182
|
+
m.fogVolume = bool( int( s14.b ) & 4 );
|
|
200
183
|
m.transparent = bool( s14.a );
|
|
201
184
|
|
|
202
185
|
uint firstTextureTransformIdx = i + 15u;
|
|
@@ -222,104 +205,3 @@ export const shaderMaterialStructs = /* glsl */ `
|
|
|
222
205
|
}
|
|
223
206
|
|
|
224
207
|
`;
|
|
225
|
-
|
|
226
|
-
export const shaderLightStruct = /* glsl */ `
|
|
227
|
-
|
|
228
|
-
#define RECT_AREA_LIGHT_TYPE 0
|
|
229
|
-
#define CIRC_AREA_LIGHT_TYPE 1
|
|
230
|
-
#define SPOT_LIGHT_TYPE 2
|
|
231
|
-
#define DIR_LIGHT_TYPE 3
|
|
232
|
-
#define POINT_LIGHT_TYPE 4
|
|
233
|
-
|
|
234
|
-
struct LightsInfo {
|
|
235
|
-
|
|
236
|
-
sampler2D tex;
|
|
237
|
-
uint count;
|
|
238
|
-
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
struct Light {
|
|
242
|
-
|
|
243
|
-
vec3 position;
|
|
244
|
-
int type;
|
|
245
|
-
|
|
246
|
-
vec3 color;
|
|
247
|
-
float intensity;
|
|
248
|
-
|
|
249
|
-
vec3 u;
|
|
250
|
-
vec3 v;
|
|
251
|
-
float area;
|
|
252
|
-
|
|
253
|
-
// spot light fields
|
|
254
|
-
float radius;
|
|
255
|
-
float near;
|
|
256
|
-
float decay;
|
|
257
|
-
float distance;
|
|
258
|
-
float coneCos;
|
|
259
|
-
float penumbraCos;
|
|
260
|
-
int iesProfile;
|
|
261
|
-
|
|
262
|
-
};
|
|
263
|
-
|
|
264
|
-
Light readLightInfo( sampler2D tex, uint index ) {
|
|
265
|
-
|
|
266
|
-
uint i = index * 6u;
|
|
267
|
-
|
|
268
|
-
vec4 s0 = texelFetch1D( tex, i + 0u );
|
|
269
|
-
vec4 s1 = texelFetch1D( tex, i + 1u );
|
|
270
|
-
vec4 s2 = texelFetch1D( tex, i + 2u );
|
|
271
|
-
vec4 s3 = texelFetch1D( tex, i + 3u );
|
|
272
|
-
|
|
273
|
-
Light l;
|
|
274
|
-
l.position = s0.rgb;
|
|
275
|
-
l.type = int( round( s0.a ) );
|
|
276
|
-
|
|
277
|
-
l.color = s1.rgb;
|
|
278
|
-
l.intensity = s1.a;
|
|
279
|
-
|
|
280
|
-
l.u = s2.rgb;
|
|
281
|
-
l.v = s3.rgb;
|
|
282
|
-
l.area = s3.a;
|
|
283
|
-
|
|
284
|
-
if ( l.type == SPOT_LIGHT_TYPE || l.type == POINT_LIGHT_TYPE ) {
|
|
285
|
-
|
|
286
|
-
vec4 s4 = texelFetch1D( tex, i + 4u );
|
|
287
|
-
vec4 s5 = texelFetch1D( tex, i + 5u );
|
|
288
|
-
l.radius = s4.r;
|
|
289
|
-
l.near = s4.g;
|
|
290
|
-
l.decay = s4.b;
|
|
291
|
-
l.distance = s4.a;
|
|
292
|
-
|
|
293
|
-
l.coneCos = s5.r;
|
|
294
|
-
l.penumbraCos = s5.g;
|
|
295
|
-
l.iesProfile = int( round ( s5.b ) );
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return l;
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
struct SpotLight {
|
|
304
|
-
|
|
305
|
-
vec3 position;
|
|
306
|
-
int type;
|
|
307
|
-
|
|
308
|
-
vec3 color;
|
|
309
|
-
float intensity;
|
|
310
|
-
|
|
311
|
-
vec3 u;
|
|
312
|
-
vec3 v;
|
|
313
|
-
float area;
|
|
314
|
-
|
|
315
|
-
float radius;
|
|
316
|
-
float near;
|
|
317
|
-
float decay;
|
|
318
|
-
float distance;
|
|
319
|
-
float coneCos;
|
|
320
|
-
float penumbraCos;
|
|
321
|
-
int iesProfile;
|
|
322
|
-
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
`;
|