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
package/pass/ssao_pass.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LinearFilter, NoBlending, RGBAFormat, RawShaderMaterial, Vector2, WebGLRenderTarget, Matrix4, MultiplyBlending, } from "three";
|
|
2
2
|
import fsQuad from "./fsQuad";
|
|
3
3
|
const ssaoTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
4
4
|
minFilter: LinearFilter,
|
|
@@ -13,17 +13,18 @@ const blurTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
|
13
13
|
const size = new Vector2();
|
|
14
14
|
const projectionMatrix = new Matrix4();
|
|
15
15
|
const inverseProjectionMatrix = new Matrix4();
|
|
16
|
+
// SSAO 着色器 — 随机采样 + 法线半球判断 + 深度连续性 + 视距自适应半径
|
|
16
17
|
const ssaoShader = new RawShaderMaterial({
|
|
17
18
|
uniforms: {
|
|
18
19
|
depthTexture: { value: null },
|
|
19
20
|
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
20
21
|
projectionMatrix: { value: new Matrix4() },
|
|
21
22
|
inverseProjectionMatrix: { value: new Matrix4() },
|
|
22
|
-
ssaoRadius: { value: 0
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
ssaoRadius: { value: 2.0 },
|
|
24
|
+
ssaoFalloff: { value: 5.0 },
|
|
25
|
+
ssaoBias: { value: 0.3 },
|
|
26
|
+
ssaoIntensity: { value: 1.0 },
|
|
25
27
|
sampleCount: { value: 16 },
|
|
26
|
-
// 对数深度缓冲区的 far 参数,用于反算线性视距
|
|
27
28
|
cameraFar: { value: 20000 },
|
|
28
29
|
},
|
|
29
30
|
vertexShader: `
|
|
@@ -38,88 +39,144 @@ const ssaoShader = new RawShaderMaterial({
|
|
|
38
39
|
#ifdef GL_ES
|
|
39
40
|
precision highp float;
|
|
40
41
|
#endif
|
|
41
|
-
|
|
42
|
+
|
|
42
43
|
uniform sampler2D depthTexture;
|
|
43
44
|
uniform vec2 resolution;
|
|
44
45
|
uniform mat4 projectionMatrix;
|
|
45
46
|
uniform mat4 inverseProjectionMatrix;
|
|
46
47
|
uniform float ssaoRadius;
|
|
48
|
+
uniform float ssaoFalloff;
|
|
47
49
|
uniform float ssaoBias;
|
|
48
50
|
uniform float ssaoIntensity;
|
|
49
51
|
uniform int sampleCount;
|
|
50
52
|
uniform float cameraFar;
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
varying vec2 vUv;
|
|
53
|
-
|
|
54
|
-
// 将对数深度值反算回线性视距(正数,单位与世界坐标一致)
|
|
55
|
-
// Three.js 对数深度编码: logDepth = log2(viewZ + 1.0) / log2(cameraFar + 1.0)
|
|
55
|
+
|
|
56
56
|
float linearizeLogDepth(float logDepth) {
|
|
57
57
|
return pow(cameraFar + 1.0, logDepth) - 1.0;
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// viewDistance: 相机到该像素的视距(正数)
|
|
62
|
-
vec3 reconstructPosition(vec2 uv, float viewDistance) {
|
|
63
|
-
// 用 inverseProjectionMatrix 求出该像素的视空间射线方向
|
|
59
|
+
|
|
60
|
+
vec3 reconstructPosition(vec2 uv, float viewZ) {
|
|
64
61
|
vec4 ndc = vec4(uv * 2.0 - 1.0, 0.0, 1.0);
|
|
65
62
|
vec4 viewDir4 = inverseProjectionMatrix * ndc;
|
|
66
63
|
vec3 viewDir = viewDir4.xyz / viewDir4.w;
|
|
67
|
-
|
|
68
|
-
return viewDir * (viewDistance / (-viewDir.z));
|
|
64
|
+
return viewDir * (viewZ / (-viewDir.z));
|
|
69
65
|
}
|
|
70
|
-
|
|
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
|
+
// 深度不连续时回退为中心深度
|
|
82
|
+
float edgeThreshold = 0.003;
|
|
83
|
+
float dL2 = abs(dL - dC) < edgeThreshold ? dL : dC;
|
|
84
|
+
float dR2 = abs(dR - dC) < edgeThreshold ? dR : dC;
|
|
85
|
+
float dD2 = abs(dD - dC) < edgeThreshold ? dD : dC;
|
|
86
|
+
float dU2 = abs(dU - dC) < edgeThreshold ? dU : dC;
|
|
87
|
+
|
|
88
|
+
float vC = linearizeLogDepth(dC);
|
|
89
|
+
float vL = linearizeLogDepth(dL2);
|
|
90
|
+
float vR = linearizeLogDepth(dR2);
|
|
91
|
+
float vD = linearizeLogDepth(dD2);
|
|
92
|
+
float vU = linearizeLogDepth(dU2);
|
|
93
|
+
|
|
94
|
+
vec3 pC = reconstructPosition(uv, vC);
|
|
95
|
+
vec3 pL = reconstructPosition(uv - vec2(step.x, 0.0), vL);
|
|
96
|
+
vec3 pR = reconstructPosition(uv + vec2(step.x, 0.0), vR);
|
|
97
|
+
vec3 pD = reconstructPosition(uv - vec2(0.0, step.y), vD);
|
|
98
|
+
vec3 pU = reconstructPosition(uv + vec2(0.0, step.y), vU);
|
|
99
|
+
|
|
100
|
+
vec3 tangentX = pR - pL;
|
|
101
|
+
vec3 tangentY = pU - pD;
|
|
102
|
+
|
|
103
|
+
if (length(tangentX) < 0.001 || length(tangentY) < 0.001) {
|
|
104
|
+
return vec3(0.0, 0.0, 1.0);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
vec3 normal = cross(normalize(tangentX), normalize(tangentY));
|
|
108
|
+
return normalize(normal);
|
|
109
|
+
}
|
|
110
|
+
|
|
71
111
|
float random(vec2 seed) {
|
|
72
112
|
return fract(sin(dot(seed, vec2(12.9898, 78.233))) * 43758.5453);
|
|
73
113
|
}
|
|
74
|
-
|
|
114
|
+
|
|
75
115
|
void main() {
|
|
76
116
|
float logDepth = texture2D(depthTexture, vUv).r;
|
|
77
|
-
|
|
117
|
+
|
|
78
118
|
// 背景 / 无穷远 → 无遮挡
|
|
79
119
|
if (logDepth >= 1.0) {
|
|
80
120
|
gl_FragColor = vec4(1.0);
|
|
81
121
|
return;
|
|
82
122
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
vec3
|
|
87
|
-
|
|
123
|
+
|
|
124
|
+
float viewZ = linearizeLogDepth(logDepth);
|
|
125
|
+
vec3 position = reconstructPosition(vUv, viewZ);
|
|
126
|
+
vec3 normal = reconstructNormal(vUv, resolution);
|
|
127
|
+
|
|
128
|
+
// 视距自适应:ssaoRadius 是世界空间遮蔽半径,换算为像素半径
|
|
129
|
+
// 近处像素多 → 像素半径大;远处像素少 → 像素半径小
|
|
130
|
+
float projScale = 1.0 / (2.0 * abs(viewZ) * resolution.x);
|
|
131
|
+
float pixelRadius = max(ssaoRadius * projScale, 1.0);
|
|
132
|
+
|
|
88
133
|
float occlusion = 0.0;
|
|
89
|
-
float radius = ssaoRadius;
|
|
90
|
-
|
|
91
134
|
float angle = random(vUv) * 6.2831853;
|
|
92
135
|
float stepAngle = 6.2831853 / float(sampleCount);
|
|
93
|
-
|
|
136
|
+
|
|
94
137
|
for (int i = 0; i < 64; i++) {
|
|
95
138
|
if (i >= sampleCount) break;
|
|
96
|
-
|
|
139
|
+
|
|
97
140
|
float theta = angle + float(i) * stepAngle;
|
|
98
|
-
float r = sqrt(float(i + 1)) * (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
vec2 sampleUv = vUv +
|
|
102
|
-
|
|
141
|
+
float r = sqrt(float(i + 1)) * (pixelRadius / sqrt(float(sampleCount)));
|
|
142
|
+
|
|
143
|
+
// 屏幕空间偏移(像素 → UV)
|
|
144
|
+
vec2 sampleUv = vUv + vec2(cos(theta), sin(theta)) * r * resolution;
|
|
145
|
+
|
|
103
146
|
if (sampleUv.x < 0.0 || sampleUv.x > 1.0 || sampleUv.y < 0.0 || sampleUv.y > 1.0) {
|
|
104
147
|
continue;
|
|
105
148
|
}
|
|
106
|
-
|
|
149
|
+
|
|
107
150
|
float sampleLogDepth = texture2D(depthTexture, sampleUv).r;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
151
|
+
// 背景像素跳过
|
|
152
|
+
if (sampleLogDepth >= 1.0) continue;
|
|
153
|
+
|
|
154
|
+
// 深度连续性:不同表面跳过(真正夹角深度值接近,假夹角深度差大)
|
|
155
|
+
float depthDiff = abs(sampleLogDepth - logDepth);
|
|
156
|
+
if (depthDiff > 0.002) continue;
|
|
157
|
+
|
|
158
|
+
float sampleViewZ = linearizeLogDepth(sampleLogDepth);
|
|
159
|
+
vec3 samplePosition = reconstructPosition(sampleUv, sampleViewZ);
|
|
160
|
+
|
|
111
161
|
vec3 diff = samplePosition - position;
|
|
112
162
|
float dist = length(diff);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
163
|
+
|
|
164
|
+
// 半球判断:采样方向必须在法线半球侧
|
|
165
|
+
// tangentDist = dot(diff, normal) 是到切面平面的有符号距离
|
|
166
|
+
// 平坦面 ≈ 0(不会超过 bias);夹角处显著 > 0
|
|
167
|
+
float tangentDist = dot(diff, normal);
|
|
168
|
+
if (tangentDist < ssaoBias) continue;
|
|
169
|
+
|
|
170
|
+
// 在衰减范围内
|
|
171
|
+
if (dist < ssaoFalloff) {
|
|
172
|
+
float rangeCheck = smoothstep(0.0, ssaoFalloff, dist);
|
|
173
|
+
occlusion += (1.0 - rangeCheck) * (1.0 - tangentDist / ssaoFalloff);
|
|
117
174
|
}
|
|
118
175
|
}
|
|
119
|
-
|
|
176
|
+
|
|
120
177
|
occlusion = 1.0 - (occlusion * ssaoIntensity / float(sampleCount));
|
|
121
178
|
occlusion = clamp(occlusion, 0.0, 1.0);
|
|
122
|
-
|
|
179
|
+
|
|
123
180
|
gl_FragColor = vec4(vec3(occlusion), 1.0);
|
|
124
181
|
}`,
|
|
125
182
|
blending: NoBlending,
|
|
@@ -132,6 +189,7 @@ const blurHShader = new RawShaderMaterial({
|
|
|
132
189
|
tDiffuse: { value: null },
|
|
133
190
|
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
134
191
|
blurRadius: { value: 2.0 },
|
|
192
|
+
depthTexture: { value: null },
|
|
135
193
|
},
|
|
136
194
|
vertexShader: `
|
|
137
195
|
attribute vec3 position;
|
|
@@ -145,24 +203,29 @@ const blurHShader = new RawShaderMaterial({
|
|
|
145
203
|
#ifdef GL_ES
|
|
146
204
|
precision highp float;
|
|
147
205
|
#endif
|
|
148
|
-
|
|
206
|
+
|
|
149
207
|
uniform sampler2D tDiffuse;
|
|
150
208
|
uniform vec2 resolution;
|
|
151
209
|
uniform float blurRadius;
|
|
152
|
-
|
|
210
|
+
uniform sampler2D depthTexture;
|
|
211
|
+
|
|
153
212
|
varying vec2 vUv;
|
|
154
|
-
|
|
213
|
+
|
|
155
214
|
void main() {
|
|
215
|
+
float centerDepth = texture2D(depthTexture, vUv).r;
|
|
156
216
|
vec4 color = vec4(0.0);
|
|
157
217
|
float totalWeight = 0.0;
|
|
158
|
-
|
|
218
|
+
|
|
159
219
|
for (int i = -4; i <= 4; i++) {
|
|
160
220
|
float weight = exp(-float(i * i) / 8.0);
|
|
161
221
|
vec2 offset = vec2(float(i) * blurRadius * resolution.x, 0.0);
|
|
162
|
-
|
|
163
|
-
|
|
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;
|
|
164
227
|
}
|
|
165
|
-
|
|
228
|
+
|
|
166
229
|
gl_FragColor = color / totalWeight;
|
|
167
230
|
}`,
|
|
168
231
|
blending: NoBlending,
|
|
@@ -175,6 +238,7 @@ const blurVShader = new RawShaderMaterial({
|
|
|
175
238
|
tDiffuse: { value: null },
|
|
176
239
|
resolution: { value: new Vector2(1 / 512, 1 / 512) },
|
|
177
240
|
blurRadius: { value: 2.0 },
|
|
241
|
+
depthTexture: { value: null },
|
|
178
242
|
},
|
|
179
243
|
vertexShader: `
|
|
180
244
|
attribute vec3 position;
|
|
@@ -188,24 +252,29 @@ const blurVShader = new RawShaderMaterial({
|
|
|
188
252
|
#ifdef GL_ES
|
|
189
253
|
precision highp float;
|
|
190
254
|
#endif
|
|
191
|
-
|
|
255
|
+
|
|
192
256
|
uniform sampler2D tDiffuse;
|
|
193
257
|
uniform vec2 resolution;
|
|
194
258
|
uniform float blurRadius;
|
|
195
|
-
|
|
259
|
+
uniform sampler2D depthTexture;
|
|
260
|
+
|
|
196
261
|
varying vec2 vUv;
|
|
197
|
-
|
|
262
|
+
|
|
198
263
|
void main() {
|
|
264
|
+
float centerDepth = texture2D(depthTexture, vUv).r;
|
|
199
265
|
vec4 color = vec4(0.0);
|
|
200
266
|
float totalWeight = 0.0;
|
|
201
|
-
|
|
267
|
+
|
|
202
268
|
for (int i = -4; i <= 4; i++) {
|
|
203
269
|
float weight = exp(-float(i * i) / 8.0);
|
|
204
270
|
vec2 offset = vec2(0.0, float(i) * blurRadius * resolution.y);
|
|
205
|
-
|
|
206
|
-
|
|
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;
|
|
207
276
|
}
|
|
208
|
-
|
|
277
|
+
|
|
209
278
|
gl_FragColor = color / totalWeight;
|
|
210
279
|
}`,
|
|
211
280
|
blending: NoBlending,
|
|
@@ -213,10 +282,11 @@ const blurVShader = new RawShaderMaterial({
|
|
|
213
282
|
depthWrite: false,
|
|
214
283
|
transparent: true,
|
|
215
284
|
});
|
|
216
|
-
const
|
|
285
|
+
const outputShader = new RawShaderMaterial({
|
|
217
286
|
uniforms: {
|
|
218
287
|
ssaoTexture: { value: null },
|
|
219
288
|
ssaoStrength: { value: 1.0 },
|
|
289
|
+
debug: { value: 0.0 },
|
|
220
290
|
},
|
|
221
291
|
vertexShader: `
|
|
222
292
|
attribute vec3 position;
|
|
@@ -230,65 +300,73 @@ const compositeShader = new RawShaderMaterial({
|
|
|
230
300
|
#ifdef GL_ES
|
|
231
301
|
precision highp float;
|
|
232
302
|
#endif
|
|
233
|
-
|
|
303
|
+
|
|
234
304
|
uniform sampler2D ssaoTexture;
|
|
235
305
|
uniform float ssaoStrength;
|
|
236
|
-
|
|
306
|
+
uniform float debug;
|
|
307
|
+
|
|
237
308
|
varying vec2 vUv;
|
|
238
|
-
|
|
309
|
+
|
|
239
310
|
void main() {
|
|
240
311
|
float ssao = texture2D(ssaoTexture, vUv).r;
|
|
241
312
|
float finalOcclusion = mix(1.0, ssao, ssaoStrength);
|
|
242
|
-
|
|
243
|
-
|
|
313
|
+
|
|
314
|
+
if (debug > 0.5) {
|
|
315
|
+
gl_FragColor = vec4(vec3(ssao), 1.0);
|
|
316
|
+
} else {
|
|
317
|
+
gl_FragColor = vec4(vec3(finalOcclusion), 1.0);
|
|
318
|
+
}
|
|
244
319
|
}`,
|
|
245
|
-
blending:
|
|
246
|
-
blendSrc: SrcColorFactor,
|
|
247
|
-
blendDst: OneFactor,
|
|
248
|
-
blendEquation: AddEquation,
|
|
320
|
+
blending: MultiplyBlending,
|
|
249
321
|
depthTest: false,
|
|
250
322
|
depthWrite: false,
|
|
251
|
-
transparent:
|
|
323
|
+
transparent: true,
|
|
252
324
|
});
|
|
253
325
|
export default function ssao_pass(renderer, camera, depthTexture, devicePixelRatio, options) {
|
|
254
|
-
if (!options.enable) {
|
|
326
|
+
if (!options.enable || !options.strength) {
|
|
255
327
|
return;
|
|
256
328
|
}
|
|
257
|
-
const originRenderTarget = renderer.getRenderTarget();
|
|
258
329
|
renderer.getSize(size);
|
|
259
330
|
size.multiplyScalar(devicePixelRatio);
|
|
260
331
|
ssaoTextureTarget.setSize(size.x, size.y);
|
|
261
332
|
blurTextureTarget.setSize(size.x, size.y);
|
|
262
333
|
projectionMatrix.copy(camera.projectionMatrix);
|
|
263
334
|
inverseProjectionMatrix.copy(projectionMatrix).invert();
|
|
335
|
+
// === 1. SSAO 遮蔽计算 ===
|
|
264
336
|
ssaoShader.uniforms.depthTexture.value = depthTexture;
|
|
265
337
|
ssaoShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
|
|
266
338
|
ssaoShader.uniforms.projectionMatrix.value = projectionMatrix;
|
|
267
339
|
ssaoShader.uniforms.inverseProjectionMatrix.value = inverseProjectionMatrix;
|
|
268
|
-
ssaoShader.uniforms.ssaoRadius.value = options.radius || 0
|
|
269
|
-
ssaoShader.uniforms.
|
|
270
|
-
ssaoShader.uniforms.
|
|
340
|
+
ssaoShader.uniforms.ssaoRadius.value = options.radius || 2.0;
|
|
341
|
+
ssaoShader.uniforms.ssaoFalloff.value = options.falloff || 5.0;
|
|
342
|
+
ssaoShader.uniforms.ssaoBias.value = options.bias || 0.3;
|
|
343
|
+
ssaoShader.uniforms.ssaoIntensity.value = options.intensity || 1.0;
|
|
271
344
|
ssaoShader.uniforms.sampleCount.value = options.sampleCount || 16;
|
|
272
345
|
ssaoShader.uniforms.cameraFar.value = options.cameraFar || camera.far || 20000;
|
|
273
346
|
renderer.setRenderTarget(ssaoTextureTarget);
|
|
274
347
|
renderer.clear();
|
|
275
348
|
fsQuad.render(renderer, ssaoShader);
|
|
349
|
+
// === 2. 双向模糊 ===
|
|
350
|
+
const blurRes = new Vector2(1 / size.x, 1 / size.y);
|
|
351
|
+
const blurR = options.blurRadius || 2.0;
|
|
276
352
|
blurHShader.uniforms.tDiffuse.value = ssaoTextureTarget.texture;
|
|
277
|
-
blurHShader.uniforms.resolution.value.
|
|
278
|
-
blurHShader.uniforms.blurRadius.value =
|
|
353
|
+
blurHShader.uniforms.resolution.value.copy(blurRes);
|
|
354
|
+
blurHShader.uniforms.blurRadius.value = blurR;
|
|
355
|
+
blurHShader.uniforms.depthTexture.value = depthTexture;
|
|
279
356
|
renderer.setRenderTarget(blurTextureTarget);
|
|
280
357
|
renderer.clear();
|
|
281
358
|
fsQuad.render(renderer, blurHShader);
|
|
282
359
|
blurVShader.uniforms.tDiffuse.value = blurTextureTarget.texture;
|
|
283
|
-
blurVShader.uniforms.resolution.value.
|
|
284
|
-
blurVShader.uniforms.blurRadius.value =
|
|
360
|
+
blurVShader.uniforms.resolution.value.copy(blurRes);
|
|
361
|
+
blurVShader.uniforms.blurRadius.value = blurR;
|
|
362
|
+
blurVShader.uniforms.depthTexture.value = depthTexture;
|
|
285
363
|
renderer.setRenderTarget(ssaoTextureTarget);
|
|
286
364
|
renderer.clear();
|
|
287
365
|
fsQuad.render(renderer, blurVShader);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
fsQuad.render(renderer,
|
|
366
|
+
// === 3. 乘法混合到屏幕 ===
|
|
367
|
+
renderer.setRenderTarget(null);
|
|
368
|
+
outputShader.uniforms.ssaoTexture.value = ssaoTextureTarget.texture;
|
|
369
|
+
outputShader.uniforms.ssaoStrength.value = options.strength || 1.0;
|
|
370
|
+
outputShader.uniforms.debug.value = options.debug ? 1.0 : 0.0;
|
|
371
|
+
fsQuad.render(renderer, outputShader);
|
|
294
372
|
}
|