@driftengine/core 4.4.1 → 4.4.2
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/CHANGELOG.json +26 -0
- package/README.md +1 -1
- package/dist/render/backend/webgl2/renderer.d.ts +3 -0
- package/dist/render/backend/webgl2/renderer.js +13 -0
- package/dist/render/backend/webgpu/postPass.d.ts +19 -3
- package/dist/render/backend/webgpu/postPass.js +17 -4
- package/dist/render/backend/webgpu/renderer.d.ts +10 -0
- package/dist/render/backend/webgpu/renderer.js +67 -4
- package/dist/render/flameLight.js +15 -2
- package/dist/render/pointShadowBudget.js +51 -41
- package/dist/render/recon/disocclusion.d.ts +36 -3
- package/dist/render/recon/disocclusion.js +56 -4
- package/dist/render/recon/resolve.js +95 -12
- package/dist/render/sceneTarget.d.ts +2 -0
- package/dist/render/sceneTarget.js +1 -1
- package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +31 -6
- package/dist/render/shaders/generated/temporalResolve.wgsl.js +31 -6
- package/dist/render/shaders/recon/resolve.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/resolve.wgsl.js +112 -8
- package/dist/render/shaders/temporalResolve.js +133 -5
- package/dist/render/temporalAa.d.ts +145 -0
- package/dist/render/temporalAa.js +190 -0
- package/dist/render/temporalPass.d.ts +16 -14
- package/dist/render/temporalPass.js +59 -14
- package/package.json +6 -6
- package/src/render/backend/webgl2/renderer.ts +21 -1
- package/src/render/backend/webgpu/postPass.ts +34 -4
- package/src/render/backend/webgpu/renderer.ts +70 -4
- package/src/render/flameLight.ts +15 -2
- package/src/render/pointShadowBudget.ts +49 -39
- package/src/render/recon/disocclusion.ts +54 -3
- package/src/render/recon/resolve.ts +137 -10
- package/src/render/sceneTarget.ts +8 -1
- package/src/render/shaders/generated/temporalResolve.wgsl.ts +31 -6
- package/src/render/shaders/recon/resolve.wgsl.ts +112 -8
- package/src/render/shaders/temporalResolve.ts +141 -5
- package/src/render/temporalAa.ts +227 -0
- package/src/render/temporalPass.ts +88 -12
|
@@ -15,6 +15,9 @@ import { TEMPORAL_RESOLVE_FRAG } from './shaders/temporalResolve.ts';
|
|
|
15
15
|
* grade all read the scene texture, and reading the unresolved one would grade a stable picture
|
|
16
16
|
* from an unstable source and put the crawl back on screen through the bloom.
|
|
17
17
|
*/
|
|
18
|
+
/** The resolve's three outputs: the picture and the two halves of the flicker record. */
|
|
19
|
+
const DRAW_ALL = [0x8ce0, 0x8ce1, 0x8ce2]; // COLOR_ATTACHMENT0, 1, 2
|
|
20
|
+
|
|
18
21
|
export class TemporalPass {
|
|
19
22
|
private readonly program: WebGLProgram;
|
|
20
23
|
private readonly uniforms: Record<string, WebGLUniformLocation | null>;
|
|
@@ -22,6 +25,21 @@ export class TemporalPass {
|
|
|
22
25
|
|
|
23
26
|
/** The pair, and which of them the next resolve writes into. */
|
|
24
27
|
private textures: (WebGLTexture | null)[] = [null, null];
|
|
28
|
+
/**
|
|
29
|
+
* Each pixel's flicker record, a pair beside the history's and swapped with it: see the
|
|
30
|
+
* anti-flicker in `temporalAa.ts`. In the history's own format, which holds what the record does —
|
|
31
|
+
* a change and a sample are colours' luma, and eight bits hold them wherever eight bits hold the
|
|
32
|
+
* colour.
|
|
33
|
+
*/
|
|
34
|
+
private records: (WebGLTexture | null)[] = [null, null];
|
|
35
|
+
/** The rest of each pixel's record — depth, pull and recent swing — beside the first. */
|
|
36
|
+
private motions: (WebGLTexture | null)[] = [null, null];
|
|
37
|
+
/**
|
|
38
|
+
* Whether the records can be half float, which the depth in them needs. Asked of the context
|
|
39
|
+
* rather than taken from the scene's format, since a record of an eight-bit scene still holds
|
|
40
|
+
* metres. Without it the anti-flicker is off and the resolve is the one before it existed.
|
|
41
|
+
*/
|
|
42
|
+
private readonly recordFloat: boolean;
|
|
25
43
|
private framebuffers: (WebGLFramebuffer | null)[] = [null, null];
|
|
26
44
|
private write = 0;
|
|
27
45
|
|
|
@@ -40,6 +58,7 @@ export class TemporalPass {
|
|
|
40
58
|
*/
|
|
41
59
|
private readonly floatColor: boolean,
|
|
42
60
|
) {
|
|
61
|
+
this.recordFloat = gl.getExtension('EXT_color_buffer_float') !== null;
|
|
43
62
|
this.program = compileProgram(gl, FULLSCREEN_VERT, TEMPORAL_RESOLVE_FRAG, 'temporalResolve');
|
|
44
63
|
this.uniforms = uniformLocations(gl, this.program, 'temporalPass');
|
|
45
64
|
const vao = gl.createVertexArray();
|
|
@@ -55,19 +74,45 @@ export class TemporalPass {
|
|
|
55
74
|
|
|
56
75
|
for (let i = 0; i < 2; i++) {
|
|
57
76
|
if (this.textures[i] === null) this.textures[i] = gl.createTexture();
|
|
58
|
-
|
|
59
|
-
if (this.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
77
|
+
if (this.records[i] === null) this.records[i] = gl.createTexture();
|
|
78
|
+
if (this.motions[i] === null) this.motions[i] = gl.createTexture();
|
|
79
|
+
for (const texture of [this.textures[i], this.records[i], this.motions[i]]) {
|
|
80
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
81
|
+
if (texture === this.textures[i] ? this.floatColor : this.recordFloat) {
|
|
82
|
+
/* The depth record is two numbers a pixel: metres, and how far they swing. */
|
|
83
|
+
const pair = texture === this.motions[i];
|
|
84
|
+
gl.texImage2D(
|
|
85
|
+
gl.TEXTURE_2D,
|
|
86
|
+
0,
|
|
87
|
+
pair ? gl.RG16F : gl.RGBA16F,
|
|
88
|
+
width,
|
|
89
|
+
height,
|
|
90
|
+
0,
|
|
91
|
+
pair ? gl.RG : gl.RGBA,
|
|
92
|
+
gl.HALF_FLOAT,
|
|
93
|
+
null,
|
|
94
|
+
);
|
|
95
|
+
} else {
|
|
96
|
+
gl.texImage2D(
|
|
97
|
+
gl.TEXTURE_2D,
|
|
98
|
+
0,
|
|
99
|
+
gl.RGBA,
|
|
100
|
+
width,
|
|
101
|
+
height,
|
|
102
|
+
0,
|
|
103
|
+
gl.RGBA,
|
|
104
|
+
gl.UNSIGNED_BYTE,
|
|
105
|
+
null,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
/* Linear, because the history is sampled between texels wherever the reprojection lands;
|
|
109
|
+
clamped, because a sample that wrapped would pull the far edge of the screen into the
|
|
110
|
+
corner — and the shader rejects an off-screen reprojection before it can anyway. */
|
|
111
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
112
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
113
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
114
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
63
115
|
}
|
|
64
|
-
/* Linear, because the history is sampled between texels wherever the reprojection lands;
|
|
65
|
-
clamped, because a sample that wrapped would pull the far edge of the screen into the
|
|
66
|
-
corner — and the shader rejects an off-screen reprojection before it can anyway. */
|
|
67
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
68
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
69
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
70
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
71
116
|
|
|
72
117
|
if (this.framebuffers[i] === null) this.framebuffers[i] = gl.createFramebuffer();
|
|
73
118
|
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffers[i]);
|
|
@@ -78,6 +123,22 @@ export class TemporalPass {
|
|
|
78
123
|
this.textures[i],
|
|
79
124
|
0,
|
|
80
125
|
);
|
|
126
|
+
gl.framebufferTexture2D(
|
|
127
|
+
gl.FRAMEBUFFER,
|
|
128
|
+
gl.COLOR_ATTACHMENT1,
|
|
129
|
+
gl.TEXTURE_2D,
|
|
130
|
+
this.records[i],
|
|
131
|
+
0,
|
|
132
|
+
);
|
|
133
|
+
gl.framebufferTexture2D(
|
|
134
|
+
gl.FRAMEBUFFER,
|
|
135
|
+
gl.COLOR_ATTACHMENT2,
|
|
136
|
+
gl.TEXTURE_2D,
|
|
137
|
+
this.motions[i],
|
|
138
|
+
0,
|
|
139
|
+
);
|
|
140
|
+
/* Per framebuffer, so set once here: the resolve writes the picture and the record. */
|
|
141
|
+
gl.drawBuffers(DRAW_ALL);
|
|
81
142
|
}
|
|
82
143
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
83
144
|
}
|
|
@@ -96,6 +157,8 @@ export class TemporalPass {
|
|
|
96
157
|
width: number,
|
|
97
158
|
height: number,
|
|
98
159
|
blend: number,
|
|
160
|
+
periodStart: boolean,
|
|
161
|
+
depthToViewZ: Float32Array,
|
|
99
162
|
): WebGLTexture {
|
|
100
163
|
const { gl } = this;
|
|
101
164
|
this.ensureSize(width, height);
|
|
@@ -120,10 +183,19 @@ export class TemporalPass {
|
|
|
120
183
|
gl.activeTexture(gl.TEXTURE2);
|
|
121
184
|
gl.bindTexture(gl.TEXTURE_2D, depth);
|
|
122
185
|
gl.uniform1i(this.uniforms['uDepth'] ?? null, 2);
|
|
186
|
+
gl.activeTexture(gl.TEXTURE3);
|
|
187
|
+
gl.bindTexture(gl.TEXTURE_2D, this.records[history]);
|
|
188
|
+
gl.uniform1i(this.uniforms['uFlicker'] ?? null, 3);
|
|
189
|
+
gl.activeTexture(gl.TEXTURE4);
|
|
190
|
+
gl.bindTexture(gl.TEXTURE_2D, this.motions[history]);
|
|
191
|
+
gl.uniform1i(this.uniforms['uFlickerMotion'] ?? null, 4);
|
|
192
|
+
gl.uniform4fv(this.uniforms['uDepthToViewZ'] ?? null, depthToViewZ);
|
|
193
|
+
gl.uniform1f(this.uniforms['uAntiFlicker'] ?? null, this.recordFloat ? 1 : 0);
|
|
123
194
|
|
|
124
195
|
gl.uniformMatrix4fv(this.uniforms['uReprojection'] ?? null, false, reprojection);
|
|
125
196
|
gl.uniform2f(this.uniforms['uTexel'] ?? null, 1 / width, 1 / height);
|
|
126
197
|
gl.uniform1f(this.uniforms['uHistoryBlend'] ?? null, blend);
|
|
198
|
+
gl.uniform1f(this.uniforms['uPeriodStart'] ?? null, periodStart ? 1 : 0);
|
|
127
199
|
|
|
128
200
|
gl.bindVertexArray(this.vao);
|
|
129
201
|
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
@@ -141,8 +213,12 @@ export class TemporalPass {
|
|
|
141
213
|
const { gl } = this;
|
|
142
214
|
for (let i = 0; i < 2; i++) {
|
|
143
215
|
if (this.textures[i] !== null) gl.deleteTexture(this.textures[i]);
|
|
216
|
+
if (this.records[i] !== null) gl.deleteTexture(this.records[i]);
|
|
217
|
+
if (this.motions[i] !== null) gl.deleteTexture(this.motions[i]);
|
|
144
218
|
if (this.framebuffers[i] !== null) gl.deleteFramebuffer(this.framebuffers[i]);
|
|
145
219
|
this.textures[i] = null;
|
|
220
|
+
this.records[i] = null;
|
|
221
|
+
this.motions[i] = null;
|
|
146
222
|
this.framebuffers[i] = null;
|
|
147
223
|
}
|
|
148
224
|
gl.deleteProgram(this.program);
|