three-base 2.0.134 → 2.0.137
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/FPScontrol.d.ts +10 -3
- package/FPScontrol.js +241 -129
- package/ThreeBase.d.ts +14 -0
- package/ThreeBase.js +53 -10
- package/package.json +3 -2
- package/pass/emissive_ao_pass.d.ts +13 -0
- package/pass/emissive_ao_pass.js +370 -0
- package/pass/ssao_pass.d.ts +2 -0
- package/pass/ssao_pass.js +162 -84
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { LinearFilter, NoBlending, RGBAFormat, RawShaderMaterial, Vector2, WebGLRenderTarget, Matrix4, AdditiveBlending, } from "three";
|
|
2
|
+
import fsQuad from "./fsQuad";
|
|
3
|
+
const emissiveTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
4
|
+
minFilter: LinearFilter,
|
|
5
|
+
magFilter: LinearFilter,
|
|
6
|
+
format: RGBAFormat,
|
|
7
|
+
});
|
|
8
|
+
const blurTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
9
|
+
minFilter: LinearFilter,
|
|
10
|
+
magFilter: LinearFilter,
|
|
11
|
+
format: RGBAFormat,
|
|
12
|
+
});
|
|
13
|
+
const size = new Vector2();
|
|
14
|
+
const projectionMatrix = new Matrix4();
|
|
15
|
+
const inverseProjectionMatrix = new Matrix4();
|
|
16
|
+
const emissiveShader = new RawShaderMaterial({
|
|
17
|
+
uniforms: {
|
|
18
|
+
depthTexture: { value: null },
|
|
19
|
+
emissiveTexture: { value: null },
|
|
20
|
+
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
21
|
+
projectionMatrix: { value: new Matrix4() },
|
|
22
|
+
inverseProjectionMatrix: { value: new Matrix4() },
|
|
23
|
+
radius: { value: 3.0 },
|
|
24
|
+
falloff: { value: 8.0 },
|
|
25
|
+
bias: { value: 0.2 },
|
|
26
|
+
intensity: { value: 1.0 },
|
|
27
|
+
sampleCount: { value: 16 },
|
|
28
|
+
cameraFar: { value: 20000 },
|
|
29
|
+
},
|
|
30
|
+
vertexShader: `
|
|
31
|
+
attribute vec3 position;
|
|
32
|
+
attribute vec2 uv;
|
|
33
|
+
varying vec2 vUv;
|
|
34
|
+
void main() {
|
|
35
|
+
vUv = uv;
|
|
36
|
+
gl_Position = vec4(position, 1.0);
|
|
37
|
+
}`,
|
|
38
|
+
fragmentShader: `
|
|
39
|
+
#ifdef GL_ES
|
|
40
|
+
precision highp float;
|
|
41
|
+
#endif
|
|
42
|
+
|
|
43
|
+
uniform sampler2D depthTexture;
|
|
44
|
+
uniform sampler2D emissiveTexture;
|
|
45
|
+
uniform vec2 resolution;
|
|
46
|
+
uniform mat4 projectionMatrix;
|
|
47
|
+
uniform mat4 inverseProjectionMatrix;
|
|
48
|
+
uniform float radius;
|
|
49
|
+
uniform float falloff;
|
|
50
|
+
uniform float bias;
|
|
51
|
+
uniform float intensity;
|
|
52
|
+
uniform int sampleCount;
|
|
53
|
+
uniform float cameraFar;
|
|
54
|
+
|
|
55
|
+
varying vec2 vUv;
|
|
56
|
+
|
|
57
|
+
float linearizeLogDepth(float logDepth) {
|
|
58
|
+
return pow(cameraFar + 1.0, logDepth) - 1.0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
vec3 reconstructPosition(vec2 uv, float viewZ) {
|
|
62
|
+
vec4 ndc = vec4(uv * 2.0 - 1.0, 0.0, 1.0);
|
|
63
|
+
vec4 viewDir4 = inverseProjectionMatrix * ndc;
|
|
64
|
+
vec3 viewDir = viewDir4.xyz / viewDir4.w;
|
|
65
|
+
return viewDir * (viewZ / (-viewDir.z));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
vec3 reconstructNormal(vec2 uv, vec2 res) {
|
|
69
|
+
vec2 step = res * 2.0;
|
|
70
|
+
|
|
71
|
+
float dC = texture2D(depthTexture, uv).r;
|
|
72
|
+
float dL = texture2D(depthTexture, uv - vec2(step.x, 0.0)).r;
|
|
73
|
+
float dR = texture2D(depthTexture, uv + vec2(step.x, 0.0)).r;
|
|
74
|
+
float dD = texture2D(depthTexture, uv - vec2(0.0, step.y)).r;
|
|
75
|
+
float dU = texture2D(depthTexture, uv + vec2(0.0, step.y)).r;
|
|
76
|
+
|
|
77
|
+
if (dL >= 1.0 || dR >= 1.0 || dD >= 1.0 || dU >= 1.0 || dC >= 1.0) {
|
|
78
|
+
return vec3(0.0, 0.0, 1.0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
float edgeThreshold = 0.003;
|
|
82
|
+
float dL2 = abs(dL - dC) < edgeThreshold ? dL : dC;
|
|
83
|
+
float dR2 = abs(dR - dC) < edgeThreshold ? dR : dC;
|
|
84
|
+
float dD2 = abs(dD - dC) < edgeThreshold ? dD : dC;
|
|
85
|
+
float dU2 = abs(dU - dC) < edgeThreshold ? dU : dC;
|
|
86
|
+
|
|
87
|
+
float vC = linearizeLogDepth(dC);
|
|
88
|
+
float vL = linearizeLogDepth(dL2);
|
|
89
|
+
float vR = linearizeLogDepth(dR2);
|
|
90
|
+
float vD = linearizeLogDepth(dD2);
|
|
91
|
+
float vU = linearizeLogDepth(dU2);
|
|
92
|
+
|
|
93
|
+
vec3 pC = reconstructPosition(uv, vC);
|
|
94
|
+
vec3 pL = reconstructPosition(uv - vec2(step.x, 0.0), vL);
|
|
95
|
+
vec3 pR = reconstructPosition(uv + vec2(step.x, 0.0), vR);
|
|
96
|
+
vec3 pD = reconstructPosition(uv - vec2(0.0, step.y), vD);
|
|
97
|
+
vec3 pU = reconstructPosition(uv + vec2(0.0, step.y), vU);
|
|
98
|
+
|
|
99
|
+
vec3 tangentX = pR - pL;
|
|
100
|
+
vec3 tangentY = pU - pD;
|
|
101
|
+
|
|
102
|
+
if (length(tangentX) < 0.001 || length(tangentY) < 0.001) {
|
|
103
|
+
return vec3(0.0, 0.0, 1.0);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
vec3 normal = cross(normalize(tangentX), normalize(tangentY));
|
|
107
|
+
return normalize(normal);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
float random(vec2 seed) {
|
|
111
|
+
return fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
void main() {
|
|
115
|
+
float logDepth = texture2D(depthTexture, vUv).r;
|
|
116
|
+
|
|
117
|
+
if (logDepth >= 1.0) {
|
|
118
|
+
gl_FragColor = vec4(0.0);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
float viewZ = linearizeLogDepth(logDepth);
|
|
123
|
+
vec3 position = reconstructPosition(vUv, viewZ);
|
|
124
|
+
vec3 normal = reconstructNormal(vUv, resolution);
|
|
125
|
+
|
|
126
|
+
float projScale = 1.0 / (2.0 * abs(viewZ) * resolution.x);
|
|
127
|
+
float pixelRadius = max(radius * projScale, 1.0);
|
|
128
|
+
|
|
129
|
+
vec3 accumulatedColor = vec3(0.0);
|
|
130
|
+
float totalWeight = 0.0;
|
|
131
|
+
|
|
132
|
+
float angle = random(vUv) * 6.2831853;
|
|
133
|
+
float stepAngle = 6.2831853 / float(sampleCount);
|
|
134
|
+
|
|
135
|
+
for (int i = 0; i < 64; i++) {
|
|
136
|
+
if (i >= sampleCount) break;
|
|
137
|
+
|
|
138
|
+
float theta = angle + float(i) * stepAngle;
|
|
139
|
+
float r = sqrt(float(i + 1)) * (pixelRadius / sqrt(float(sampleCount)));
|
|
140
|
+
|
|
141
|
+
vec2 sampleUv = vUv + vec2(cos(theta), sin(theta)) * r * resolution;
|
|
142
|
+
|
|
143
|
+
if (sampleUv.x < 0.0 || sampleUv.x > 1.0 || sampleUv.y < 0.0 || sampleUv.y > 1.0) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
float sampleLogDepth = texture2D(depthTexture, sampleUv).r;
|
|
148
|
+
if (sampleLogDepth >= 1.0) continue;
|
|
149
|
+
|
|
150
|
+
float depthDiff = abs(sampleLogDepth - logDepth);
|
|
151
|
+
if (depthDiff > 0.002) continue;
|
|
152
|
+
|
|
153
|
+
float sampleViewZ = linearizeLogDepth(sampleLogDepth);
|
|
154
|
+
vec3 samplePosition = reconstructPosition(sampleUv, sampleViewZ);
|
|
155
|
+
|
|
156
|
+
vec3 diff = position - samplePosition;
|
|
157
|
+
float dist = length(diff);
|
|
158
|
+
|
|
159
|
+
float tangentDist = dot(diff, normal);
|
|
160
|
+
if (tangentDist < bias) continue;
|
|
161
|
+
|
|
162
|
+
vec3 emissiveColor = texture2D(emissiveTexture, sampleUv).rgb;
|
|
163
|
+
float emissiveIntensity = length(emissiveColor);
|
|
164
|
+
|
|
165
|
+
if (emissiveIntensity > 0.01 && dist < falloff) {
|
|
166
|
+
float rangeCheck = smoothstep(0.0, falloff, dist);
|
|
167
|
+
float weight = (1.0 - rangeCheck) * (1.0 - tangentDist / falloff);
|
|
168
|
+
accumulatedColor += emissiveColor * weight;
|
|
169
|
+
totalWeight += weight;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (totalWeight > 0.0) {
|
|
174
|
+
accumulatedColor /= totalWeight;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
accumulatedColor *= intensity;
|
|
178
|
+
accumulatedColor = clamp(accumulatedColor, 0.0, 1.0);
|
|
179
|
+
|
|
180
|
+
gl_FragColor = vec4(accumulatedColor, 1.0);
|
|
181
|
+
}`,
|
|
182
|
+
blending: NoBlending,
|
|
183
|
+
depthTest: false,
|
|
184
|
+
depthWrite: false,
|
|
185
|
+
transparent: true,
|
|
186
|
+
});
|
|
187
|
+
const blurHShader = new RawShaderMaterial({
|
|
188
|
+
uniforms: {
|
|
189
|
+
tDiffuse: { value: null },
|
|
190
|
+
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
191
|
+
blurRadius: { value: 2.0 },
|
|
192
|
+
depthTexture: { value: null },
|
|
193
|
+
},
|
|
194
|
+
vertexShader: `
|
|
195
|
+
attribute vec3 position;
|
|
196
|
+
attribute vec2 uv;
|
|
197
|
+
varying vec2 vUv;
|
|
198
|
+
void main() {
|
|
199
|
+
vUv = uv;
|
|
200
|
+
gl_Position = vec4(position, 1.0);
|
|
201
|
+
}`,
|
|
202
|
+
fragmentShader: `
|
|
203
|
+
#ifdef GL_ES
|
|
204
|
+
precision highp float;
|
|
205
|
+
#endif
|
|
206
|
+
|
|
207
|
+
uniform sampler2D tDiffuse;
|
|
208
|
+
uniform vec2 resolution;
|
|
209
|
+
uniform float blurRadius;
|
|
210
|
+
uniform sampler2D depthTexture;
|
|
211
|
+
|
|
212
|
+
varying vec2 vUv;
|
|
213
|
+
|
|
214
|
+
void main() {
|
|
215
|
+
float centerDepth = texture2D(depthTexture, vUv).r;
|
|
216
|
+
vec4 color = vec4(0.0);
|
|
217
|
+
float totalWeight = 0.0;
|
|
218
|
+
|
|
219
|
+
for (int i = -4; i <= 4; i++) {
|
|
220
|
+
float weight = exp(-float(i * i) / 8.0);
|
|
221
|
+
vec2 offset = vec2(float(i) * blurRadius * resolution.x, 0.0);
|
|
222
|
+
vec2 sampleUv = vUv + offset;
|
|
223
|
+
float sampleDepth = texture2D(depthTexture, sampleUv).r;
|
|
224
|
+
float depthWeight = abs(sampleDepth - centerDepth) < 0.001 ? 1.0 : 0.1;
|
|
225
|
+
color += texture2D(tDiffuse, sampleUv) * weight * depthWeight;
|
|
226
|
+
totalWeight += weight * depthWeight;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
gl_FragColor = color / totalWeight;
|
|
230
|
+
}`,
|
|
231
|
+
blending: NoBlending,
|
|
232
|
+
depthTest: false,
|
|
233
|
+
depthWrite: false,
|
|
234
|
+
transparent: true,
|
|
235
|
+
});
|
|
236
|
+
const blurVShader = new RawShaderMaterial({
|
|
237
|
+
uniforms: {
|
|
238
|
+
tDiffuse: { value: null },
|
|
239
|
+
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
240
|
+
blurRadius: { value: 2.0 },
|
|
241
|
+
depthTexture: { value: null },
|
|
242
|
+
},
|
|
243
|
+
vertexShader: `
|
|
244
|
+
attribute vec3 position;
|
|
245
|
+
attribute vec2 uv;
|
|
246
|
+
varying vec2 vUv;
|
|
247
|
+
void main() {
|
|
248
|
+
vUv = uv;
|
|
249
|
+
gl_Position = vec4(position, 1.0);
|
|
250
|
+
}`,
|
|
251
|
+
fragmentShader: `
|
|
252
|
+
#ifdef GL_ES
|
|
253
|
+
precision highp float;
|
|
254
|
+
#endif
|
|
255
|
+
|
|
256
|
+
uniform sampler2D tDiffuse;
|
|
257
|
+
uniform vec2 resolution;
|
|
258
|
+
uniform float blurRadius;
|
|
259
|
+
uniform sampler2D depthTexture;
|
|
260
|
+
|
|
261
|
+
varying vec2 vUv;
|
|
262
|
+
|
|
263
|
+
void main() {
|
|
264
|
+
float centerDepth = texture2D(depthTexture, vUv).r;
|
|
265
|
+
vec4 color = vec4(0.0);
|
|
266
|
+
float totalWeight = 0.0;
|
|
267
|
+
|
|
268
|
+
for (int i = -4; i <= 4; i++) {
|
|
269
|
+
float weight = exp(-float(i * i) / 8.0);
|
|
270
|
+
vec2 offset = vec2(0.0, float(i) * blurRadius * resolution.y);
|
|
271
|
+
vec2 sampleUv = vUv + offset;
|
|
272
|
+
float sampleDepth = texture2D(depthTexture, sampleUv).r;
|
|
273
|
+
float depthWeight = abs(sampleDepth - centerDepth) < 0.001 ? 1.0 : 0.1;
|
|
274
|
+
color += texture2D(tDiffuse, sampleUv) * weight * depthWeight;
|
|
275
|
+
totalWeight += weight * depthWeight;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
gl_FragColor = color / totalWeight;
|
|
279
|
+
}`,
|
|
280
|
+
blending: NoBlending,
|
|
281
|
+
depthTest: false,
|
|
282
|
+
depthWrite: false,
|
|
283
|
+
transparent: true,
|
|
284
|
+
});
|
|
285
|
+
const outputShader = new RawShaderMaterial({
|
|
286
|
+
uniforms: {
|
|
287
|
+
emissiveTexture: { value: null },
|
|
288
|
+
strength: { value: 1.0 },
|
|
289
|
+
debug: { value: 0.0 },
|
|
290
|
+
},
|
|
291
|
+
vertexShader: `
|
|
292
|
+
attribute vec3 position;
|
|
293
|
+
attribute vec2 uv;
|
|
294
|
+
varying vec2 vUv;
|
|
295
|
+
void main() {
|
|
296
|
+
vUv = uv;
|
|
297
|
+
gl_Position = vec4(position, 1.0);
|
|
298
|
+
}`,
|
|
299
|
+
fragmentShader: `
|
|
300
|
+
#ifdef GL_ES
|
|
301
|
+
precision highp float;
|
|
302
|
+
#endif
|
|
303
|
+
|
|
304
|
+
uniform sampler2D emissiveTexture;
|
|
305
|
+
uniform float strength;
|
|
306
|
+
uniform float debug;
|
|
307
|
+
|
|
308
|
+
varying vec2 vUv;
|
|
309
|
+
|
|
310
|
+
void main() {
|
|
311
|
+
vec3 emissive = texture2D(emissiveTexture, vUv).rgb;
|
|
312
|
+
vec3 finalEmissive = emissive * strength;
|
|
313
|
+
|
|
314
|
+
if (debug > 0.5) {
|
|
315
|
+
gl_FragColor = vec4(finalEmissive, 1.0);
|
|
316
|
+
} else {
|
|
317
|
+
gl_FragColor = vec4(finalEmissive, length(finalEmissive));
|
|
318
|
+
}
|
|
319
|
+
}`,
|
|
320
|
+
blending: AdditiveBlending,
|
|
321
|
+
depthTest: false,
|
|
322
|
+
depthWrite: false,
|
|
323
|
+
transparent: true,
|
|
324
|
+
});
|
|
325
|
+
export default function emissive_ao_pass(renderer, camera, depthTexture, emissiveTexture, devicePixelRatio, options) {
|
|
326
|
+
if (!options.enable || !options.strength) {
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
renderer.getSize(size);
|
|
330
|
+
size.multiplyScalar(devicePixelRatio);
|
|
331
|
+
emissiveTextureTarget.setSize(size.x, size.y);
|
|
332
|
+
blurTextureTarget.setSize(size.x, size.y);
|
|
333
|
+
projectionMatrix.copy(camera.projectionMatrix);
|
|
334
|
+
inverseProjectionMatrix.copy(projectionMatrix).invert();
|
|
335
|
+
emissiveShader.uniforms.depthTexture.value = depthTexture;
|
|
336
|
+
emissiveShader.uniforms.emissiveTexture.value = emissiveTexture;
|
|
337
|
+
emissiveShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
338
|
+
emissiveShader.uniforms.projectionMatrix.value = projectionMatrix;
|
|
339
|
+
emissiveShader.uniforms.inverseProjectionMatrix.value = inverseProjectionMatrix;
|
|
340
|
+
emissiveShader.uniforms.radius.value = options.radius || 3.0;
|
|
341
|
+
emissiveShader.uniforms.falloff.value = options.falloff || 8.0;
|
|
342
|
+
emissiveShader.uniforms.bias.value = options.bias || 0.2;
|
|
343
|
+
emissiveShader.uniforms.intensity.value = options.intensity || 1.0;
|
|
344
|
+
emissiveShader.uniforms.sampleCount.value = options.sampleCount || 16;
|
|
345
|
+
emissiveShader.uniforms.cameraFar.value = options.cameraFar || camera.far || 20000;
|
|
346
|
+
renderer.setRenderTarget(emissiveTextureTarget);
|
|
347
|
+
renderer.clear();
|
|
348
|
+
fsQuad.render(renderer, emissiveShader);
|
|
349
|
+
const blurRes = new Vector2(1 / size.x, 1 / size.y);
|
|
350
|
+
const blurR = options.blurRadius || 2.0;
|
|
351
|
+
blurHShader.uniforms.tDiffuse.value = emissiveTextureTarget.texture;
|
|
352
|
+
blurHShader.uniforms.resolution.value.copy(blurRes);
|
|
353
|
+
blurHShader.uniforms.blurRadius.value = blurR;
|
|
354
|
+
blurHShader.uniforms.depthTexture.value = depthTexture;
|
|
355
|
+
renderer.setRenderTarget(blurTextureTarget);
|
|
356
|
+
renderer.clear();
|
|
357
|
+
fsQuad.render(renderer, blurHShader);
|
|
358
|
+
blurVShader.uniforms.tDiffuse.value = blurTextureTarget.texture;
|
|
359
|
+
blurVShader.uniforms.resolution.value.copy(blurRes);
|
|
360
|
+
blurVShader.uniforms.blurRadius.value = blurR;
|
|
361
|
+
blurVShader.uniforms.depthTexture.value = depthTexture;
|
|
362
|
+
renderer.setRenderTarget(emissiveTextureTarget);
|
|
363
|
+
renderer.clear();
|
|
364
|
+
fsQuad.render(renderer, blurVShader);
|
|
365
|
+
renderer.setRenderTarget(null);
|
|
366
|
+
outputShader.uniforms.emissiveTexture.value = emissiveTextureTarget.texture;
|
|
367
|
+
outputShader.uniforms.strength.value = options.strength || 1.0;
|
|
368
|
+
outputShader.uniforms.debug.value = options.debug ? 1.0 : 0.0;
|
|
369
|
+
fsQuad.render(renderer, outputShader);
|
|
370
|
+
}
|
package/pass/ssao_pass.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Camera, DepthTexture, WebGLRenderer } from "three";
|
|
2
2
|
export default function ssao_pass(renderer: WebGLRenderer, camera: Camera, depthTexture: DepthTexture, devicePixelRatio: number, options: {
|
|
3
3
|
enable: boolean;
|
|
4
|
+
debug?: boolean;
|
|
4
5
|
radius?: number;
|
|
6
|
+
falloff?: number;
|
|
5
7
|
bias?: number;
|
|
6
8
|
intensity?: number;
|
|
7
9
|
sampleCount?: number;
|