@xviewer.js/postprocessing 1.0.0-alpha.12 → 1.0.0-alpha.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/dist/main.js +790 -80
- package/dist/main.js.map +1 -1
- package/dist/module.js +793 -84
- package/dist/module.js.map +1 -1
- package/package.json +2 -6
- package/types/BloomPlugin.d.ts +1 -0
- package/types/EffectComposerPlugin.d.ts +1 -0
- package/types/EffectPassPlugin.d.ts +1 -0
- package/types/FXAAPlugin.d.ts +1 -0
- package/types/MSAAPlugin.d.ts +1 -0
- package/types/SMAAPlugin.d.ts +1 -0
- package/types/TRAAPlugin.d.ts +1 -0
- package/types/TTTTTTTT.d.ts +2 -0
- package/types/ToneMappingPlugin.d.ts +1 -0
- package/types/index.d.ts +1 -0
package/dist/module.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Plugin,
|
|
2
|
-
import { RenderPass, EffectPass, EffectComposer, ToneMappingMode, ToneMappingEffect, BloomEffect, BlendFunction, FXAAEffect, SMAAPreset, EdgeDetectionMode, PredicationMode, SMAAEffect } from 'postprocessing';
|
|
3
|
-
import { HalfFloatType } from 'three';
|
|
1
|
+
import { Plugin, PropertyManager } from '@xviewer.js/core';
|
|
2
|
+
import { RenderPass, EffectPass, EffectComposer, ToneMappingMode, ToneMappingEffect, BloomEffect, BlendFunction, FXAAEffect, SMAAPreset, EdgeDetectionMode, PredicationMode, SMAAEffect, Pass, Effect } from 'postprocessing';
|
|
3
|
+
import { HalfFloatType, ShaderMaterial, Uniform, Vector2, Matrix4, Vector3, NoBlending, GLSL3, FramebufferTexture, LinearFilter, Clock, Quaternion, WebGLRenderTarget, NearestFilter, ShaderChunk, Matrix3, UniformsUtils, Color, RGBAFormat, DepthTexture, DataTexture } from 'three';
|
|
4
4
|
|
|
5
5
|
class EffectComposerPlugin extends Plugin {
|
|
6
6
|
static Instance(viewer) {
|
|
@@ -46,6 +46,7 @@ class EffectComposerPlugin extends Plugin {
|
|
|
46
46
|
}
|
|
47
47
|
constructor(props){
|
|
48
48
|
super();
|
|
49
|
+
this.type = "EffectComposerPlugin";
|
|
49
50
|
this.install = ()=>{
|
|
50
51
|
const { renderer, scene, camera } = this.viewer;
|
|
51
52
|
this._renderPass = new RenderPass(scene, camera);
|
|
@@ -64,35 +65,6 @@ class EffectComposerPlugin extends Plugin {
|
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
/******************************************************************************
|
|
68
|
-
Copyright (c) Microsoft Corporation.
|
|
69
|
-
|
|
70
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
71
|
-
purpose with or without fee is hereby granted.
|
|
72
|
-
|
|
73
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
74
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
75
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
76
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
77
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
78
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
79
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
80
|
-
***************************************************************************** */
|
|
81
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
function __decorate(decorators, target, key, desc) {
|
|
85
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
86
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
87
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
88
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
92
|
-
var e = new Error(message);
|
|
93
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
68
|
class PassPlugin extends Plugin {
|
|
97
69
|
get enable() {
|
|
98
70
|
return this.pass.enabled;
|
|
@@ -107,9 +79,6 @@ class PassPlugin extends Plugin {
|
|
|
107
79
|
this.composer.activePass(this.pass, v);
|
|
108
80
|
}
|
|
109
81
|
}
|
|
110
|
-
__decorate([
|
|
111
|
-
property
|
|
112
|
-
], PassPlugin.prototype, "enable", null);
|
|
113
82
|
|
|
114
83
|
class ToneMappingPlugin extends PassPlugin {
|
|
115
84
|
get mode() {
|
|
@@ -120,6 +89,7 @@ class ToneMappingPlugin extends PassPlugin {
|
|
|
120
89
|
}
|
|
121
90
|
constructor(props){
|
|
122
91
|
super();
|
|
92
|
+
this.type = "ToneMappingPlugin";
|
|
123
93
|
this.install = ()=>{
|
|
124
94
|
this.effect = new ToneMappingEffect(props);
|
|
125
95
|
this.pass = this.composer.addPass(new EffectPass(this.viewer.camera, this.effect));
|
|
@@ -129,25 +99,39 @@ class ToneMappingPlugin extends PassPlugin {
|
|
|
129
99
|
};
|
|
130
100
|
}
|
|
131
101
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
102
|
+
PropertyManager._getClassProperties("ToneMappingPlugin").property("enable").property("mode", {
|
|
103
|
+
value: ToneMappingMode
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
function _extends() {
|
|
107
|
+
_extends = Object.assign || function assign(target) {
|
|
108
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
109
|
+
var source = arguments[i];
|
|
110
|
+
for (var key in source) if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return target;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return _extends.apply(this, arguments);
|
|
117
|
+
}
|
|
137
118
|
|
|
138
119
|
class BloomPlugin extends PassPlugin {
|
|
120
|
+
// @property({ min: 0, max: 2, step: 0.01 })
|
|
139
121
|
get intensity() {
|
|
140
122
|
return this.effect.intensity;
|
|
141
123
|
}
|
|
142
124
|
set intensity(v) {
|
|
143
125
|
this.effect.intensity = v;
|
|
144
126
|
}
|
|
127
|
+
// @property({ min: 0, max: 10, step: 0.01 })
|
|
145
128
|
get luminanceThreshold() {
|
|
146
129
|
return this.effect.luminanceMaterial.threshold;
|
|
147
130
|
}
|
|
148
131
|
set luminanceThreshold(v) {
|
|
149
132
|
this.effect.luminanceMaterial.threshold = v;
|
|
150
133
|
}
|
|
134
|
+
// @property({ min: 0, max: 10, step: 0.01 })
|
|
151
135
|
get luminanceSmoothing() {
|
|
152
136
|
return this.effect.luminanceMaterial.smoothing;
|
|
153
137
|
}
|
|
@@ -156,11 +140,11 @@ class BloomPlugin extends PassPlugin {
|
|
|
156
140
|
}
|
|
157
141
|
constructor(props){
|
|
158
142
|
super();
|
|
143
|
+
this.type = "BloomPlugin";
|
|
159
144
|
this.install = ()=>{
|
|
160
|
-
this.effect = new BloomEffect({
|
|
161
|
-
blendFunction: BlendFunction.ADD
|
|
162
|
-
|
|
163
|
-
});
|
|
145
|
+
this.effect = new BloomEffect(_extends({
|
|
146
|
+
blendFunction: BlendFunction.ADD
|
|
147
|
+
}, props));
|
|
164
148
|
this.pass = this.composer.addPass(new EffectPass(this.viewer.camera, this.effect));
|
|
165
149
|
};
|
|
166
150
|
this.uninstall = ()=>{
|
|
@@ -168,31 +152,24 @@ class BloomPlugin extends PassPlugin {
|
|
|
168
152
|
};
|
|
169
153
|
}
|
|
170
154
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
], BloomPlugin.prototype, "luminanceThreshold", null);
|
|
185
|
-
__decorate([
|
|
186
|
-
property({
|
|
187
|
-
min: 0,
|
|
188
|
-
max: 10,
|
|
189
|
-
step: 0.01
|
|
190
|
-
})
|
|
191
|
-
], BloomPlugin.prototype, "luminanceSmoothing", null);
|
|
155
|
+
PropertyManager._getClassProperties("BloomPlugin").property("enable").property("intensity", {
|
|
156
|
+
min: 0,
|
|
157
|
+
max: 2,
|
|
158
|
+
step: 0.01
|
|
159
|
+
}).property("luminanceThreshold", {
|
|
160
|
+
min: 0,
|
|
161
|
+
max: 10,
|
|
162
|
+
step: 0.01
|
|
163
|
+
}).property("luminanceSmoothing", {
|
|
164
|
+
min: 0,
|
|
165
|
+
max: 10,
|
|
166
|
+
step: 0.01
|
|
167
|
+
});
|
|
192
168
|
|
|
193
169
|
class FXAAPlugin extends PassPlugin {
|
|
194
170
|
constructor(){
|
|
195
171
|
super();
|
|
172
|
+
this.type = "FXAAPlugin";
|
|
196
173
|
this.install = ()=>{
|
|
197
174
|
this.pass = this.composer.addPass(new EffectPass(this.viewer.camera, new FXAAEffect()));
|
|
198
175
|
};
|
|
@@ -201,8 +178,10 @@ class FXAAPlugin extends PassPlugin {
|
|
|
201
178
|
};
|
|
202
179
|
}
|
|
203
180
|
}
|
|
181
|
+
PropertyManager._getClassProperties("FXAAPlugin").property("enable");
|
|
204
182
|
|
|
205
183
|
class SMAAPlugin extends PassPlugin {
|
|
184
|
+
// @property({ value: SMAAPreset })
|
|
206
185
|
get preset() {
|
|
207
186
|
return this._preset;
|
|
208
187
|
}
|
|
@@ -212,12 +191,14 @@ class SMAAPlugin extends PassPlugin {
|
|
|
212
191
|
this.effect.applyPreset(v);
|
|
213
192
|
}
|
|
214
193
|
}
|
|
194
|
+
// @property({ value: EdgeDetectionMode })
|
|
215
195
|
get edgeDetectionMode() {
|
|
216
196
|
return this.effect.edgeDetectionMaterial.edgeDetectionMode;
|
|
217
197
|
}
|
|
218
198
|
set edgeDetectionMode(v) {
|
|
219
199
|
this.effect.edgeDetectionMaterial.edgeDetectionMode = v;
|
|
220
200
|
}
|
|
201
|
+
// @property({ value: PredicationMode })
|
|
221
202
|
get predicationMode() {
|
|
222
203
|
return this.effect.edgeDetectionMaterial.predicationMode;
|
|
223
204
|
}
|
|
@@ -226,6 +207,7 @@ class SMAAPlugin extends PassPlugin {
|
|
|
226
207
|
}
|
|
227
208
|
constructor(props = {}){
|
|
228
209
|
super();
|
|
210
|
+
this.type = "SMAAPlugin";
|
|
229
211
|
this._preset = SMAAPreset.MEDIUM;
|
|
230
212
|
this.install = ()=>{
|
|
231
213
|
this.effect = new SMAAEffect(props);
|
|
@@ -236,21 +218,13 @@ class SMAAPlugin extends PassPlugin {
|
|
|
236
218
|
};
|
|
237
219
|
}
|
|
238
220
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
value: EdgeDetectionMode
|
|
247
|
-
})
|
|
248
|
-
], SMAAPlugin.prototype, "edgeDetectionMode", null);
|
|
249
|
-
__decorate([
|
|
250
|
-
property({
|
|
251
|
-
value: PredicationMode
|
|
252
|
-
})
|
|
253
|
-
], SMAAPlugin.prototype, "predicationMode", null);
|
|
221
|
+
PropertyManager._getClassProperties("SMAAPlugin").property("enable").property("preset", {
|
|
222
|
+
value: SMAAPreset
|
|
223
|
+
}).property("edgeDetectionMode", {
|
|
224
|
+
value: EdgeDetectionMode
|
|
225
|
+
}).property("predicationMode", {
|
|
226
|
+
value: PredicationMode
|
|
227
|
+
});
|
|
254
228
|
|
|
255
229
|
class MSAAPlugin extends Plugin {
|
|
256
230
|
get enable() {
|
|
@@ -264,6 +238,7 @@ class MSAAPlugin extends Plugin {
|
|
|
264
238
|
}
|
|
265
239
|
constructor(){
|
|
266
240
|
super();
|
|
241
|
+
this.type = "MSAAPlugin";
|
|
267
242
|
this._maxSamples = 4;
|
|
268
243
|
this.install = ()=>{
|
|
269
244
|
const { renderer } = this.viewer;
|
|
@@ -275,9 +250,743 @@ class MSAAPlugin extends Plugin {
|
|
|
275
250
|
};
|
|
276
251
|
}
|
|
277
252
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
253
|
+
PropertyManager._getClassProperties("MSAAPlugin").property("enable");
|
|
254
|
+
|
|
255
|
+
// from: https://news.ycombinator.com/item?id=17876741
|
|
256
|
+
// reference: http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
|
|
257
|
+
// eslint-disable-next-line no-unused-vars
|
|
258
|
+
const g = 1.32471795724474602596090885447809 // Plastic number
|
|
259
|
+
;
|
|
260
|
+
const a1 = 1.0 / g;
|
|
261
|
+
const a2 = 1.0 / (g * g);
|
|
262
|
+
const base = 1.1127756842787055 // harmoniousNumber(7), yields better coverage compared to using 0.5
|
|
263
|
+
;
|
|
264
|
+
const generateR2 = (count)=>{
|
|
265
|
+
const points = [];
|
|
266
|
+
for(let n = 0; n < count; n++){
|
|
267
|
+
points.push([
|
|
268
|
+
(base + a1 * n) % 1,
|
|
269
|
+
(base + a2 * n) % 1
|
|
270
|
+
]);
|
|
271
|
+
}
|
|
272
|
+
return points;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const r2Sequence = generateR2(256).map(([a, b])=>[
|
|
276
|
+
a - 0.5,
|
|
277
|
+
b - 0.5
|
|
278
|
+
]);
|
|
279
|
+
function jitter(width, height, camera, frame, jitterScale = 1) {
|
|
280
|
+
const [x, y] = r2Sequence[frame % r2Sequence.length];
|
|
281
|
+
if (camera.setViewOffset) {
|
|
282
|
+
camera.setViewOffset(width, height, x * jitterScale, y * jitterScale, width, height);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
var vertexShader = "#define GLSLIFY 1\nvarying vec2 vUv;void main(){vUv=position.xy*0.5+0.5;gl_Position=vec4(position.xy,1.0,1.0);}"; // eslint-disable-line
|
|
287
|
+
|
|
288
|
+
var fragmentShader = "#define GLSLIFY 1\nvarying vec2 vUv;uniform highp sampler2D inputTexture;uniform highp sampler2D velocityTexture;uniform highp sampler2D depthTexture;uniform highp sampler2D lastVelocityTexture;uniform float maxBlend;uniform float neighborhoodClampIntensity;uniform bool fullAccumulate;uniform vec2 invTexSize;uniform float cameraNear;uniform float cameraFar;uniform mat4 projectionMatrix;uniform mat4 projectionMatrixInverse;uniform mat4 cameraMatrixWorld;uniform vec3 cameraPos;uniform vec3 prevCameraPos;uniform mat4 prevViewMatrix;uniform mat4 prevCameraMatrixWorld;uniform mat4 prevProjectionMatrix;uniform mat4 prevProjectionMatrixInverse;uniform float keepData;\n#define EPSILON 0.00001\n#define DIFFUSE_SPECULAR 0\n#define DIFFUSE 1\n#define SPECULAR 2\n#include <gbuffer_packing>\n#include <packing>\n#include <reproject>\nvec3 reprojectedUvDiffuse=vec3(-1.0),reprojectedUvSpecular=vec3(-1.0);void accumulate(inout vec4 outputColor,inout vec4 inp,inout vec4 acc,inout float roughness,inout float moveFactor,bool doReprojectSpecular){vec3 reprojectedUvConfidence=doReprojectSpecular ? reprojectedUvSpecular : reprojectedUvDiffuse;vec2 reprojectedUv=reprojectedUvConfidence.xy;float confidence=reprojectedUvConfidence.z;confidence=pow(confidence,confidencePower);float accumBlend=1.-1./(acc.a+1.0);accumBlend=mix(0.,accumBlend,confidence);float maxValue=(fullAccumulate ? 1. : maxBlend)*keepData;\n#if inputType != DIFFUSE\nconst float roughnessMaximum=0.1;if(doReprojectSpecular&&roughness>=0.0&&roughness<roughnessMaximum){float maxRoughnessValue=mix(0.,maxValue,roughness/roughnessMaximum);maxValue=mix(maxValue,maxRoughnessValue,min(100.*moveFactor,1.));}\n#endif\nfloat temporalReprojectMix=min(accumBlend,maxValue);acc.a=1./(1.-temporalReprojectMix)-1.;acc.a=min(65536.,acc.a);outputColor.rgb=mix(inp.rgb,acc.rgb,temporalReprojectMix);outputColor.a=acc.a;undoColorTransform(outputColor.rgb);}void reproject(inout vec4 inp,inout vec4 acc,sampler2D accumulatedTexture,inout bool wasSampled,bool doNeighborhoodClamp,bool doReprojectSpecular){vec3 uvc=doReprojectSpecular ? reprojectedUvSpecular : reprojectedUvDiffuse;vec2 uv=uvc.xy;acc=sampleReprojectedTexture(accumulatedTexture,uv);transformColor(acc.rgb);if(!wasSampled){inp.rgb=acc.rgb;return;}acc.a++;vec3 clampedColor=acc.rgb;int clampRadius=doReprojectSpecular&&roughness<0.25 ? 1 : 2;clampNeighborhood(inputTexture,clampedColor,inp.rgb,clampRadius,doReprojectSpecular);float r=doReprojectSpecular ? roughness : 1.0;float clampAggressiveness=min(1.,uvc.z*r);float clampIntensity=mix(0.,min(1.,moveFactor*50.+neighborhoodClampIntensity),clampAggressiveness);vec3 newColor=mix(acc.rgb,clampedColor,clampIntensity);float colorDiff=min(length(newColor-acc.rgb),1.);acc.a*=1.-colorDiff;acc.rgb=newColor;}void preprocessInput(inout highp vec4 texel,inout bool sampledThisFrame){sampledThisFrame=texel.r>=0.;texel.rgb=max(texel.rgb,vec3(0.));transformColor(texel.rgb);}void getTexels(inout highp vec4 inputTexel[textureCount],inout bool sampledThisFrame[textureCount]){\n#if inputType == DIFFUSE_SPECULAR\nhighp vec4 tex=textureLod(inputTexture,vUv,0.);unpackTwoVec4(tex,inputTexel[0],inputTexel[1]);preprocessInput(inputTexel[0],sampledThisFrame[0]);preprocessInput(inputTexel[1],sampledThisFrame[1]);\n#else\ninputTexel[0]=textureLod(inputTexture,vUv,0.0);preprocessInput(inputTexel[0],sampledThisFrame[0]);\n#endif\n}void computeGVariables(vec2 dilatedUv,float depth){worldPos=screenSpaceToWorldSpace(dilatedUv,depth,cameraMatrixWorld,projectionMatrixInverse);vec3 viewPos=(viewMatrix*vec4(worldPos,1.0)).xyz;viewDir=normalize(viewPos);vec3 viewNormal=(vec4(worldNormal,0.0)*viewMatrix).xyz;viewAngle=dot(-viewDir,viewNormal);}void computeReprojectedUv(float depth,vec3 worldPos,vec3 worldNormal){reprojectedUvDiffuse=getReprojectedUV(false,depth,worldPos,worldNormal);\n#if inputType == DIFFUSE_SPECULAR || inputType == SPECULAR\nreprojectedUvSpecular=getReprojectedUV(true,depth,worldPos,worldNormal);if(reprojectedUvSpecular.x==-1.0){reprojectedUvSpecular=reprojectedUvDiffuse;}\n#endif\n}void getRoughnessRayLength(inout highp vec4 inputTexel[textureCount]){\n#if inputType == DIFFUSE_SPECULAR\nrayLength=inputTexel[1].a;roughness=clamp(inputTexel[0].a,0.,1.);\n#elif inputType == SPECULAR\nvec2 data=unpackHalf2x16(floatBitsToUint(inputTexel[0].a));rayLength=data.r;roughness=clamp(data.g,0.,1.);\n#endif\n}void main(){vec2 dilatedUv=vUv;getVelocityNormalDepth(dilatedUv,velocity,worldNormal,depth);highp vec4 inputTexel[textureCount],accumulatedTexel[textureCount];bool textureSampledThisFrame[textureCount];getTexels(inputTexel,textureSampledThisFrame);\n#if inputType != DIFFUSE\nif(depth==1.0&&fwidth(depth)==0.0){discard;return;}\n#endif\ncurvature=getCurvature(worldNormal);computeGVariables(dilatedUv,depth);getRoughnessRayLength(inputTexel);computeReprojectedUv(depth,worldPos,worldNormal);moveFactor=min(dot(velocity,velocity)*10000.,1.);\n#pragma unroll_loop_start\nfor(int i=0;i<textureCount;i++){reproject(inputTexel[i],accumulatedTexel[i],accumulatedTexture[i],textureSampledThisFrame[i],neighborhoodClamp[i],reprojectSpecular[i]);accumulate(gOutput[i],inputTexel[i],accumulatedTexel[i],roughness,moveFactor,reprojectSpecular[i]);}\n#pragma unroll_loop_end\n}"; // eslint-disable-line
|
|
289
|
+
|
|
290
|
+
var reproject = "#define GLSLIFY 1\nvec2 dilatedUv,velocity;vec3 worldNormal,worldPos,viewDir;float depth,curvature,viewAngle,rayLength,angleMix;float roughness=1.;float moveFactor=0.;\n#define luminance(a) dot(vec3(0.2125, 0.7154, 0.0721), a)\nfloat getViewZ(const in float depth){\n#ifdef PERSPECTIVE_CAMERA\nreturn perspectiveDepthToViewZ(depth,cameraNear,cameraFar);\n#else\nreturn orthographicDepthToViewZ(depth,cameraNear,cameraFar);\n#endif\n}vec3 screenSpaceToWorldSpace(const vec2 uv,const float depth,mat4 curMatrixWorld,const mat4 projMatrixInverse){vec4 ndc=vec4((uv.x-0.5)*2.0,(uv.y-0.5)*2.0,(depth-0.5)*2.0,1.0);vec4 clip=projMatrixInverse*ndc;vec4 view=curMatrixWorld*(clip/clip.w);return view.xyz;}vec2 viewSpaceToScreenSpace(const vec3 position,const mat4 projMatrix){vec4 projectedCoord=projMatrix*vec4(position,1.0);projectedCoord.xy/=projectedCoord.w;projectedCoord.xy=projectedCoord.xy*0.5+0.5;return projectedCoord.xy;}\n#ifdef logTransform\nvoid transformColor(inout vec3 color){color=log(color+1.);}void undoColorTransform(inout vec3 color){color=exp(color)-1.;}\n#else\n#define transformColor\n#define undoColorTransform\n#endif\nvoid getNeighborhoodAABB(const sampler2D tex,const int clampRadius,inout vec3 minNeighborColor,inout vec3 maxNeighborColor,const bool isSpecular){for(int x=-clampRadius;x<=clampRadius;x++){for(int y=-clampRadius;y<=clampRadius;y++){vec2 offset=vec2(x,y)*invTexSize;vec2 neighborUv=vUv+offset;\n#if inputType == DIFFUSE_SPECULAR\nvec4 t1,t2;vec4 packedNeighborTexel=textureLod(inputTexture,neighborUv,0.0);unpackTwoVec4(packedNeighborTexel,t1,t2);vec4 neighborTexel=isSpecular ? t2 : t1;\n#else\nvec4 neighborTexel=textureLod(inputTexture,neighborUv,0.0);\n#endif\nif(neighborTexel.r>=0.){minNeighborColor=min(neighborTexel.rgb,minNeighborColor);maxNeighborColor=max(neighborTexel.rgb,maxNeighborColor);}}}}void clampNeighborhood(const sampler2D tex,inout vec3 color,vec3 inputColor,const int clampRadius,const bool isSpecular){undoColorTransform(inputColor);vec3 minNeighborColor=inputColor;vec3 maxNeighborColor=inputColor;getNeighborhoodAABB(tex,clampRadius,minNeighborColor,maxNeighborColor,isSpecular);transformColor(minNeighborColor);transformColor(maxNeighborColor);color=clamp(color,minNeighborColor,maxNeighborColor);}void getVelocityNormalDepth(inout vec2 dilatedUv,out vec2 vel,out vec3 normal,out float depth){vec2 centerUv=dilatedUv;vec4 velocityTexel=textureLod(velocityTexture,centerUv,0.0);vel=velocityTexel.rg;normal=unpackNormal(velocityTexel.b);depth=velocityTexel.a;}\n#define PLANE_DISTANCE 20.\n#define WORLD_DISTANCE 10.\n#define NORMAL_DISTANCE 1.\nfloat planeDistanceDisocclusionCheck(const vec3 worldPos,const vec3 lastWorldPos,const vec3 worldNormal,const float distFactor){vec3 toCurrent=worldPos-lastWorldPos;float distToPlane=abs(dot(toCurrent,worldNormal));return distToPlane/PLANE_DISTANCE*distFactor;}float worldDistanceDisocclusionCheck(const vec3 worldPos,const vec3 lastWorldPos,const float distFactor){return length(worldPos-lastWorldPos)/WORLD_DISTANCE*distFactor;}float normalDisocclusionCheck(const vec3 worldNormal,const vec3 lastWorldNormal,const float distFactor){return min(1.-dot(worldNormal,lastWorldNormal),1.)/NORMAL_DISTANCE*distFactor;}float validateReprojectedUV(const vec2 reprojectedUv,const vec3 worldPos,const vec3 worldNormal,const bool isHitPoint){if(reprojectedUv.x>1.0||reprojectedUv.x<0.0||reprojectedUv.y>1.0||reprojectedUv.y<0.0)return 0.;vec2 dilatedReprojectedUv=reprojectedUv;vec2 lastVelocity=vec2(0.0);vec3 lastWorldNormal=vec3(0.0);float lastDepth=0.0;getVelocityNormalDepth(dilatedReprojectedUv,lastVelocity,lastWorldNormal,lastDepth);vec3 lastWorldPos=screenSpaceToWorldSpace(dilatedReprojectedUv,lastDepth,prevCameraMatrixWorld,prevProjectionMatrixInverse);vec3 lastViewPos=(prevViewMatrix*vec4(lastWorldPos,1.0)).xyz;vec3 lastViewDir=normalize(lastViewPos);vec3 lastViewNormal=(vec4(lastWorldNormal,0.0)*prevViewMatrix).xyz;float lastViewAngle=dot(-lastViewDir,lastViewNormal);angleMix=abs(lastViewAngle-viewAngle);float viewZ=abs(getViewZ(depth));float distFactor=1.+1./(viewZ+1.0);float disoccl=0.;disoccl+=worldDistanceDisocclusionCheck(worldPos,lastWorldPos,distFactor);disoccl+=planeDistanceDisocclusionCheck(worldPos,lastWorldPos,worldNormal,distFactor);disoccl+=normalDisocclusionCheck(worldNormal,lastWorldNormal,distFactor);float confidence=1.-min(disoccl,1.);confidence=max(confidence,0.);confidence=pow(confidence,confidencePower);return confidence;}vec2 reprojectHitPoint(const vec3 rayOrig,const float rayLength){if(curvature>0.05||rayLength<0.01){return vec2(-1.);}vec3 cameraRay=normalize(rayOrig-cameraPos);vec3 parallaxHitPoint=cameraPos+cameraRay*rayLength;vec4 reprojectedHitPoint=prevProjectionMatrix*prevViewMatrix*vec4(parallaxHitPoint,1.0);reprojectedHitPoint.xyz/=reprojectedHitPoint.w;reprojectedHitPoint.xy=reprojectedHitPoint.xy*0.5+0.5;vec2 diffuseUv=vUv-velocity.xy;float m=min(max(0.,roughness-0.25)/0.25,1.);return reprojectedHitPoint.xy;}vec3 getReprojectedUV(const bool doReprojectSpecular,const float depth,const vec3 worldPos,const vec3 worldNormal){if(doReprojectSpecular){vec2 reprojectedUv=reprojectHitPoint(worldPos,rayLength);float confidence=validateReprojectedUV(reprojectedUv,worldPos,worldNormal,true);return vec3(reprojectedUv,confidence);}else{vec2 reprojectedUv=vUv-velocity;float confidence=validateReprojectedUV(reprojectedUv,worldPos,worldNormal,false);return vec3(reprojectedUv,confidence);}}vec4 BiCubicCatmullRom5Tap(sampler2D tex,vec2 P){vec2 Weight[3];vec2 Sample[3];vec2 UV=P/invTexSize;vec2 tc=floor(UV-0.5)+0.5;vec2 f=UV-tc;vec2 f2=f*f;vec2 f3=f2*f;vec2 w0=f2-0.5*(f3+f);vec2 w1=1.5*f3-2.5*f2+vec2(1.);vec2 w3=0.5*(f3-f2);vec2 w2=vec2(1.)-w0-w1-w3;Weight[0]=w0;Weight[1]=w1+w2;Weight[2]=w3;Sample[0]=tc-vec2(1.);Sample[1]=tc+w2/Weight[1];Sample[2]=tc+vec2(2.);Sample[0]*=invTexSize;Sample[1]*=invTexSize;Sample[2]*=invTexSize;float sampleWeight[5];sampleWeight[0]=Weight[1].x*Weight[0].y;sampleWeight[1]=Weight[0].x*Weight[1].y;sampleWeight[2]=Weight[1].x*Weight[1].y;sampleWeight[3]=Weight[2].x*Weight[1].y;sampleWeight[4]=Weight[1].x*Weight[2].y;vec4 Ct=textureLod(tex,vec2(Sample[1].x,Sample[0].y),0.)*sampleWeight[0];vec4 Cl=textureLod(tex,vec2(Sample[0].x,Sample[1].y),0.)*sampleWeight[1];vec4 Cc=textureLod(tex,vec2(Sample[1].x,Sample[1].y),0.)*sampleWeight[2];vec4 Cr=textureLod(tex,vec2(Sample[2].x,Sample[1].y),0.)*sampleWeight[3];vec4 Cb=textureLod(tex,vec2(Sample[1].x,Sample[2].y),0.)*sampleWeight[4];float WeightMultiplier=1./(sampleWeight[0]+sampleWeight[1]+sampleWeight[2]+sampleWeight[3]+sampleWeight[4]);return max((Ct+Cl+Cc+Cr+Cb)*WeightMultiplier,vec4(0.));}vec4 sampleReprojectedTexture(const sampler2D tex,const vec2 reprojectedUv){vec4 catmull=BiCubicCatmullRom5Tap(tex,reprojectedUv);return catmull;}float getCurvature(vec3 n){float curvature=length(fwidth(n));return curvature;}"; // eslint-disable-line
|
|
291
|
+
|
|
292
|
+
var gbuffer_packing = "#define GLSLIFY 1\nuniform highp sampler2D gBufferTexture;struct Material{highp vec4 diffuse;highp vec3 normal;highp float roughness;highp float metalness;highp vec3 emissive;};\n#define ONE_SAFE 0.999999\n#define NON_ZERO_OFFSET 0.0001\nconst highp float c_precision=256.0;const highp float c_precisionp1=c_precision+1.0;highp float color2float(in highp vec3 color){color=min(color+NON_ZERO_OFFSET,vec3(ONE_SAFE));return floor(color.r*c_precision+0.5)+floor(color.b*c_precision+0.5)*c_precisionp1+floor(color.g*c_precision+0.5)*c_precisionp1*c_precisionp1;}highp vec3 float2color(in highp float value){highp vec3 color;color.r=mod(value,c_precisionp1)/c_precision;color.b=mod(floor(value/c_precisionp1),c_precisionp1)/c_precision;color.g=floor(value/(c_precisionp1*c_precisionp1))/c_precision;color-=NON_ZERO_OFFSET;color=max(color,vec3(0.0));return color;}highp vec2 OctWrap(highp vec2 v){highp vec2 w=1.0-abs(v.yx);if(v.x<0.0)w.x=-w.x;if(v.y<0.0)w.y=-w.y;return w;}highp vec2 encodeOctWrap(highp vec3 n){n/=(abs(n.x)+abs(n.y)+abs(n.z));n.xy=n.z>0.0 ? n.xy : OctWrap(n.xy);n.xy=n.xy*0.5+0.5;return n.xy;}highp vec3 decodeOctWrap(highp vec2 f){f=f*2.0-1.0;highp vec3 n=vec3(f.x,f.y,1.0-abs(f.x)-abs(f.y));highp float t=max(-n.z,0.0);n.x+=n.x>=0.0 ?-t : t;n.y+=n.y>=0.0 ?-t : t;return normalize(n);}highp float packNormal(highp vec3 normal){return uintBitsToFloat(packHalf2x16(encodeOctWrap(normal)));}highp vec3 unpackNormal(highp float packedNormal){return decodeOctWrap(unpackHalf2x16(floatBitsToUint(packedNormal)));}highp vec4 packTwoVec4(highp vec4 v1,highp vec4 v2){highp vec4 encoded=vec4(0.0);v1+=NON_ZERO_OFFSET;v2+=NON_ZERO_OFFSET;highp uint v1r=packHalf2x16(v1.rg);highp uint v1g=packHalf2x16(v1.ba);highp uint v2r=packHalf2x16(v2.rg);highp uint v2g=packHalf2x16(v2.ba);encoded.r=uintBitsToFloat(v1r);encoded.g=uintBitsToFloat(v1g);encoded.b=uintBitsToFloat(v2r);encoded.a=uintBitsToFloat(v2g);return encoded;}void unpackTwoVec4(highp vec4 encoded,out highp vec4 v1,out highp vec4 v2){highp uint r=floatBitsToUint(encoded.r);highp uint g=floatBitsToUint(encoded.g);highp uint b=floatBitsToUint(encoded.b);highp uint a=floatBitsToUint(encoded.a);v1.rg=unpackHalf2x16(r);v1.ba=unpackHalf2x16(g);v2.rg=unpackHalf2x16(b);v2.ba=unpackHalf2x16(a);v1-=NON_ZERO_OFFSET;v2-=NON_ZERO_OFFSET;}vec4 unpackTwoVec4(highp vec4 encoded,const int index){highp uint r=floatBitsToUint(index==0 ? encoded.r : encoded.b);highp uint g=floatBitsToUint(index==0 ? encoded.g : encoded.a);vec4 v;v.rg=unpackHalf2x16(r);v.ba=unpackHalf2x16(g);v-=NON_ZERO_OFFSET;return v;}highp vec4 encodeRGBE8(highp vec3 rgb){highp vec4 vEncoded;highp float maxComponent=max(max(rgb.r,rgb.g),rgb.b);highp float fExp=ceil(log2(maxComponent));vEncoded.rgb=rgb/exp2(fExp);vEncoded.a=(fExp+128.0)/255.0;return vEncoded;}highp vec3 decodeRGBE8(highp vec4 rgbe){highp vec3 vDecoded;highp float fExp=rgbe.a*255.0-128.0;vDecoded=rgbe.rgb*exp2(fExp);return vDecoded;}highp float vec4ToFloat(highp vec4 vec){vec=min(vec+NON_ZERO_OFFSET,vec4(ONE_SAFE));highp uvec4 v=uvec4(vec*255.0);highp uint value=(v.a<<24u)|(v.b<<16u)|(v.g<<8u)|(v.r);return uintBitsToFloat(value);}highp vec4 floatToVec4(highp float f){highp uint value=floatBitsToUint(f);highp vec4 v;v.r=float(value&0xFFu)/255.0;v.g=float((value>>8u)&0xFFu)/255.0;v.b=float((value>>16u)&0xFFu)/255.0;v.a=float((value>>24u)&0xFFu)/255.0;v-=NON_ZERO_OFFSET;v=max(v,vec4(0.0));return v;}highp vec4 packGBuffer(highp vec4 diffuse,highp vec3 normal,highp float roughness,highp float metalness,highp vec3 emissive){highp vec4 gBuffer;gBuffer.r=vec4ToFloat(diffuse);gBuffer.g=packNormal(normal);gBuffer.b=color2float(vec3(roughness,metalness,0.));gBuffer.a=vec4ToFloat(encodeRGBE8(emissive));return gBuffer;}Material getMaterial(highp sampler2D gBufferTexture,highp vec2 uv){highp vec4 gBuffer=textureLod(gBufferTexture,uv,0.0);highp vec4 diffuse=floatToVec4(gBuffer.r);highp vec3 normal=unpackNormal(gBuffer.g);highp vec3 roughnessMetalness=float2color(gBuffer.b);highp float roughness=roughnessMetalness.r;highp float metalness=roughnessMetalness.g;highp vec3 emissive=decodeRGBE8(floatToVec4(gBuffer.a));return Material(diffuse,normal,roughness,metalness,emissive);}Material getMaterial(highp vec2 uv){return getMaterial(gBufferTexture,uv);}highp vec3 getNormal(highp sampler2D gBufferTexture,highp vec2 uv){return unpackNormal(textureLod(gBufferTexture,uv,0.0).g);}"; // eslint-disable-line
|
|
293
|
+
|
|
294
|
+
// source: https://github.com/mrdoob/three.js/blob/b9bc47ab1978022ab0947a9bce1b1209769b8d91/src/renderers/webgl/WebGLProgram.js#L228
|
|
295
|
+
// Unroll Loops
|
|
296
|
+
const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\s*int\s+i\s*=\s*(\d+)\s*;\s*i\s*<\s*(\d+)\s*;\s*i\s*\+\+\s*\)\s*{([\s\S]+?)}\s+#pragma unroll_loop_end/g;
|
|
297
|
+
function unrollLoops(string) {
|
|
298
|
+
return string.replace(unrollLoopPattern, loopReplacer);
|
|
299
|
+
}
|
|
300
|
+
function loopReplacer(match, start, end, snippet) {
|
|
301
|
+
let string = "";
|
|
302
|
+
for(let i = parseInt(start); i < parseInt(end); i++){
|
|
303
|
+
string += snippet.replace(/\[\s*i\s*\]/g, "[ " + i + " ]").replace(/UNROLLED_LOOP_INDEX/g, i);
|
|
304
|
+
}
|
|
305
|
+
return string;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
class TemporalReprojectMaterial extends ShaderMaterial {
|
|
309
|
+
constructor(textureCount = 1){
|
|
310
|
+
let finalFragmentShader = fragmentShader.replace("#include <reproject>", reproject).replace("#include <gbuffer_packing>", gbuffer_packing);
|
|
311
|
+
let definitions = "";
|
|
312
|
+
for(let i = 0; i < textureCount; i++){
|
|
313
|
+
definitions += /* glsl */ `
|
|
314
|
+
uniform sampler2D accumulatedTexture${i};
|
|
315
|
+
|
|
316
|
+
layout(location = ${i}) out vec4 gOutput${i};
|
|
317
|
+
`;
|
|
318
|
+
}
|
|
319
|
+
finalFragmentShader = definitions + finalFragmentShader.replaceAll("textureCount", textureCount);
|
|
320
|
+
finalFragmentShader = unrollLoops(finalFragmentShader);
|
|
321
|
+
const matches2 = finalFragmentShader.matchAll(/accumulatedTexture\[\s*[0-9]+\s*]/g);
|
|
322
|
+
for (const [key] of matches2){
|
|
323
|
+
const number = key.replace(/[^0-9]/g, "");
|
|
324
|
+
finalFragmentShader = finalFragmentShader.replace(key, "accumulatedTexture" + number);
|
|
325
|
+
}
|
|
326
|
+
const matches3 = finalFragmentShader.matchAll(/gOutput\[\s*[0-9]+\s*]/g);
|
|
327
|
+
for (const [key] of matches3){
|
|
328
|
+
const number = key.replace(/[^0-9]/g, "");
|
|
329
|
+
finalFragmentShader = finalFragmentShader.replace(key, "gOutput" + number);
|
|
330
|
+
}
|
|
331
|
+
super({
|
|
332
|
+
type: "TemporalReprojectMaterial",
|
|
333
|
+
uniforms: {
|
|
334
|
+
inputTexture: new Uniform(null),
|
|
335
|
+
velocityTexture: new Uniform(null),
|
|
336
|
+
depthTexture: new Uniform(null),
|
|
337
|
+
lastVelocityTexture: new Uniform(null),
|
|
338
|
+
neighborhoodClampIntensity: new Uniform(0),
|
|
339
|
+
fullAccumulate: new Uniform(false),
|
|
340
|
+
keepData: new Uniform(1),
|
|
341
|
+
delta: new Uniform(0),
|
|
342
|
+
invTexSize: new Uniform(new Vector2()),
|
|
343
|
+
projectionMatrix: new Uniform(new Matrix4()),
|
|
344
|
+
projectionMatrixInverse: new Uniform(new Matrix4()),
|
|
345
|
+
cameraMatrixWorld: new Uniform(new Matrix4()),
|
|
346
|
+
viewMatrix: new Uniform(new Matrix4()),
|
|
347
|
+
prevViewMatrix: new Uniform(new Matrix4()),
|
|
348
|
+
prevCameraMatrixWorld: new Uniform(new Matrix4()),
|
|
349
|
+
prevProjectionMatrix: new Uniform(new Matrix4()),
|
|
350
|
+
prevProjectionMatrixInverse: new Uniform(new Matrix4()),
|
|
351
|
+
cameraPos: new Uniform(new Vector3()),
|
|
352
|
+
prevCameraPos: new Uniform(new Vector3()),
|
|
353
|
+
cameraNear: new Uniform(0),
|
|
354
|
+
cameraFar: new Uniform(0),
|
|
355
|
+
maxBlend: new Uniform(0)
|
|
356
|
+
},
|
|
357
|
+
vertexShader,
|
|
358
|
+
fragmentShader: finalFragmentShader,
|
|
359
|
+
blending: NoBlending,
|
|
360
|
+
depthWrite: false,
|
|
361
|
+
depthTest: false,
|
|
362
|
+
toneMapped: false,
|
|
363
|
+
glslVersion: GLSL3
|
|
364
|
+
});
|
|
365
|
+
for(let i = 0; i < textureCount; i++){
|
|
366
|
+
this.uniforms["inputTexture" + i] = new Uniform(null);
|
|
367
|
+
this.uniforms["accumulatedTexture" + i] = new Uniform(null);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const isGroundProjectedEnv = (c)=>{
|
|
373
|
+
var _c_material_fragmentShader;
|
|
374
|
+
return (_c_material_fragmentShader = c.material.fragmentShader) == null ? void 0 : _c_material_fragmentShader.includes("float intersection2 = diskIntersectWithBackFaceCulling( camPos, p, h, vec3( 0.0, 1.0, 0.0 ), radius );");
|
|
375
|
+
};
|
|
376
|
+
const isChildMaterialRenderable = (c, material = c.material)=>{
|
|
377
|
+
return material.visible && material.depthWrite && material.depthTest && (!material.transparent || material.opacity > 0) && !isGroundProjectedEnv(c);
|
|
378
|
+
};
|
|
379
|
+
const didCameraMove = (camera, lastCameraPosition, lastCameraQuaternion)=>{
|
|
380
|
+
if (camera.position.distanceToSquared(lastCameraPosition) > 0.000001) {
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
if (camera.quaternion.angleTo(lastCameraQuaternion) > 0.001) {
|
|
384
|
+
return true;
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
};
|
|
388
|
+
const getVisibleChildren = (object)=>{
|
|
389
|
+
const queue = [
|
|
390
|
+
object
|
|
391
|
+
];
|
|
392
|
+
const objects = [];
|
|
393
|
+
while(queue.length !== 0){
|
|
394
|
+
const mesh = queue.shift();
|
|
395
|
+
if (mesh.material) objects.push(mesh);
|
|
396
|
+
for (const c of mesh.children){
|
|
397
|
+
if (c.visible) queue.push(c);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return objects;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const defaultTemporalReprojectPassOptions = {
|
|
404
|
+
dilation: false,
|
|
405
|
+
fullAccumulate: false,
|
|
406
|
+
neighborhoodClamp: false,
|
|
407
|
+
neighborhoodClampRadius: 1,
|
|
408
|
+
neighborhoodClampIntensity: 1,
|
|
409
|
+
maxBlend: 1,
|
|
410
|
+
logTransform: false,
|
|
411
|
+
depthDistance: 2,
|
|
412
|
+
worldDistance: 4,
|
|
413
|
+
reprojectSpecular: false,
|
|
414
|
+
renderTarget: null,
|
|
415
|
+
copyTextures: true,
|
|
416
|
+
confidencePower: 0.75,
|
|
417
|
+
inputType: "diffuse"
|
|
418
|
+
};
|
|
419
|
+
const tmpProjectionMatrix$1 = new Matrix4();
|
|
420
|
+
const tmpProjectionMatrixInverse$1 = new Matrix4();
|
|
421
|
+
const tmpVec2 = new Vector2();
|
|
422
|
+
class TemporalReprojectPass extends Pass {
|
|
423
|
+
setInputTexture(texture) {
|
|
424
|
+
this.fullscreenMaterial.uniforms.inputTexture.value = texture;
|
|
425
|
+
}
|
|
426
|
+
dispose() {
|
|
427
|
+
super.dispose();
|
|
428
|
+
this.renderTarget.dispose();
|
|
429
|
+
this.fullscreenMaterial.dispose();
|
|
430
|
+
}
|
|
431
|
+
setSize(width, height) {
|
|
432
|
+
var _this_framebufferTexture;
|
|
433
|
+
this.renderTarget.setSize(width, height);
|
|
434
|
+
this.fullscreenMaterial.uniforms.invTexSize.value.set(1 / width, 1 / height);
|
|
435
|
+
(_this_framebufferTexture = this.framebufferTexture) == null ? void 0 : _this_framebufferTexture.dispose();
|
|
436
|
+
const inputTexture = this.fullscreenMaterial.uniforms.inputTexture.value;
|
|
437
|
+
this.framebufferTexture = new FramebufferTexture(width, height, inputTexture.format);
|
|
438
|
+
this.framebufferTexture.type = inputTexture.type;
|
|
439
|
+
this.framebufferTexture.minFilter = LinearFilter;
|
|
440
|
+
this.framebufferTexture.magFilter = LinearFilter;
|
|
441
|
+
this.framebufferTexture.needsUpdate = true;
|
|
442
|
+
for(let i = 0; i < this.textureCount; i++){
|
|
443
|
+
var _this_overrideAccumulatedTextures_i;
|
|
444
|
+
const accumulatedTexture = (_this_overrideAccumulatedTextures_i = this.overrideAccumulatedTextures[i]) != null ? _this_overrideAccumulatedTextures_i : this.framebufferTexture;
|
|
445
|
+
this.fullscreenMaterial.uniforms["accumulatedTexture" + i].value = accumulatedTexture;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
get texture() {
|
|
449
|
+
return this.renderTarget.texture;
|
|
450
|
+
}
|
|
451
|
+
reset() {
|
|
452
|
+
this.fullscreenMaterial.uniforms.keepData.value = 0;
|
|
453
|
+
}
|
|
454
|
+
render(renderer) {
|
|
455
|
+
this.frame = (this.frame + 1) % 4096;
|
|
456
|
+
const delta = Math.min(1 / 10, this.clock.getDelta());
|
|
457
|
+
this.fullscreenMaterial.uniforms.delta.value = delta;
|
|
458
|
+
tmpProjectionMatrix$1.copy(this._camera.projectionMatrix);
|
|
459
|
+
tmpProjectionMatrixInverse$1.copy(this._camera.projectionMatrixInverse);
|
|
460
|
+
if (this._camera.view) this._camera.view.enabled = false;
|
|
461
|
+
this._camera.updateProjectionMatrix();
|
|
462
|
+
this.fullscreenMaterial.uniforms.projectionMatrix.value.copy(this._camera.projectionMatrix);
|
|
463
|
+
this.fullscreenMaterial.uniforms.projectionMatrixInverse.value.copy(this._camera.projectionMatrixInverse);
|
|
464
|
+
this.fullscreenMaterial.uniforms.lastVelocityTexture.value = this.velocityDepthNormalPass.lastVelocityTexture;
|
|
465
|
+
this.fullscreenMaterial.uniforms.fullAccumulate.value = this.options.fullAccumulate && !didCameraMove(this._camera, this.lastCameraTransform.position, this.lastCameraTransform.quaternion);
|
|
466
|
+
this.lastCameraTransform.position.copy(this._camera.position);
|
|
467
|
+
this.lastCameraTransform.quaternion.copy(this._camera.quaternion);
|
|
468
|
+
if (this._camera.view) this._camera.view.enabled = true;
|
|
469
|
+
this._camera.projectionMatrix.copy(tmpProjectionMatrix$1);
|
|
470
|
+
this._camera.projectionMatrixInverse.copy(tmpProjectionMatrixInverse$1);
|
|
471
|
+
this.fullscreenMaterial.uniforms.cameraNear.value = this._camera.near;
|
|
472
|
+
this.fullscreenMaterial.uniforms.cameraFar.value = this._camera.far;
|
|
473
|
+
renderer.setRenderTarget(this.renderTarget);
|
|
474
|
+
renderer.render(this.scene, this.camera);
|
|
475
|
+
this.fullscreenMaterial.uniforms.keepData.value = 1;
|
|
476
|
+
if (this.overrideAccumulatedTextures.length === 0) {
|
|
477
|
+
this.framebufferTexture.needsUpdate = true;
|
|
478
|
+
renderer.copyFramebufferToTexture(tmpVec2, this.framebufferTexture);
|
|
479
|
+
}
|
|
480
|
+
// save last transformations
|
|
481
|
+
this.fullscreenMaterial.uniforms.prevCameraMatrixWorld.value.copy(this._camera.matrixWorld);
|
|
482
|
+
this.fullscreenMaterial.uniforms.prevViewMatrix.value.copy(this._camera.matrixWorldInverse);
|
|
483
|
+
this.fullscreenMaterial.uniforms.prevProjectionMatrix.value.copy(this.fullscreenMaterial.uniforms.projectionMatrix.value);
|
|
484
|
+
this.fullscreenMaterial.uniforms.prevProjectionMatrixInverse.value.copy(this.fullscreenMaterial.uniforms.projectionMatrixInverse.value);
|
|
485
|
+
this.fullscreenMaterial.uniforms.prevCameraPos.value.copy(this._camera.position);
|
|
486
|
+
}
|
|
487
|
+
jitter(jitterScale = 1) {
|
|
488
|
+
this.unjitter();
|
|
489
|
+
jitter(this.renderTarget.width, this.renderTarget.height, this._camera, this.frame, jitterScale);
|
|
490
|
+
}
|
|
491
|
+
unjitter() {
|
|
492
|
+
if (this._camera.clearViewOffset) this._camera.clearViewOffset();
|
|
493
|
+
}
|
|
494
|
+
constructor(scene, camera, velocityDepthNormalPass, texture, textureCount, options = defaultTemporalReprojectPassOptions){
|
|
495
|
+
super("TemporalReprojectPass");
|
|
496
|
+
this.needsSwap = false;
|
|
497
|
+
this.overrideAccumulatedTextures = [];
|
|
498
|
+
this.clock = new Clock();
|
|
499
|
+
this.r2Sequence = [];
|
|
500
|
+
this.frame = 0;
|
|
501
|
+
this.lastCameraTransform = {
|
|
502
|
+
position: new Vector3(),
|
|
503
|
+
quaternion: new Quaternion()
|
|
504
|
+
};
|
|
505
|
+
this._scene = scene;
|
|
506
|
+
this._camera = camera;
|
|
507
|
+
this.textureCount = textureCount;
|
|
508
|
+
options = _extends({}, defaultTemporalReprojectPassOptions, options);
|
|
509
|
+
this.renderTarget = new WebGLRenderTarget(1, 1, {
|
|
510
|
+
count: textureCount,
|
|
511
|
+
minFilter: NearestFilter,
|
|
512
|
+
magFilter: NearestFilter,
|
|
513
|
+
type: texture.type,
|
|
514
|
+
depthBuffer: false
|
|
515
|
+
});
|
|
516
|
+
this.renderTarget.textures.forEach((texture, index)=>texture.name = "TemporalReprojectPass.accumulatedTexture" + index);
|
|
517
|
+
this.fullscreenMaterial = new TemporalReprojectMaterial(textureCount);
|
|
518
|
+
this.fullscreenMaterial.defines.textureCount = textureCount;
|
|
519
|
+
if (options.dilation) this.fullscreenMaterial.defines.dilation = "";
|
|
520
|
+
if (options.neighborhoodClamp) this.fullscreenMaterial.defines.neighborhoodClamp = "";
|
|
521
|
+
if (options.logTransform) this.fullscreenMaterial.defines.logTransform = "";
|
|
522
|
+
if (camera.isPerspectiveCamera) this.fullscreenMaterial.defines.PERSPECTIVE_CAMERA = "";
|
|
523
|
+
this.fullscreenMaterial.defines.neighborhoodClampRadius = parseInt(options.neighborhoodClampRadius);
|
|
524
|
+
this.fullscreenMaterial.defines.depthDistance = options.depthDistance.toPrecision(5);
|
|
525
|
+
this.fullscreenMaterial.defines.worldDistance = options.worldDistance.toPrecision(5);
|
|
526
|
+
this.fullscreenMaterial.uniforms.fullAccumulate.value = options.fullAccumulate;
|
|
527
|
+
this.fullscreenMaterial.uniforms.neighborhoodClampIntensity.value = options.neighborhoodClampIntensity;
|
|
528
|
+
this.fullscreenMaterial.uniforms.maxBlend.value = options.maxBlend;
|
|
529
|
+
this.fullscreenMaterial.uniforms.projectionMatrix.value = camera.projectionMatrix.clone();
|
|
530
|
+
this.fullscreenMaterial.uniforms.projectionMatrixInverse.value = camera.projectionMatrixInverse.clone();
|
|
531
|
+
this.fullscreenMaterial.uniforms.cameraMatrixWorld.value = camera.matrixWorld;
|
|
532
|
+
this.fullscreenMaterial.uniforms.viewMatrix.value = camera.matrixWorldInverse;
|
|
533
|
+
this.fullscreenMaterial.uniforms.cameraPos.value = camera.position;
|
|
534
|
+
this.fullscreenMaterial.uniforms.prevViewMatrix.value = camera.matrixWorldInverse.clone();
|
|
535
|
+
this.fullscreenMaterial.uniforms.prevCameraMatrixWorld.value = camera.matrixWorld.clone();
|
|
536
|
+
this.fullscreenMaterial.uniforms.prevProjectionMatrix.value = camera.projectionMatrix.clone();
|
|
537
|
+
this.fullscreenMaterial.uniforms.prevProjectionMatrixInverse.value = camera.projectionMatrixInverse.clone();
|
|
538
|
+
this.fullscreenMaterial.uniforms.velocityTexture.value = velocityDepthNormalPass.renderTarget.texture;
|
|
539
|
+
this.fullscreenMaterial.uniforms.depthTexture.value = velocityDepthNormalPass.depthTexture;
|
|
540
|
+
var _indexOf;
|
|
541
|
+
this.fullscreenMaterial.defines.inputType = (_indexOf = [
|
|
542
|
+
"diffuseSpecular",
|
|
543
|
+
"diffuse",
|
|
544
|
+
"specular"
|
|
545
|
+
].indexOf(options.inputType)) != null ? _indexOf : 1;
|
|
546
|
+
for (const opt of [
|
|
547
|
+
"reprojectSpecular",
|
|
548
|
+
"neighborhoodClamp"
|
|
549
|
+
]){
|
|
550
|
+
let value = options[opt];
|
|
551
|
+
if (typeof value !== "array") value = Array(textureCount).fill(value);
|
|
552
|
+
this.fullscreenMaterial.defines[opt] = /* glsl */ `bool[](${value.join(", ")})`;
|
|
553
|
+
}
|
|
554
|
+
this.fullscreenMaterial.defines.confidencePower = options.confidencePower.toPrecision(5);
|
|
555
|
+
this.options = options;
|
|
556
|
+
this.velocityDepthNormalPass = velocityDepthNormalPass;
|
|
557
|
+
this.fullscreenMaterial.uniforms.inputTexture.value = texture;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
var traa_compose = "#define GLSLIFY 1\nuniform sampler2D accumulatedTexture;void mainImage(const in vec4 inputColor,const in vec2 uv,out vec4 outputColor){vec4 accumulatedTexel=textureLod(accumulatedTexture,uv,0.);outputColor=vec4(accumulatedTexel.rgb,1.);}"; // eslint-disable-line
|
|
562
|
+
|
|
563
|
+
class TRAAEffect extends Effect {
|
|
564
|
+
setSize(width, height) {
|
|
565
|
+
var _this_temporalReprojectPass;
|
|
566
|
+
(_this_temporalReprojectPass = this.temporalReprojectPass) == null ? void 0 : _this_temporalReprojectPass.setSize(width, height);
|
|
567
|
+
}
|
|
568
|
+
dispose() {
|
|
569
|
+
super.dispose();
|
|
570
|
+
this.temporalReprojectPass.dispose();
|
|
571
|
+
}
|
|
572
|
+
reset() {
|
|
573
|
+
this.temporalReprojectPass.reset();
|
|
574
|
+
}
|
|
575
|
+
update(renderer, inputBuffer) {
|
|
576
|
+
if (!this.temporalReprojectPass) {
|
|
577
|
+
this.temporalReprojectPass = new TemporalReprojectPass(this._scene, this._camera, this.velocityDepthNormalPass, inputBuffer.texture, 1, this.options);
|
|
578
|
+
this.temporalReprojectPass.setSize(inputBuffer.width, inputBuffer.height);
|
|
579
|
+
this.uniforms.get("accumulatedTexture").value = this.temporalReprojectPass.texture;
|
|
580
|
+
}
|
|
581
|
+
this.temporalReprojectPass.setInputTexture(inputBuffer.texture);
|
|
582
|
+
this.temporalReprojectPass.unjitter();
|
|
583
|
+
this.unjitteredProjectionMatrix = this._camera.projectionMatrix.clone();
|
|
584
|
+
this._camera.projectionMatrix.copy(this.unjitteredProjectionMatrix);
|
|
585
|
+
this.temporalReprojectPass.jitter();
|
|
586
|
+
this.temporalReprojectPass.render(renderer);
|
|
587
|
+
}
|
|
588
|
+
constructor(scene, camera, velocityDepthNormalPass, options = defaultTemporalReprojectPassOptions){
|
|
589
|
+
super("TRAAEffect", traa_compose, {
|
|
590
|
+
type: "FinalTRAAEffectMaterial",
|
|
591
|
+
uniforms: new Map([
|
|
592
|
+
[
|
|
593
|
+
"accumulatedTexture",
|
|
594
|
+
new Uniform(null)
|
|
595
|
+
]
|
|
596
|
+
])
|
|
597
|
+
});
|
|
598
|
+
this._scene = scene;
|
|
599
|
+
this._camera = camera;
|
|
600
|
+
this.velocityDepthNormalPass = velocityDepthNormalPass;
|
|
601
|
+
options = _extends({}, options, {
|
|
602
|
+
maxBlend: 0.9,
|
|
603
|
+
neighborhoodClamp: true,
|
|
604
|
+
neighborhoodClampIntensity: 1,
|
|
605
|
+
neighborhoodClampRadius: 1,
|
|
606
|
+
logTransform: true,
|
|
607
|
+
confidencePower: 4
|
|
608
|
+
});
|
|
609
|
+
this.options = _extends({}, defaultTemporalReprojectPassOptions, options);
|
|
610
|
+
this.setSize(options.width, options.height);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// this shader is from: https://github.com/gkjohnson/threejs-sandbox
|
|
615
|
+
// Modified ShaderChunk.skinning_pars_vertex to handle
|
|
616
|
+
// a second set of bone information from the previous frame
|
|
617
|
+
const prev_skinning_pars_vertex = /* glsl */ `
|
|
618
|
+
#ifdef USE_SKINNING
|
|
619
|
+
#ifdef BONE_TEXTURE
|
|
620
|
+
uniform sampler2D prevBoneTexture;
|
|
621
|
+
mat4 getPrevBoneMatrix( const in float i ) {
|
|
622
|
+
float j = i * 4.0;
|
|
623
|
+
float x = mod( j, float( boneTextureSize ) );
|
|
624
|
+
float y = floor( j / float( boneTextureSize ) );
|
|
625
|
+
float dx = 1.0 / float( boneTextureSize );
|
|
626
|
+
float dy = 1.0 / float( boneTextureSize );
|
|
627
|
+
y = dy * ( y + 0.5 );
|
|
628
|
+
vec4 v1 = textureLod( prevBoneTexture, vec2( dx * ( x + 0.5 ), y ), 0. );
|
|
629
|
+
vec4 v2 = textureLod( prevBoneTexture, vec2( dx * ( x + 1.5 ), y ), 0. );
|
|
630
|
+
vec4 v3 = textureLod( prevBoneTexture, vec2( dx * ( x + 2.5 ), y ), 0. );
|
|
631
|
+
vec4 v4 = textureLod( prevBoneTexture, vec2( dx * ( x + 3.5 ), y ), 0. );
|
|
632
|
+
mat4 bone = mat4( v1, v2, v3, v4 );
|
|
633
|
+
return bone;
|
|
634
|
+
}
|
|
635
|
+
#else
|
|
636
|
+
uniform mat4 prevBoneMatrices[ MAX_BONES ];
|
|
637
|
+
mat4 getPrevBoneMatrix( const in float i ) {
|
|
638
|
+
mat4 bone = prevBoneMatrices[ int(i) ];
|
|
639
|
+
return bone;
|
|
640
|
+
}
|
|
641
|
+
#endif
|
|
642
|
+
#endif
|
|
643
|
+
`;
|
|
644
|
+
const velocity_vertex_pars = /* glsl */ `
|
|
645
|
+
#define MAX_BONES 64
|
|
646
|
+
|
|
647
|
+
${ShaderChunk.skinning_pars_vertex}
|
|
648
|
+
${prev_skinning_pars_vertex}
|
|
649
|
+
|
|
650
|
+
uniform mat4 velocityMatrix;
|
|
651
|
+
uniform mat4 prevVelocityMatrix;
|
|
652
|
+
varying vec4 prevPosition;
|
|
653
|
+
varying vec4 newPosition;
|
|
654
|
+
|
|
655
|
+
varying vec2 vHighPrecisionZW;
|
|
656
|
+
`;
|
|
657
|
+
// Returns the body of the vertex shader for the velocity buffer
|
|
658
|
+
const velocity_vertex_main = /* glsl */ `
|
|
659
|
+
// Get the current vertex position
|
|
660
|
+
transformed = vec3( position );
|
|
661
|
+
${ShaderChunk.skinning_vertex}
|
|
662
|
+
newPosition = velocityMatrix * vec4( transformed, 1.0 );
|
|
663
|
+
|
|
664
|
+
// Get the previous vertex position
|
|
665
|
+
transformed = vec3( position );
|
|
666
|
+
${ShaderChunk.skinbase_vertex.replace(/mat4 /g, "").replace(/getBoneMatrix/g, "getPrevBoneMatrix")}
|
|
667
|
+
${ShaderChunk.skinning_vertex.replace(/vec4 /g, "")}
|
|
668
|
+
prevPosition = prevVelocityMatrix * vec4( transformed, 1.0 );
|
|
669
|
+
|
|
670
|
+
gl_Position = newPosition;
|
|
671
|
+
|
|
672
|
+
vHighPrecisionZW = gl_Position.zw;
|
|
673
|
+
`;
|
|
674
|
+
const velocity_fragment_pars = /* glsl */ `
|
|
675
|
+
varying vec4 prevPosition;
|
|
676
|
+
varying vec4 newPosition;
|
|
677
|
+
|
|
678
|
+
varying vec2 vHighPrecisionZW;
|
|
679
|
+
`;
|
|
680
|
+
const velocity_fragment_main = /* glsl */ `
|
|
681
|
+
vec2 pos0 = (prevPosition.xy / prevPosition.w) * 0.5 + 0.5;
|
|
682
|
+
vec2 pos1 = (newPosition.xy / newPosition.w) * 0.5 + 0.5;
|
|
683
|
+
|
|
684
|
+
vec2 vel = pos1 - pos0;
|
|
685
|
+
|
|
686
|
+
float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;
|
|
687
|
+
|
|
688
|
+
gl_FragColor = vec4(vel.x, vel.y, 0., 0.);
|
|
689
|
+
`;
|
|
690
|
+
const velocity_uniforms = {
|
|
691
|
+
prevVelocityMatrix: {
|
|
692
|
+
value: new Matrix4()
|
|
693
|
+
},
|
|
694
|
+
velocityMatrix: {
|
|
695
|
+
value: new Matrix4()
|
|
696
|
+
},
|
|
697
|
+
prevBoneTexture: {
|
|
698
|
+
value: null
|
|
699
|
+
},
|
|
700
|
+
boneTexture: {
|
|
701
|
+
value: null
|
|
702
|
+
},
|
|
703
|
+
normalMap: {
|
|
704
|
+
value: null
|
|
705
|
+
},
|
|
706
|
+
normalScale: {
|
|
707
|
+
value: new Vector2(1, 1)
|
|
708
|
+
},
|
|
709
|
+
uvTransform: {
|
|
710
|
+
value: new Matrix3()
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
class VelocityDepthNormalMaterial extends ShaderMaterial {
|
|
714
|
+
constructor(camera){
|
|
715
|
+
super({
|
|
716
|
+
uniforms: _extends({}, UniformsUtils.clone(velocity_uniforms), {
|
|
717
|
+
cameraMatrixWorld: {
|
|
718
|
+
value: camera.matrixWorld
|
|
719
|
+
}
|
|
720
|
+
}),
|
|
721
|
+
vertexShader: /* glsl */ `
|
|
722
|
+
#include <common>
|
|
723
|
+
#include <uv_pars_vertex>
|
|
724
|
+
#include <displacementmap_pars_vertex>
|
|
725
|
+
#include <normal_pars_vertex>
|
|
726
|
+
#include <morphtarget_pars_vertex>
|
|
727
|
+
#include <logdepthbuf_pars_vertex>
|
|
728
|
+
#include <clipping_planes_pars_vertex>
|
|
729
|
+
|
|
730
|
+
varying vec2 vUv;
|
|
731
|
+
|
|
732
|
+
varying vec3 vViewPosition;
|
|
733
|
+
|
|
734
|
+
${velocity_vertex_pars}
|
|
735
|
+
|
|
736
|
+
void main() {
|
|
737
|
+
vec3 transformed;
|
|
738
|
+
|
|
739
|
+
#include <uv_vertex>
|
|
740
|
+
|
|
741
|
+
#include <skinbase_vertex>
|
|
742
|
+
#include <beginnormal_vertex>
|
|
743
|
+
#include <skinnormal_vertex>
|
|
744
|
+
#include <defaultnormal_vertex>
|
|
745
|
+
|
|
746
|
+
#include <morphnormal_vertex>
|
|
747
|
+
#include <normal_vertex>
|
|
748
|
+
#include <morphtarget_vertex>
|
|
749
|
+
#include <displacementmap_vertex>
|
|
750
|
+
#include <project_vertex>
|
|
751
|
+
#include <logdepthbuf_vertex>
|
|
752
|
+
#include <clipping_planes_vertex>
|
|
753
|
+
|
|
754
|
+
${velocity_vertex_main}
|
|
755
|
+
|
|
756
|
+
vViewPosition = - mvPosition.xyz;
|
|
757
|
+
|
|
758
|
+
vUv = uv;
|
|
759
|
+
|
|
760
|
+
}`,
|
|
761
|
+
fragmentShader: /* glsl */ `
|
|
762
|
+
precision highp float;
|
|
763
|
+
uniform mat4 cameraMatrixWorld;
|
|
764
|
+
|
|
765
|
+
varying vec3 vViewPosition;
|
|
766
|
+
|
|
767
|
+
${velocity_fragment_pars}
|
|
768
|
+
#include <packing>
|
|
769
|
+
|
|
770
|
+
#include <uv_pars_fragment>
|
|
771
|
+
#include <normal_pars_fragment>
|
|
772
|
+
#include <normalmap_pars_fragment>
|
|
773
|
+
|
|
774
|
+
varying vec2 vUv;
|
|
775
|
+
|
|
776
|
+
// source: https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/
|
|
777
|
+
vec2 OctWrap( vec2 v ) {
|
|
778
|
+
vec2 w = 1.0 - abs( v.yx );
|
|
779
|
+
if (v.x < 0.0) w.x = -w.x;
|
|
780
|
+
if (v.y < 0.0) w.y = -w.y;
|
|
781
|
+
return w;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
vec2 encodeOctWrap(vec3 n) {
|
|
785
|
+
n /= (abs(n.x) + abs(n.y) + abs(n.z));
|
|
786
|
+
n.xy = n.z > 0.0 ? n.xy : OctWrap(n.xy);
|
|
787
|
+
n.xy = n.xy * 0.5 + 0.5;
|
|
788
|
+
return n.xy;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
float packNormal(vec3 normal) {
|
|
792
|
+
return uintBitsToFloat(packHalf2x16(encodeOctWrap(normal)));
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
void main() {
|
|
796
|
+
#define vNormalMapUv vUv
|
|
797
|
+
|
|
798
|
+
#include <normal_fragment_begin>
|
|
799
|
+
#include <normal_fragment_maps>
|
|
800
|
+
|
|
801
|
+
${velocity_fragment_main}
|
|
802
|
+
vec3 worldNormal = normalize((cameraMatrixWorld * vec4(normal, 0.)).xyz);
|
|
803
|
+
gl_FragColor.b = packNormal(worldNormal);
|
|
804
|
+
gl_FragColor.a = fragCoordZ;
|
|
805
|
+
}`
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const materialProps = [
|
|
811
|
+
"vertexTangent",
|
|
812
|
+
"vertexColors",
|
|
813
|
+
"vertexAlphas",
|
|
814
|
+
"vertexUvs",
|
|
815
|
+
"uvsVertexOnly",
|
|
816
|
+
"supportsVertexTextures",
|
|
817
|
+
"instancing",
|
|
818
|
+
"instancingColor",
|
|
819
|
+
"side",
|
|
820
|
+
"flatShading",
|
|
821
|
+
"skinning",
|
|
822
|
+
"doubleSided",
|
|
823
|
+
"flipSided"
|
|
824
|
+
];
|
|
825
|
+
const copyNecessaryProps = (originalMaterial, newMaterial)=>{
|
|
826
|
+
for (const props of materialProps)newMaterial[props] = originalMaterial[props];
|
|
827
|
+
};
|
|
828
|
+
const keepMaterialMapUpdated = (mrtMaterial, originalMaterial, prop, define, useKey)=>{
|
|
829
|
+
{
|
|
830
|
+
if (originalMaterial[prop] !== mrtMaterial[prop]) {
|
|
831
|
+
mrtMaterial[prop] = originalMaterial[prop];
|
|
832
|
+
mrtMaterial.uniforms[prop].value = originalMaterial[prop];
|
|
833
|
+
if (originalMaterial[prop]) {
|
|
834
|
+
mrtMaterial.defines[define] = "";
|
|
835
|
+
} else {
|
|
836
|
+
delete mrtMaterial.defines[define];
|
|
837
|
+
}
|
|
838
|
+
mrtMaterial.needsUpdate = true;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
const backgroundColor = new Color(0);
|
|
844
|
+
const zeroVec2 = new Vector2();
|
|
845
|
+
const tmpProjectionMatrix = new Matrix4();
|
|
846
|
+
const tmpProjectionMatrixInverse = new Matrix4();
|
|
847
|
+
const saveBoneTexture = (object, floatType)=>{
|
|
848
|
+
let boneTexture = object.material.uniforms.prevBoneTexture.value;
|
|
849
|
+
if (boneTexture && boneTexture.image.width === object.skeleton.boneTexture.width) {
|
|
850
|
+
boneTexture = object.material.uniforms.prevBoneTexture.value;
|
|
851
|
+
boneTexture.image.data.set(object.skeleton.boneTexture.image.data);
|
|
852
|
+
} else {
|
|
853
|
+
boneTexture == null ? void 0 : boneTexture.dispose();
|
|
854
|
+
const boneMatrices = object.skeleton.boneTexture.image.data.slice();
|
|
855
|
+
const size = object.skeleton.boneTexture.image.width;
|
|
856
|
+
boneTexture = new DataTexture(boneMatrices, size, size, RGBAFormat, floatType);
|
|
857
|
+
object.material.uniforms.prevBoneTexture.value = boneTexture;
|
|
858
|
+
boneTexture.needsUpdate = true;
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
const updateVelocityDepthNormalMaterialBeforeRender = (c, camera)=>{
|
|
862
|
+
var _c_skeleton;
|
|
863
|
+
if ((_c_skeleton = c.skeleton) == null ? void 0 : _c_skeleton.boneTexture) {
|
|
864
|
+
c.material.uniforms.boneTexture.value = c.skeleton.boneTexture;
|
|
865
|
+
if (!("USE_SKINNING" in c.material.defines)) {
|
|
866
|
+
c.material.defines.USE_SKINNING = "";
|
|
867
|
+
c.material.defines.BONE_TEXTURE = "";
|
|
868
|
+
c.material.needsUpdate = true;
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
c.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, c.matrixWorld);
|
|
872
|
+
c.material.uniforms.velocityMatrix.value.multiplyMatrices(camera.projectionMatrix, c.modelViewMatrix);
|
|
873
|
+
};
|
|
874
|
+
const updateVelocityDepthNormalMaterialAfterRender = (c, camera, floatType)=>{
|
|
875
|
+
var _c_skeleton;
|
|
876
|
+
c.material.uniforms.prevVelocityMatrix.value.multiplyMatrices(camera.projectionMatrix, c.modelViewMatrix);
|
|
877
|
+
if ((_c_skeleton = c.skeleton) == null ? void 0 : _c_skeleton.boneTexture) saveBoneTexture(c, floatType);
|
|
878
|
+
};
|
|
879
|
+
class VelocityDepthNormalPass extends Pass {
|
|
880
|
+
get texture() {
|
|
881
|
+
return this.renderTarget.texture;
|
|
882
|
+
}
|
|
883
|
+
setVelocityDepthNormalMaterialInScene() {
|
|
884
|
+
this.visibleMeshes = getVisibleChildren(this._scene);
|
|
885
|
+
for (const c of this.visibleMeshes){
|
|
886
|
+
const originalMaterial = c.material;
|
|
887
|
+
let [cachedOriginalMaterial, velocityDepthNormalMaterial] = this.cachedMaterials.get(c) || [];
|
|
888
|
+
if (originalMaterial !== cachedOriginalMaterial) {
|
|
889
|
+
var _c_skeleton;
|
|
890
|
+
velocityDepthNormalMaterial = new VelocityDepthNormalMaterial(this._camera);
|
|
891
|
+
copyNecessaryProps(originalMaterial, velocityDepthNormalMaterial);
|
|
892
|
+
c.material = velocityDepthNormalMaterial;
|
|
893
|
+
if ((_c_skeleton = c.skeleton) == null ? void 0 : _c_skeleton.boneTexture) saveBoneTexture(c, this._floatType);
|
|
894
|
+
this.cachedMaterials.set(c, [
|
|
895
|
+
originalMaterial,
|
|
896
|
+
velocityDepthNormalMaterial
|
|
897
|
+
]);
|
|
898
|
+
}
|
|
899
|
+
c.material = velocityDepthNormalMaterial;
|
|
900
|
+
c.visible = isChildMaterialRenderable(c, originalMaterial);
|
|
901
|
+
keepMaterialMapUpdated(velocityDepthNormalMaterial, originalMaterial, "normalMap", "USE_NORMALMAP_TANGENTSPACE");
|
|
902
|
+
velocityDepthNormalMaterial.uniforms.normalMap.value = originalMaterial.normalMap;
|
|
903
|
+
const map = originalMaterial.map || originalMaterial.normalMap || originalMaterial.roughnessMap || originalMaterial.metalnessMap;
|
|
904
|
+
if (map) velocityDepthNormalMaterial.uniforms.uvTransform.value = map.matrix;
|
|
905
|
+
updateVelocityDepthNormalMaterialBeforeRender(c, this._camera);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
unsetVelocityDepthNormalMaterialInScene() {
|
|
909
|
+
for (const c of this.visibleMeshes){
|
|
910
|
+
c.visible = true;
|
|
911
|
+
updateVelocityDepthNormalMaterialAfterRender(c, this._camera, this._floatType);
|
|
912
|
+
c.material = this.cachedMaterials.get(c)[0];
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
setSize(width, height) {
|
|
916
|
+
var _this_lastVelocityTexture;
|
|
917
|
+
this.renderTarget.setSize(width, height);
|
|
918
|
+
(_this_lastVelocityTexture = this.lastVelocityTexture) == null ? void 0 : _this_lastVelocityTexture.dispose();
|
|
919
|
+
this.lastVelocityTexture = new FramebufferTexture(width, height, RGBAFormat);
|
|
920
|
+
this.lastVelocityTexture.type = this._floatType;
|
|
921
|
+
this.lastVelocityTexture.minFilter = NearestFilter;
|
|
922
|
+
this.lastVelocityTexture.magFilter = NearestFilter;
|
|
923
|
+
}
|
|
924
|
+
dispose() {
|
|
925
|
+
super.dispose();
|
|
926
|
+
this.renderTarget.dispose();
|
|
927
|
+
}
|
|
928
|
+
render(renderer) {
|
|
929
|
+
tmpProjectionMatrix.copy(this._camera.projectionMatrix);
|
|
930
|
+
tmpProjectionMatrixInverse.copy(this._camera.projectionMatrixInverse);
|
|
931
|
+
if (this._camera.view) this._camera.view.enabled = false;
|
|
932
|
+
this._camera.updateProjectionMatrix();
|
|
933
|
+
// in case a RenderPass is not being used, so we need to update the camera's world matrix manually
|
|
934
|
+
this._camera.updateMatrixWorld();
|
|
935
|
+
this.setVelocityDepthNormalMaterialInScene();
|
|
936
|
+
const { background } = this._scene;
|
|
937
|
+
this._scene.background = backgroundColor;
|
|
938
|
+
renderer.setRenderTarget(this.renderTarget);
|
|
939
|
+
renderer.copyFramebufferToTexture(zeroVec2, this.lastVelocityTexture);
|
|
940
|
+
renderer.render(this._scene, this._camera);
|
|
941
|
+
this._scene.background = background;
|
|
942
|
+
this.unsetVelocityDepthNormalMaterialInScene();
|
|
943
|
+
if (this._camera.view) this._camera.view.enabled = true;
|
|
944
|
+
this._camera.projectionMatrix.copy(tmpProjectionMatrix);
|
|
945
|
+
this._camera.projectionMatrixInverse.copy(tmpProjectionMatrixInverse);
|
|
946
|
+
}
|
|
947
|
+
constructor(scene, camera, floatType = HalfFloatType){
|
|
948
|
+
super("VelocityDepthNormalPass");
|
|
949
|
+
this.cachedMaterials = new WeakMap();
|
|
950
|
+
this.visibleMeshes = [];
|
|
951
|
+
this.needsSwap = false;
|
|
952
|
+
this._scene = scene;
|
|
953
|
+
this._camera = camera;
|
|
954
|
+
this._floatType = floatType;
|
|
955
|
+
this.renderTarget = new WebGLRenderTarget(1, 1, {
|
|
956
|
+
type: floatType,
|
|
957
|
+
minFilter: NearestFilter,
|
|
958
|
+
magFilter: NearestFilter
|
|
959
|
+
});
|
|
960
|
+
this.renderTarget.texture.name = "VelocityDepthNormalPass.Texture";
|
|
961
|
+
this.renderTarget.depthTexture = new DepthTexture(1, 1);
|
|
962
|
+
this.renderTarget.depthTexture.type = floatType;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
function getVelocityDepthNormalPass(viewer, autoAdd = true) {
|
|
967
|
+
const composer = EffectComposerPlugin.Instance(viewer);
|
|
968
|
+
let vdnPass = composer.getPass(VelocityDepthNormalPass);
|
|
969
|
+
if (vdnPass === undefined && autoAdd) {
|
|
970
|
+
vdnPass = composer.addPass(new VelocityDepthNormalPass(viewer.scene, viewer.camera));
|
|
971
|
+
}
|
|
972
|
+
return vdnPass;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
class TRAAPlugin extends PassPlugin {
|
|
976
|
+
constructor(props = {}){
|
|
977
|
+
super();
|
|
978
|
+
this.type = "TRAAPlugin";
|
|
979
|
+
this.install = ()=>{
|
|
980
|
+
const { scene, camera } = this.viewer;
|
|
981
|
+
this._effect = new TRAAEffect(scene, camera, getVelocityDepthNormalPass(this.viewer), props);
|
|
982
|
+
this.pass = this.composer.addPass(new EffectPass(camera, this._effect));
|
|
983
|
+
};
|
|
984
|
+
this.uninstall = ()=>{
|
|
985
|
+
this.composer.removePass(this.pass);
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
PropertyManager._getClassProperties("TRAAPlugin").property("enable");
|
|
281
990
|
|
|
282
|
-
export { BloomPlugin, EffectComposerPlugin, FXAAPlugin, MSAAPlugin, SMAAPlugin, ToneMappingPlugin };
|
|
991
|
+
export { BloomPlugin, EffectComposerPlugin, FXAAPlugin, MSAAPlugin, SMAAPlugin, TRAAPlugin, ToneMappingPlugin };
|
|
283
992
|
//# sourceMappingURL=module.js.map
|