@woosh/meep-engine 2.140.0 → 2.142.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/package.json +1 -1
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts +21 -0
- package/src/core/geom/3d/quaternion/quat3_multiply.d.ts.map +1 -0
- package/src/core/geom/3d/quaternion/quat3_multiply.js +25 -0
- package/src/engine/control/first-person/prototype_first_person_controller.js +5 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +67 -42
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.d.ts +12 -22
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.d.ts.map +1 -1
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOShader.js +340 -186
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.d.ts +44 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.d.ts.map +1 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.js +151 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.d.ts +14 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.d.ts.map +1 -0
- package/src/engine/graphics/render/buffer/simple-fx/ao/generateHilbertNoiseTexture.js +78 -0
- package/src/engine/physics/PLAN.md +705 -461
- package/src/engine/physics/REVIEW_002.md +151 -0
- package/src/engine/physics/REVIEW_003.md +166 -0
- package/src/engine/physics/constraint/DofMode.d.ts +28 -0
- package/src/engine/physics/constraint/DofMode.d.ts.map +1 -0
- package/src/engine/physics/constraint/DofMode.js +35 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts +38 -0
- package/src/engine/physics/constraint/solve_constraints.d.ts.map +1 -0
- package/src/engine/physics/constraint/solve_constraints.js +673 -0
- package/src/engine/physics/ecs/Joint.d.ts +294 -0
- package/src/engine/physics/ecs/Joint.d.ts.map +1 -0
- package/src/engine/physics/ecs/Joint.js +402 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts +52 -0
- package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
- package/src/engine/physics/ecs/PhysicsSystem.js +126 -4
- package/src/engine/physics/fluid/FluidField.d.ts +14 -10
- package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidField.js +14 -10
- package/src/engine/physics/fluid/FluidSimulator.d.ts.map +1 -1
- package/src/engine/physics/fluid/FluidSimulator.js +0 -1
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts +17 -10
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_compute_solid_neighbour_mask.js +18 -11
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts +13 -10
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure.js +18 -13
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts +4 -3
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_solve_pressure_pcg.js +15 -11
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts +24 -22
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.d.ts.map +1 -1
- package/src/engine/physics/fluid/solver/v3_grid_subtract_pressure_gradient.js +26 -22
- package/src/engine/physics/island/IslandBuilder.d.ts +4 -1
- package/src/engine/physics/island/IslandBuilder.d.ts.map +1 -1
- package/src/engine/physics/island/IslandBuilder.js +33 -16
- package/src/engine/physics/narrowphase/box_box_manifold.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/box_box_manifold.js +27 -1
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts +33 -0
- package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
- package/src/engine/physics/narrowphase/narrowphase_step.js +75 -0
- package/src/engine/physics/narrowphase/ray_shapes.d.ts +66 -0
- package/src/engine/physics/narrowphase/ray_shapes.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/ray_shapes.js +187 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts +16 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/refine_ray_concave.js +145 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts +39 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.d.ts.map +1 -0
- package/src/engine/physics/narrowphase/refine_ray_hit.js +78 -0
- package/src/engine/physics/queries/raycast.d.ts +11 -9
- package/src/engine/physics/queries/raycast.d.ts.map +1 -1
- package/src/engine/physics/queries/raycast.js +108 -159
- package/src/engine/physics/solver/solve_contacts.d.ts +28 -0
- package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
- package/src/engine/physics/solver/solve_contacts.js +169 -1
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts +114 -0
- package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -0
- package/src/engine/physics/vehicle/RaycastVehicle.js +333 -0
|
@@ -1,186 +1,340 @@
|
|
|
1
|
-
import { Matrix4, Vector2 } from 'three';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'
|
|
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
|
-
varying vec2 vUv;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
uniform
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
uniform
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
float
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
#
|
|
85
|
-
return
|
|
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
|
-
float
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
float
|
|
175
|
-
vec3
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
1
|
+
import { Matrix4, Vector2 } from 'three';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Point-sampled screen-space volumetric obscurance.
|
|
5
|
+
*
|
|
6
|
+
* A hemisphere of radius `kernelRadius` is sampled in the volume above the surface (oriented by the
|
|
7
|
+
* surface normal, lifted slightly off it to avoid self-occlusion). Each sample is counted as
|
|
8
|
+
* occluded when it lies behind the depth buffer *and* the surface it tapped is itself within
|
|
9
|
+
* `kernelRadius` (so distant geometry seen through the depth buffer does not occlude). The
|
|
10
|
+
* occluded fraction is a physically plausible obscurance estimate, so `intensity = 1.0` produces a
|
|
11
|
+
* correct-looking result with no scene-dependent multiplier; higher values are an artistic
|
|
12
|
+
* darkening control.
|
|
13
|
+
*
|
|
14
|
+
* Sample placement uses a fixed R3 low-discrepancy kernel rotated per pixel by an R2 blue-noise
|
|
15
|
+
* dither (interleaved sampling). The blue-noise rotation pushes the sampling error into high
|
|
16
|
+
* frequencies that the edge-aware upscale downstream removes cleanly, leaving little residual.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const SAOShader = {
|
|
20
|
+
defines: {
|
|
21
|
+
'NUM_SAMPLES': 7,
|
|
22
|
+
'NORMAL_TEXTURE': 0,
|
|
23
|
+
'DEPTH_PACKING': 1,
|
|
24
|
+
'PERSPECTIVE_CAMERA': 1
|
|
25
|
+
},
|
|
26
|
+
uniforms: {
|
|
27
|
+
|
|
28
|
+
'tDepth': { value: null },
|
|
29
|
+
'tNormal': { value: null },
|
|
30
|
+
'tHilbert': { value: null },
|
|
31
|
+
'size': { value: new Vector2(512, 512) },
|
|
32
|
+
|
|
33
|
+
'cameraNear': { value: 1 },
|
|
34
|
+
'cameraFar': { value: 100 },
|
|
35
|
+
'cameraProjectionMatrix': { value: new Matrix4() },
|
|
36
|
+
'cameraInverseProjectionMatrix': { value: new Matrix4() },
|
|
37
|
+
|
|
38
|
+
// artistic darkening control; 1.0 == physically plausible
|
|
39
|
+
'intensity': { value: 1.0 },
|
|
40
|
+
|
|
41
|
+
// radius of the sampling hemisphere, in world/view-space units; also the maximum distance at
|
|
42
|
+
// which a tapped surface counts as an occluder
|
|
43
|
+
'kernelRadius': { value: 0.5 }
|
|
44
|
+
},
|
|
45
|
+
vertexShader: /* glsl */`
|
|
46
|
+
|
|
47
|
+
varying vec2 vUv;
|
|
48
|
+
|
|
49
|
+
void main() {
|
|
50
|
+
vUv = uv;
|
|
51
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
52
|
+
}`,
|
|
53
|
+
|
|
54
|
+
fragmentShader: /* glsl */`
|
|
55
|
+
|
|
56
|
+
#include <common>
|
|
57
|
+
|
|
58
|
+
varying vec2 vUv;
|
|
59
|
+
|
|
60
|
+
uniform sampler2D tDepth;
|
|
61
|
+
|
|
62
|
+
#if NORMAL_TEXTURE == 1
|
|
63
|
+
uniform sampler2D tNormal;
|
|
64
|
+
#endif
|
|
65
|
+
|
|
66
|
+
uniform highp usampler2D tHilbert;
|
|
67
|
+
|
|
68
|
+
uniform float cameraNear;
|
|
69
|
+
uniform float cameraFar;
|
|
70
|
+
uniform mat4 cameraProjectionMatrix;
|
|
71
|
+
uniform mat4 cameraInverseProjectionMatrix;
|
|
72
|
+
|
|
73
|
+
uniform float intensity;
|
|
74
|
+
uniform float kernelRadius;
|
|
75
|
+
uniform vec2 size;
|
|
76
|
+
|
|
77
|
+
// RGBA depth
|
|
78
|
+
|
|
79
|
+
#include <packing>
|
|
80
|
+
|
|
81
|
+
out float out_occlusion;
|
|
82
|
+
|
|
83
|
+
float getDepth( const in vec2 screenPosition ) {
|
|
84
|
+
#if DEPTH_PACKING == 1
|
|
85
|
+
return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );
|
|
86
|
+
#else
|
|
87
|
+
return texture2D( tDepth, screenPosition ).x;
|
|
88
|
+
#endif
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
float getViewZ( const in float depth ) {
|
|
92
|
+
#if PERSPECTIVE_CAMERA == 1
|
|
93
|
+
return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );
|
|
94
|
+
#else
|
|
95
|
+
return orthographicDepthToViewZ( depth, cameraNear, cameraFar );
|
|
96
|
+
#endif
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {
|
|
100
|
+
float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];
|
|
101
|
+
vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );
|
|
102
|
+
clipPosition *= clipW; // unprojection.
|
|
103
|
+
|
|
104
|
+
return ( cameraInverseProjectionMatrix * clipPosition ).xyz;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {
|
|
108
|
+
#if NORMAL_TEXTURE == 1
|
|
109
|
+
return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );
|
|
110
|
+
#else
|
|
111
|
+
// Accurate normal reconstruction (Drobot): for each axis pick the nearer-in-depth
|
|
112
|
+
// neighbour, so the tangent basis never straddles a silhouette. dFdx-based normals read
|
|
113
|
+
// garbage across depth discontinuities, which mis-orients the sampling hemisphere and
|
|
114
|
+
// makes flat, camera-facing surfaces self-occlude along their edges.
|
|
115
|
+
vec2 texel = 1.0 / size;
|
|
116
|
+
|
|
117
|
+
float dc = getDepth( screenPosition );
|
|
118
|
+
float dl = getDepth( screenPosition - vec2( texel.x, 0.0 ) );
|
|
119
|
+
float dr = getDepth( screenPosition + vec2( texel.x, 0.0 ) );
|
|
120
|
+
float dd = getDepth( screenPosition - vec2( 0.0, texel.y ) );
|
|
121
|
+
float du = getDepth( screenPosition + vec2( 0.0, texel.y ) );
|
|
122
|
+
|
|
123
|
+
vec3 dpdx;
|
|
124
|
+
if ( abs( dl - dc ) < abs( dr - dc ) ) {
|
|
125
|
+
vec3 left = getViewPosition( screenPosition - vec2( texel.x, 0.0 ), dl, getViewZ( dl ) );
|
|
126
|
+
dpdx = viewPosition - left;
|
|
127
|
+
} else {
|
|
128
|
+
vec3 right = getViewPosition( screenPosition + vec2( texel.x, 0.0 ), dr, getViewZ( dr ) );
|
|
129
|
+
dpdx = right - viewPosition;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
vec3 dpdy;
|
|
133
|
+
if ( abs( dd - dc ) < abs( du - dc ) ) {
|
|
134
|
+
vec3 down = getViewPosition( screenPosition - vec2( 0.0, texel.y ), dd, getViewZ( dd ) );
|
|
135
|
+
dpdy = viewPosition - down;
|
|
136
|
+
} else {
|
|
137
|
+
vec3 up = getViewPosition( screenPosition + vec2( 0.0, texel.y ), du, getViewZ( du ) );
|
|
138
|
+
dpdy = up - viewPosition;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return normalize( cross( dpdx, dpdy ) );
|
|
142
|
+
#endif
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Marty's R2 low-discrepancy sequence: maps a permutation index to a 2D blue-noise-like point.
|
|
146
|
+
// (GLSL ES has no fma; the expanded multiply-add is equivalent here.)
|
|
147
|
+
vec2 r2_marty( uint index ) {
|
|
148
|
+
return fract( vec2( float( index ) ) * vec2( 0.245122333753, 0.430159709002 ) + 0.5 );
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Concentric disk mapping (Shirley & Chiu): low-distortion uniform disk sample from [0,1)^2.
|
|
152
|
+
vec2 sampleUniformDiskConcentric( const in vec2 u ) {
|
|
153
|
+
vec2 offset = 2.0 * u - 1.0;
|
|
154
|
+
|
|
155
|
+
if ( offset.x == 0.0 && offset.y == 0.0 ) return vec2( 0.0 );
|
|
156
|
+
|
|
157
|
+
float r;
|
|
158
|
+
float theta;
|
|
159
|
+
|
|
160
|
+
if ( abs( offset.x ) > abs( offset.y ) ) {
|
|
161
|
+
r = offset.x;
|
|
162
|
+
theta = ( PI * 0.25 ) * ( offset.y / offset.x );
|
|
163
|
+
} else {
|
|
164
|
+
r = offset.y;
|
|
165
|
+
theta = ( PI * 0.5 ) - ( PI * 0.25 ) * ( offset.x / offset.y );
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return r * vec2( cos( theta ), sin( theta ) );
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Cosine-weighted hemisphere direction in tangent space (z is up), via Malley's method.
|
|
172
|
+
vec3 sampleCosineWeightedHemisphere( const in vec2 u ) {
|
|
173
|
+
vec2 d = sampleUniformDiskConcentric( u );
|
|
174
|
+
float z = sqrt( max( 0.0, 1.0 - dot( d, d ) ) );
|
|
175
|
+
return vec3( d.x, d.y, z );
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Branchless orthonormal basis from a unit normal (Duff et al. 2017). Columns are T, B, N, so
|
|
179
|
+
// basis * v maps a tangent-space vector (z up) into the normal's frame.
|
|
180
|
+
mat3 buildOrthonormalBasis( const in vec3 n ) {
|
|
181
|
+
vec3 T;
|
|
182
|
+
vec3 B;
|
|
183
|
+
|
|
184
|
+
if ( n.z < 0.0 ) {
|
|
185
|
+
float a = 1.0 / ( 1.0 - n.z );
|
|
186
|
+
float b = n.x * n.y * a;
|
|
187
|
+
T = vec3( 1.0 - n.x * n.x * a, -b, n.x );
|
|
188
|
+
B = vec3( b, n.y * n.y * a - 1.0, -n.y );
|
|
189
|
+
} else {
|
|
190
|
+
float a = 1.0 / ( 1.0 + n.z );
|
|
191
|
+
float b = -n.x * n.y * a;
|
|
192
|
+
T = vec3( 1.0 - n.x * n.x * a, b, -n.x );
|
|
193
|
+
B = vec3( b, 1.0 - n.y * n.y * a, -n.y );
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return mat3( T, B, n );
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Roberts' R3 low-discrepancy additive recurrence: ( 1/g, 1/g^2, 1/g^3 ), g^4 = g + 1
|
|
200
|
+
const vec3 R3 = vec3( 0.8191725134, 0.6710436067, 0.5497004779 );
|
|
201
|
+
|
|
202
|
+
const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );
|
|
203
|
+
|
|
204
|
+
// normal-bias as a fraction of kernelRadius: lifts the sample origin off the surface to avoid
|
|
205
|
+
// self-occlusion. Larger removes acne but lets near-surface contact occlusion leak.
|
|
206
|
+
const float SURFACE_BIAS = 0.05;
|
|
207
|
+
|
|
208
|
+
// push each sample this many pixels further along its screen-space direction so it never
|
|
209
|
+
// reads the centre pixel (self-occlusion); folded into the offset instead of a hard reject
|
|
210
|
+
const float SELF_OCCLUSION_MARGIN_PIXELS = 2.0;
|
|
211
|
+
|
|
212
|
+
// radial distribution bias: normalized radius -> pow( radius, power ) pulls samples toward
|
|
213
|
+
// the origin, where occlusion contributes most (small crevices over large open surfaces)
|
|
214
|
+
const float sampleDistributionPower = 2.0;
|
|
215
|
+
|
|
216
|
+
// distant samples contribute less (less reliable / more likely to be noise): fraction of the
|
|
217
|
+
// radius over which an occluder's contribution fades to zero at the edge. Must be in [0, 1]. (GTAO)
|
|
218
|
+
const float GTAO_EFFECT_FALLOFF_RANGE = 0.615;
|
|
219
|
+
|
|
220
|
+
float getOccludedFraction( const in vec3 centerViewPosition ) {
|
|
221
|
+
vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );
|
|
222
|
+
|
|
223
|
+
// sample origin lifted slightly off the surface along the normal (see SURFACE_BIAS)
|
|
224
|
+
vec3 sampleOrigin = centerViewPosition + centerViewNormal * ( kernelRadius * SURFACE_BIAS );
|
|
225
|
+
|
|
226
|
+
// tangent->view basis, built once and reused for every sample
|
|
227
|
+
mat3 tbn = buildOrthonormalBasis( centerViewNormal );
|
|
228
|
+
|
|
229
|
+
// per-pixel 2D blue noise: a Hilbert-curve permutation index (spatially well distributed)
|
|
230
|
+
// fed through Marty's R2 sequence. .x rotates the kernel around the normal, .y offsets the
|
|
231
|
+
// sampling radius -- decorrelating neighbours so the edge-aware upscale resolves them.
|
|
232
|
+
uint hilbertIndex = texelFetch( tHilbert, ivec2( gl_FragCoord.xy ) & 63, 0 ).x;
|
|
233
|
+
vec2 noise = r2_marty( hilbertIndex );
|
|
234
|
+
|
|
235
|
+
float ca = cos( noise.x * PI2 );
|
|
236
|
+
float sa = sin( noise.x * PI2 );
|
|
237
|
+
vec3 rT = tbn[0] * ca + tbn[1] * sa;
|
|
238
|
+
vec3 rB = tbn[1] * ca - tbn[0] * sa;
|
|
239
|
+
tbn[0] = rT;
|
|
240
|
+
tbn[1] = rB;
|
|
241
|
+
|
|
242
|
+
// distance falloff (GTAO): full weight until falloffFrom, then linear to zero at the radius
|
|
243
|
+
float falloffRange = GTAO_EFFECT_FALLOFF_RANGE * kernelRadius;
|
|
244
|
+
float falloffFrom = kernelRadius - falloffRange;
|
|
245
|
+
float falloffMul = -1.0 / falloffRange;
|
|
246
|
+
float falloffAdd = falloffFrom / falloffRange + 1.0;
|
|
247
|
+
|
|
248
|
+
float occlusion = 0.0;
|
|
249
|
+
|
|
250
|
+
for ( int i = 0; i < NUM_SAMPLES; i ++ ) {
|
|
251
|
+
// fixed R3 low-discrepancy point; per-pixel variation comes from the rotated frame
|
|
252
|
+
// and the radius offset below
|
|
253
|
+
vec3 q = fract( float( i ) * R3 );
|
|
254
|
+
|
|
255
|
+
// cosine-weighted hemisphere direction, oriented to the (rotated) surface frame:
|
|
256
|
+
// concentrates samples near the normal where occlusion matters most
|
|
257
|
+
vec3 dir = normalize( tbn * sampleCosineWeightedHemisphere( q.xy ) );
|
|
258
|
+
|
|
259
|
+
// normalized radius with a per-pixel offset, biased toward the origin (see
|
|
260
|
+
// sampleDistributionPower) so the near occluders that dominate AO are favoured
|
|
261
|
+
float radius = pow( fract( q.z + noise.y ), sampleDistributionPower );
|
|
262
|
+
|
|
263
|
+
vec3 samplePositionVS = sampleOrigin + dir * ( radius * kernelRadius );
|
|
264
|
+
|
|
265
|
+
// project the sample into screen space
|
|
266
|
+
vec4 clip = cameraProjectionMatrix * vec4( samplePositionVS, 1.0 );
|
|
267
|
+
vec2 sampleUv = ( clip.xy / clip.w ) * 0.5 + 0.5;
|
|
268
|
+
|
|
269
|
+
// screen-space offset from the centre, in pixels
|
|
270
|
+
vec2 offsetPixels = ( sampleUv - vUv ) * size;
|
|
271
|
+
|
|
272
|
+
// push forward along the screen direction by the self-occlusion margin (extends the
|
|
273
|
+
// screen-space radius), then snap to the nearest pixel centre so the depth fetch is
|
|
274
|
+
// exact and neighbouring pixels stay coherent (GTAO)
|
|
275
|
+
float offsetLength = length( offsetPixels );
|
|
276
|
+
offsetPixels += offsetPixels / max( offsetLength, EPSILON ) * SELF_OCCLUSION_MARGIN_PIXELS;
|
|
277
|
+
offsetPixels = round( offsetPixels );
|
|
278
|
+
|
|
279
|
+
sampleUv = vUv + offsetPixels / size;
|
|
280
|
+
|
|
281
|
+
// samples outside the screen have no depth to test against
|
|
282
|
+
if ( sampleUv.x < 0.0 || sampleUv.x > 1.0 || sampleUv.y < 0.0 || sampleUv.y > 1.0 ) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
float sampleDepth = getDepth( sampleUv );
|
|
287
|
+
|
|
288
|
+
// skip the sky / far plane
|
|
289
|
+
if ( sampleDepth >= ( 1.0 - EPSILON ) ) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
float sceneViewZ = getViewZ( sampleDepth );
|
|
294
|
+
|
|
295
|
+
// the tapped surface must lie in front of (closer than) the probe to occlude it; if the
|
|
296
|
+
// probe is in front of the surface it sits in open space and nothing is occluded
|
|
297
|
+
// (view Z grows more negative away from the camera)
|
|
298
|
+
if ( samplePositionVS.z >= sceneViewZ ) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ...and the tapped surface must actually be within the sampling radius, otherwise we
|
|
303
|
+
// have hit distant geometry through the depth buffer that does not occlude this point
|
|
304
|
+
vec3 occluderVS = getViewPosition( sampleUv, sampleDepth, sceneViewZ );
|
|
305
|
+
float sampleDist = distance( centerViewPosition, occluderVS );
|
|
306
|
+
if ( sampleDist > kernelRadius ) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// distant samples contribute less: linear fade from full weight at falloffFrom to zero
|
|
311
|
+
// at the radius (GTAO)
|
|
312
|
+
occlusion += saturate( sampleDist * falloffMul + falloffAdd );
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return occlusion * INV_NUM_SAMPLES;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
void main() {
|
|
319
|
+
float centerDepth = getDepth( vUv );
|
|
320
|
+
if( centerDepth >= ( 1.0 - EPSILON ) ) {
|
|
321
|
+
discard;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
float centerViewZ = getViewZ( centerDepth );
|
|
325
|
+
vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );
|
|
326
|
+
|
|
327
|
+
float occlusion = getOccludedFraction( viewPosition );
|
|
328
|
+
|
|
329
|
+
// intensity is an artistic power: 1.0 leaves the physical estimate untouched, higher
|
|
330
|
+
// darkens occluded areas while leaving fully-lit areas at 1.0
|
|
331
|
+
float visibility = pow( 1.0 - occlusion, intensity );
|
|
332
|
+
|
|
333
|
+
// never fully occlude: if the receiver can see a sample at all it is not truly black, and
|
|
334
|
+
// the R8 target cannot represent anything below 1/255 anyway
|
|
335
|
+
out_occlusion = max( 1.0 / 255.0, visibility );
|
|
336
|
+
}`
|
|
337
|
+
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export { SAOShader };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export namespace SAOUpscaleShader {
|
|
2
|
+
namespace defines {
|
|
3
|
+
let NUM_TAPS: number;
|
|
4
|
+
let DEPTH_PACKING: number;
|
|
5
|
+
let PERSPECTIVE_CAMERA: number;
|
|
6
|
+
}
|
|
7
|
+
namespace uniforms {
|
|
8
|
+
namespace tAO {
|
|
9
|
+
let value: any;
|
|
10
|
+
}
|
|
11
|
+
namespace tDepth {
|
|
12
|
+
let value_1: any;
|
|
13
|
+
export { value_1 as value };
|
|
14
|
+
}
|
|
15
|
+
namespace tHilbert {
|
|
16
|
+
let value_2: any;
|
|
17
|
+
export { value_2 as value };
|
|
18
|
+
}
|
|
19
|
+
namespace size {
|
|
20
|
+
let value_3: Vector2;
|
|
21
|
+
export { value_3 as value };
|
|
22
|
+
}
|
|
23
|
+
namespace cameraNear {
|
|
24
|
+
let value_4: number;
|
|
25
|
+
export { value_4 as value };
|
|
26
|
+
}
|
|
27
|
+
namespace cameraFar {
|
|
28
|
+
let value_5: number;
|
|
29
|
+
export { value_5 as value };
|
|
30
|
+
}
|
|
31
|
+
namespace blurRadius {
|
|
32
|
+
let value_6: number;
|
|
33
|
+
export { value_6 as value };
|
|
34
|
+
}
|
|
35
|
+
namespace depthSigma {
|
|
36
|
+
let value_7: number;
|
|
37
|
+
export { value_7 as value };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let vertexShader: string;
|
|
41
|
+
let fragmentShader: string;
|
|
42
|
+
}
|
|
43
|
+
import { Vector2 } from 'three';
|
|
44
|
+
//# sourceMappingURL=SAOUpscaleShader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SAOUpscaleShader.d.ts","sourceRoot":"","sources":["../../../../../../../../src/engine/graphics/render/buffer/simple-fx/ao/SAOUpscaleShader.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBAAwB,OAAO"}
|