@driftengine/core 4.8.3 → 4.8.5
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 +82 -0
- package/README.md +1 -1
- package/dist/build/shaderComments.js +0 -0
- package/dist/geometry/meshConcat.js +2 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.js +16 -1
- package/dist/math/scalar.js +1 -1
- package/dist/render/anisotropicLobe.d.ts +7 -0
- package/dist/render/anisotropicLobe.js +33 -0
- package/dist/render/backend/api.d.ts +41 -4
- package/dist/render/backend/select.js +8 -0
- package/dist/render/backend/webgl2/clothTextures.d.ts +27 -0
- package/dist/render/backend/webgl2/clothTextures.js +93 -0
- package/dist/render/backend/webgl2/renderer.d.ts +136 -3
- package/dist/render/backend/webgl2/renderer.js +604 -63
- package/dist/render/backend/webgl2/skinScatter.d.ts +50 -0
- package/dist/render/backend/webgl2/skinScatter.js +256 -0
- package/dist/render/backend/webgpu/buffers.d.ts +25 -11
- package/dist/render/backend/webgpu/buffers.js +98 -49
- package/dist/render/backend/webgpu/clothSolvePack.d.ts +27 -0
- package/dist/render/backend/webgpu/clothSolvePack.js +129 -0
- package/dist/render/backend/webgpu/clothTextures.d.ts +68 -0
- package/dist/render/backend/webgpu/clothTextures.js +145 -0
- package/dist/render/backend/webgpu/compressedUpload.d.ts +18 -0
- package/dist/render/backend/webgpu/compressedUpload.js +38 -0
- package/dist/render/backend/webgpu/computeHost.d.ts +21 -0
- package/dist/render/backend/webgpu/computeHost.js +5 -0
- package/dist/render/backend/webgpu/depthPass.d.ts +16 -6
- package/dist/render/backend/webgpu/depthPass.js +39 -9
- package/dist/render/backend/webgpu/drawCommand.js +6 -2
- package/dist/render/backend/webgpu/flatPass.d.ts +38 -4
- package/dist/render/backend/webgpu/flatPass.js +109 -12
- package/dist/render/backend/webgpu/gpuSkinnedCloth.d.ts +74 -0
- package/dist/render/backend/webgpu/gpuSkinnedCloth.js +452 -0
- package/dist/render/backend/webgpu/motionPass.d.ts +20 -0
- package/dist/render/backend/webgpu/motionPass.js +106 -9
- package/dist/render/backend/webgpu/postPass.d.ts +3 -1
- package/dist/render/backend/webgpu/postPass.js +6 -3
- package/dist/render/backend/webgpu/renderer.d.ts +113 -5
- package/dist/render/backend/webgpu/renderer.js +498 -48
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.d.ts +33 -0
- package/dist/render/backend/webgpu/shaders/clothSolve.wgsl.js +469 -0
- package/dist/render/backend/webgpu/skinScatterPass.d.ts +51 -0
- package/dist/render/backend/webgpu/skinScatterPass.js +253 -0
- package/dist/render/backend/webgpu/surfaceTexturePass.d.ts +4 -1
- package/dist/render/backend/webgpu/surfaceTexturePass.js +37 -12
- package/dist/render/clothBindingData.d.ts +41 -0
- package/dist/render/clothBindingData.js +72 -0
- package/dist/render/clothPlacement.d.ts +25 -0
- package/dist/render/clothPlacement.js +85 -0
- package/dist/render/compressedSource.d.ts +66 -0
- package/dist/render/compressedSource.js +138 -0
- package/dist/render/cutoutCaster.d.ts +2 -0
- package/dist/render/cutoutCaster.js +2 -0
- package/dist/render/cutoutDither.d.ts +51 -0
- package/dist/render/cutoutDither.js +90 -0
- package/dist/render/eyeRefraction.d.ts +35 -0
- package/dist/render/eyeRefraction.js +40 -0
- package/dist/render/glCompressed.d.ts +27 -0
- package/dist/render/glCompressed.js +53 -0
- package/dist/render/hairLobes.d.ts +70 -0
- package/dist/render/hairLobes.js +120 -0
- package/dist/render/lightBudget.d.ts +22 -0
- package/dist/render/lightBudget.js +22 -0
- package/dist/render/mesh.d.ts +7 -0
- package/dist/render/mesh.js +24 -0
- package/dist/render/recon/motionVectors.d.ts +4 -2
- package/dist/render/recon/motionVectors.js +6 -3
- package/dist/render/renderQuality.d.ts +20 -0
- package/dist/render/renderQuality.js +5 -0
- package/dist/render/rendererHarness.js +4 -0
- package/dist/render/sceneTarget.d.ts +12 -0
- package/dist/render/sceneTarget.js +14 -0
- package/dist/render/shaders/clothBinding.d.ts +22 -0
- package/dist/render/shaders/clothBinding.js +80 -0
- package/dist/render/shaders/depth.js +42 -6
- package/dist/render/shaders/flat/anisotropic.d.ts +15 -0
- package/dist/render/shaders/flat/anisotropic.js +68 -0
- package/dist/render/shaders/flat/eye.d.ts +1 -0
- package/dist/render/shaders/flat/eye.js +81 -0
- package/dist/render/shaders/flat/hair.d.ts +1 -0
- package/dist/render/shaders/flat/hair.js +101 -0
- package/dist/render/shaders/flat/index.js +36 -2
- package/dist/render/shaders/flat/main.d.ts +1 -1
- package/dist/render/shaders/flat/main.js +113 -17
- package/dist/render/shaders/flat/models.d.ts +14 -0
- package/dist/render/shaders/flat/models.js +273 -0
- package/dist/render/shaders/flat/preamble.js +26 -24
- package/dist/render/shaders/flat/skin.d.ts +1 -0
- package/dist/render/shaders/flat/skin.js +114 -0
- package/dist/render/shaders/generated/depth.wgsl.d.ts +38 -16
- package/dist/render/shaders/generated/depth.wgsl.js +38 -16
- package/dist/render/shaders/generated/flat.wgsl.d.ts +1790 -1704
- package/dist/render/shaders/generated/flat.wgsl.js +1828 -1742
- package/dist/render/shaders/generated/skinBlur.wgsl.d.ts +48 -0
- package/dist/render/shaders/generated/skinBlur.wgsl.js +54 -0
- package/dist/render/shaders/recon/motion.wgsl.d.ts +1 -1
- package/dist/render/shaders/recon/motion.wgsl.js +102 -0
- package/dist/render/shaders/skinBlur.d.ts +1 -0
- package/dist/render/shaders/skinBlur.js +103 -0
- package/dist/render/shaders/skinning.d.ts +3 -1
- package/dist/render/shaders/skinning.js +31 -4
- package/dist/render/shadowCasters.d.ts +13 -1
- package/dist/render/skinBlur.d.ts +41 -0
- package/dist/render/skinBlur.js +49 -0
- package/dist/render/skinScatter.d.ts +67 -0
- package/dist/render/skinScatter.js +80 -0
- package/dist/render/skinnedClothRun.d.ts +26 -0
- package/dist/render/skinnedClothRun.js +84 -0
- package/dist/render/surfaceModel.d.ts +129 -0
- package/dist/render/surfaceModel.js +152 -0
- package/dist/render/surfaceTexture.d.ts +44 -4
- package/dist/render/surfaceTexture.js +60 -46
- package/dist/render/vertexDefaults.js +7 -0
- package/package.json +6 -6
- package/src/build/shaderComments.ts +0 -0
- package/src/geometry/meshConcat.ts +2 -0
- package/src/index.ts +40 -1
- package/src/math/scalar.ts +1 -1
- package/src/render/anisotropicLobe.ts +41 -0
- package/src/render/backend/api.ts +52 -3
- package/src/render/backend/select.ts +8 -0
- package/src/render/backend/webgl2/clothTextures.ts +120 -0
- package/src/render/backend/webgl2/renderer.ts +693 -64
- package/src/render/backend/webgl2/skinScatter.ts +309 -0
- package/src/render/backend/webgpu/buffers.ts +137 -63
- package/src/render/backend/webgpu/clothSolvePack.ts +161 -0
- package/src/render/backend/webgpu/clothTextures.ts +194 -0
- package/src/render/backend/webgpu/compressedUpload.ts +65 -0
- package/src/render/backend/webgpu/computeHost.ts +25 -0
- package/src/render/backend/webgpu/depthPass.ts +39 -7
- package/src/render/backend/webgpu/drawCommand.ts +6 -2
- package/src/render/backend/webgpu/flatPass.ts +145 -7
- package/src/render/backend/webgpu/gpuSkinnedCloth.ts +502 -0
- package/src/render/backend/webgpu/motionPass.ts +128 -9
- package/src/render/backend/webgpu/postPass.ts +5 -1
- package/src/render/backend/webgpu/renderer.ts +663 -43
- package/src/render/backend/webgpu/shaders/clothSolve.wgsl.ts +470 -0
- package/src/render/backend/webgpu/skinScatterPass.ts +309 -0
- package/src/render/backend/webgpu/surfaceTexturePass.ts +42 -12
- package/src/render/clothBindingData.ts +89 -0
- package/src/render/clothPlacement.ts +114 -0
- package/src/render/compressedSource.ts +198 -0
- package/src/render/cutoutCaster.ts +5 -0
- package/src/render/cutoutDither.ts +99 -0
- package/src/render/eyeRefraction.ts +72 -0
- package/src/render/glCompressed.ts +86 -0
- package/src/render/hairLobes.ts +188 -0
- package/src/render/lightBudget.ts +25 -0
- package/src/render/mesh.ts +23 -0
- package/src/render/recon/motionVectors.ts +6 -3
- package/src/render/renderQuality.ts +28 -0
- package/src/render/rendererHarness.ts +4 -0
- package/src/render/sceneTarget.ts +21 -0
- package/src/render/shaders/clothBinding.ts +81 -0
- package/src/render/shaders/depth.ts +42 -6
- package/src/render/shaders/flat/anisotropic.ts +68 -0
- package/src/render/shaders/flat/eye.ts +82 -0
- package/src/render/shaders/flat/hair.ts +102 -0
- package/src/render/shaders/flat/index.ts +36 -2
- package/src/render/shaders/flat/main.ts +113 -17
- package/src/render/shaders/flat/models.ts +286 -0
- package/src/render/shaders/flat/preamble.ts +26 -24
- package/src/render/shaders/flat/skin.ts +116 -0
- package/src/render/shaders/generated/depth.wgsl.ts +38 -16
- package/src/render/shaders/generated/flat.wgsl.ts +1828 -1742
- package/src/render/shaders/generated/skinBlur.wgsl.ts +56 -0
- package/src/render/shaders/recon/motion.wgsl.ts +102 -0
- package/src/render/shaders/skinBlur.ts +105 -0
- package/src/render/shaders/skinning.ts +31 -4
- package/src/render/shadowCasters.ts +13 -0
- package/src/render/skinBlur.ts +53 -0
- package/src/render/skinScatter.ts +92 -0
- package/src/render/skinnedClothRun.ts +128 -0
- package/src/render/surfaceModel.ts +274 -0
- package/src/render/surfaceTexture.ts +123 -63
- package/src/render/vertexDefaults.ts +7 -0
- package/dist/math/exact.d.ts +0 -76
- package/dist/math/exact.js +0 -327
- package/src/math/exact.ts +0 -340
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skin's screen-space scattering on WebGL2: the target skin's diffuse half is drawn into, and the
|
|
3
|
+
* two passes that spread it. `skinBlur.ts` is what the blur computes and why; the WebGPU backend's
|
|
4
|
+
* `skinScatterPass.ts` is the same thing in that backend's terms.
|
|
5
|
+
*
|
|
6
|
+
* **Drawn as it goes, not kept**: this backend issues a draw when it is asked for, and the state a
|
|
7
|
+
* skin draw reads — its joint palette, its uniforms — is rewritten by the draw after it. So the
|
|
8
|
+
* renderer draws each skin twice in place, the frame's half and then at once its diffuse half into
|
|
9
|
+
* this target, which shares the frame's depth and tests for equality against it.
|
|
10
|
+
*
|
|
11
|
+
* **The units it reads are its own** — `SKIN_BLUR_TEXTURE_UNIT` and the one after — past every
|
|
12
|
+
* unit a lit program binds, because it runs in the middle of a frame and the draws after it must
|
|
13
|
+
* find their textures where they left them.
|
|
14
|
+
*/
|
|
15
|
+
import { SKIN_BLUR_DEPTH_UNIT, SKIN_BLUR_TEXTURE_UNIT } from '../../lightBudget.ts';
|
|
16
|
+
import { blendKeeping } from '../../sceneCoverage.ts';
|
|
17
|
+
import type { SceneTarget } from '../../sceneTarget.ts';
|
|
18
|
+
import { compileProgram, uniformLocations } from '../../shader.ts';
|
|
19
|
+
import { FULLSCREEN_VERT } from '../../shaders/fullscreen.ts';
|
|
20
|
+
import { SKIN_BLUR_FRAG } from '../../shaders/skinBlur.ts';
|
|
21
|
+
import { SKIN_PROFILES } from '../../skinBlur.ts';
|
|
22
|
+
|
|
23
|
+
const CLEAR = new Float32Array(4);
|
|
24
|
+
|
|
25
|
+
export class GlSkinScatter {
|
|
26
|
+
private readonly gl: WebGL2RenderingContext;
|
|
27
|
+
private readonly program: WebGLProgram;
|
|
28
|
+
private readonly uniforms: Record<string, WebGLUniformLocation | null>;
|
|
29
|
+
private readonly vao: WebGLVertexArrayObject;
|
|
30
|
+
/** Each profile's scatter distance per channel, in metres: four floats a profile. */
|
|
31
|
+
private readonly profiles = new Float32Array(SKIN_PROFILES * 4);
|
|
32
|
+
private readonly step = new Float32Array(2);
|
|
33
|
+
private readonly depthToViewZ = new Float32Array(4);
|
|
34
|
+
private diffuse: WebGLTexture | null = null;
|
|
35
|
+
private across: WebGLTexture | null = null;
|
|
36
|
+
private multisampled: WebGLRenderbuffer | null = null;
|
|
37
|
+
private drawFramebuffer: WebGLFramebuffer | null = null;
|
|
38
|
+
private resolveFramebuffer: WebGLFramebuffer | null = null;
|
|
39
|
+
private acrossFramebuffer: WebGLFramebuffer | null = null;
|
|
40
|
+
private width = 0;
|
|
41
|
+
private height = 0;
|
|
42
|
+
private samples = 1;
|
|
43
|
+
private sharedDepth: WebGLTexture | WebGLRenderbuffer | null = null;
|
|
44
|
+
/** Refused once and for good: a driver that will not render to half floats. */
|
|
45
|
+
private unavailable = false;
|
|
46
|
+
private cleared = false;
|
|
47
|
+
private drawn = false;
|
|
48
|
+
|
|
49
|
+
constructor(gl: WebGL2RenderingContext) {
|
|
50
|
+
this.gl = gl;
|
|
51
|
+
this.program = compileProgram(gl, FULLSCREEN_VERT, SKIN_BLUR_FRAG, 'skinBlur');
|
|
52
|
+
this.uniforms = uniformLocations(gl, this.program, 'skinBlur');
|
|
53
|
+
const vao = gl.createVertexArray();
|
|
54
|
+
if (vao === null) throw new Error('GlSkinScatter: createVertexArray failed');
|
|
55
|
+
this.vao = vao;
|
|
56
|
+
/*
|
|
57
|
+
* Rendering to half floats is the extension's, not WebGL2's — the scene target asks for it
|
|
58
|
+
* only when it keeps range, so this asks for itself. Without it, skin is drawn whole.
|
|
59
|
+
*/
|
|
60
|
+
if (gl.getExtension('EXT_color_buffer_float') === null) this.refuse();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Whether any skin's diffuse was drawn this frame. */
|
|
64
|
+
get pending(): boolean {
|
|
65
|
+
return this.drawn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** What one profile scatters, per channel, in metres: the last material to name it says. */
|
|
69
|
+
setProfile(index: number, r: number, g: number, b: number): void {
|
|
70
|
+
const at = Math.min(Math.max(Math.round(index), 0), SKIN_PROFILES - 1) * 4;
|
|
71
|
+
this.profiles[at] = r;
|
|
72
|
+
this.profiles[at + 1] = g;
|
|
73
|
+
this.profiles[at + 2] = b;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Whether a skin can be drawn in two halves now: the target fits the frame and shares its depth.
|
|
78
|
+
* False where this driver will not render to half floats, and then skin is drawn whole.
|
|
79
|
+
*/
|
|
80
|
+
ready(scene: SceneTarget): boolean {
|
|
81
|
+
if (this.unavailable) return false;
|
|
82
|
+
const depth = scene.sharedDepth();
|
|
83
|
+
const attached = depth.renderbuffer ?? depth.texture;
|
|
84
|
+
if (attached === null) return false;
|
|
85
|
+
if (
|
|
86
|
+
this.drawFramebuffer !== null &&
|
|
87
|
+
this.width === depth.width &&
|
|
88
|
+
this.height === depth.height &&
|
|
89
|
+
this.samples === depth.samples &&
|
|
90
|
+
this.sharedDepth === attached
|
|
91
|
+
) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
const made = this.allocate(
|
|
95
|
+
depth.width,
|
|
96
|
+
depth.height,
|
|
97
|
+
depth.samples,
|
|
98
|
+
depth.texture,
|
|
99
|
+
depth.renderbuffer,
|
|
100
|
+
);
|
|
101
|
+
/* Asked in the middle of a frame: the frame's own framebuffer goes back as it was. */
|
|
102
|
+
scene.bind();
|
|
103
|
+
return made;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Bind the target for one skin's diffuse half, cleared the first time a frame does. */
|
|
107
|
+
begin(): void {
|
|
108
|
+
const { gl } = this;
|
|
109
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.drawFramebuffer);
|
|
110
|
+
gl.viewport(0, 0, this.width, this.height);
|
|
111
|
+
if (!this.cleared) {
|
|
112
|
+
gl.clearBufferfv(gl.COLOR, 0, CLEAR);
|
|
113
|
+
this.cleared = true;
|
|
114
|
+
}
|
|
115
|
+
this.drawn = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Across into the second target, then down and added into the frame, which `scene` binds. `depth`
|
|
120
|
+
* is the frame's depth as a single-sampled texture, or null where none could be had — and then
|
|
121
|
+
* the diffuse goes back unspread rather than not at all, so the skin keeps its light.
|
|
122
|
+
*/
|
|
123
|
+
spread(
|
|
124
|
+
scene: SceneTarget,
|
|
125
|
+
depth: WebGLTexture | null,
|
|
126
|
+
empty: WebGLTexture,
|
|
127
|
+
projection: ArrayLike<number>,
|
|
128
|
+
inverse: ArrayLike<number>,
|
|
129
|
+
): void {
|
|
130
|
+
const { gl } = this;
|
|
131
|
+
if (this.multisampled !== null) {
|
|
132
|
+
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, this.drawFramebuffer);
|
|
133
|
+
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, this.resolveFramebuffer);
|
|
134
|
+
gl.blitFramebuffer(
|
|
135
|
+
0,
|
|
136
|
+
0,
|
|
137
|
+
this.width,
|
|
138
|
+
this.height,
|
|
139
|
+
0,
|
|
140
|
+
0,
|
|
141
|
+
this.width,
|
|
142
|
+
this.height,
|
|
143
|
+
gl.COLOR_BUFFER_BIT,
|
|
144
|
+
gl.NEAREST,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
gl.disable(gl.DEPTH_TEST);
|
|
148
|
+
gl.disable(gl.CULL_FACE);
|
|
149
|
+
gl.disable(gl.BLEND);
|
|
150
|
+
gl.depthMask(false);
|
|
151
|
+
gl.bindVertexArray(this.vao);
|
|
152
|
+
gl.useProgram(this.program);
|
|
153
|
+
const u = this.uniforms;
|
|
154
|
+
gl.uniform1i(u['uSkin'] ?? null, SKIN_BLUR_TEXTURE_UNIT);
|
|
155
|
+
gl.uniform1i(u['uDepth'] ?? null, SKIN_BLUR_DEPTH_UNIT);
|
|
156
|
+
/* The four terms that carry a depth back to view-space metres: the occlusion blur's own. */
|
|
157
|
+
this.depthToViewZ[0] = (inverse[10] as number) ?? 0;
|
|
158
|
+
this.depthToViewZ[1] = (inverse[14] as number) ?? 0;
|
|
159
|
+
this.depthToViewZ[2] = (inverse[11] as number) ?? 0;
|
|
160
|
+
this.depthToViewZ[3] = (inverse[15] as number) ?? 1;
|
|
161
|
+
gl.uniform4fv(u['uDepthToViewZ'] ?? null, this.depthToViewZ);
|
|
162
|
+
/* Pixels a metre spans at a metre; nothing to measure against without a depth, so nothing spreads. */
|
|
163
|
+
gl.uniform1f(
|
|
164
|
+
u['uFocal'] ?? null,
|
|
165
|
+
depth === null ? 0 : ((projection[5] as number) * this.height) / 2,
|
|
166
|
+
);
|
|
167
|
+
gl.uniform4fv(u['uProfiles'] ?? null, this.profiles);
|
|
168
|
+
gl.activeTexture(gl.TEXTURE0 + SKIN_BLUR_DEPTH_UNIT);
|
|
169
|
+
gl.bindTexture(gl.TEXTURE_2D, depth ?? empty);
|
|
170
|
+
|
|
171
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.acrossFramebuffer);
|
|
172
|
+
gl.viewport(0, 0, this.width, this.height);
|
|
173
|
+
gl.activeTexture(gl.TEXTURE0 + SKIN_BLUR_TEXTURE_UNIT);
|
|
174
|
+
gl.bindTexture(gl.TEXTURE_2D, this.diffuse);
|
|
175
|
+
this.step[0] = 1 / this.width;
|
|
176
|
+
this.step[1] = 0;
|
|
177
|
+
gl.uniform2fv(u['uStep'] ?? null, this.step);
|
|
178
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
179
|
+
|
|
180
|
+
scene.bind();
|
|
181
|
+
gl.bindTexture(gl.TEXTURE_2D, this.across);
|
|
182
|
+
this.step[0] = 0;
|
|
183
|
+
this.step[1] = 1 / this.height;
|
|
184
|
+
gl.uniform2fv(u['uStep'] ?? null, this.step);
|
|
185
|
+
/* Added: its colour onto the frame's, the frame's alpha kept. */
|
|
186
|
+
gl.enable(gl.BLEND);
|
|
187
|
+
gl.blendEquation(gl.FUNC_ADD);
|
|
188
|
+
blendKeeping(gl, gl.ONE, gl.ONE);
|
|
189
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
190
|
+
|
|
191
|
+
/* The world pass's own state, as the next draw expects to find it. */
|
|
192
|
+
gl.disable(gl.BLEND);
|
|
193
|
+
gl.enable(gl.DEPTH_TEST);
|
|
194
|
+
gl.enable(gl.CULL_FACE);
|
|
195
|
+
gl.depthMask(true);
|
|
196
|
+
gl.bindVertexArray(null);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Spent at the frame's start: what was drawn into the target was last frame's. */
|
|
200
|
+
reset(): void {
|
|
201
|
+
this.cleared = false;
|
|
202
|
+
this.drawn = false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
dispose(): void {
|
|
206
|
+
const { gl } = this;
|
|
207
|
+
this.release();
|
|
208
|
+
gl.deleteProgram(this.program);
|
|
209
|
+
gl.deleteVertexArray(this.vao);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private allocate(
|
|
213
|
+
width: number,
|
|
214
|
+
height: number,
|
|
215
|
+
samples: number,
|
|
216
|
+
depthTexture: WebGLTexture | null,
|
|
217
|
+
depthRenderbuffer: WebGLRenderbuffer | null,
|
|
218
|
+
): boolean {
|
|
219
|
+
const { gl } = this;
|
|
220
|
+
this.release();
|
|
221
|
+
this.width = width;
|
|
222
|
+
this.height = height;
|
|
223
|
+
this.samples = samples;
|
|
224
|
+
/* Its own unit, so making its textures unbinds nothing a lit program reads. */
|
|
225
|
+
gl.activeTexture(gl.TEXTURE0 + SKIN_BLUR_TEXTURE_UNIT);
|
|
226
|
+
this.sharedDepth = depthRenderbuffer ?? depthTexture;
|
|
227
|
+
this.diffuse = this.halfFloatTexture(width, height);
|
|
228
|
+
this.across = this.halfFloatTexture(width, height);
|
|
229
|
+
|
|
230
|
+
this.drawFramebuffer = gl.createFramebuffer();
|
|
231
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.drawFramebuffer);
|
|
232
|
+
if (samples > 1 && depthRenderbuffer !== null) {
|
|
233
|
+
this.multisampled = gl.createRenderbuffer();
|
|
234
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, this.multisampled);
|
|
235
|
+
gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples, gl.RGBA16F, width, height);
|
|
236
|
+
gl.framebufferRenderbuffer(
|
|
237
|
+
gl.FRAMEBUFFER,
|
|
238
|
+
gl.COLOR_ATTACHMENT0,
|
|
239
|
+
gl.RENDERBUFFER,
|
|
240
|
+
this.multisampled,
|
|
241
|
+
);
|
|
242
|
+
gl.framebufferRenderbuffer(
|
|
243
|
+
gl.FRAMEBUFFER,
|
|
244
|
+
gl.DEPTH_ATTACHMENT,
|
|
245
|
+
gl.RENDERBUFFER,
|
|
246
|
+
depthRenderbuffer,
|
|
247
|
+
);
|
|
248
|
+
} else {
|
|
249
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.diffuse, 0);
|
|
250
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, depthTexture, 0);
|
|
251
|
+
}
|
|
252
|
+
const drawReady = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
|
|
253
|
+
|
|
254
|
+
if (this.multisampled !== null) {
|
|
255
|
+
this.resolveFramebuffer = gl.createFramebuffer();
|
|
256
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.resolveFramebuffer);
|
|
257
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.diffuse, 0);
|
|
258
|
+
}
|
|
259
|
+
this.acrossFramebuffer = gl.createFramebuffer();
|
|
260
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, this.acrossFramebuffer);
|
|
261
|
+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.across, 0);
|
|
262
|
+
const acrossReady = gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE;
|
|
263
|
+
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
|
264
|
+
if (drawReady && acrossReady) return true;
|
|
265
|
+
this.release();
|
|
266
|
+
this.refuse();
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
private refuse(): void {
|
|
271
|
+
if (this.unavailable) return;
|
|
272
|
+
this.unavailable = true;
|
|
273
|
+
console.warn(
|
|
274
|
+
"WebGL2: this driver will not render skin's diffuse to half floats, so skinScattering " +
|
|
275
|
+
"'screen-space' draws skin pre-integrated. The frame is otherwise unaffected.",
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
private halfFloatTexture(width: number, height: number): WebGLTexture | null {
|
|
280
|
+
const { gl } = this;
|
|
281
|
+
const texture = gl.createTexture();
|
|
282
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
283
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA16F, width, height, 0, gl.RGBA, gl.HALF_FLOAT, null);
|
|
284
|
+
/* Linear: the blur takes taps between texels, and reads a part-covered one for the part it is. */
|
|
285
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
286
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
287
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
288
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
289
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
290
|
+
return texture;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private release(): void {
|
|
294
|
+
const { gl } = this;
|
|
295
|
+
if (this.drawFramebuffer !== null) gl.deleteFramebuffer(this.drawFramebuffer);
|
|
296
|
+
if (this.resolveFramebuffer !== null) gl.deleteFramebuffer(this.resolveFramebuffer);
|
|
297
|
+
if (this.acrossFramebuffer !== null) gl.deleteFramebuffer(this.acrossFramebuffer);
|
|
298
|
+
if (this.multisampled !== null) gl.deleteRenderbuffer(this.multisampled);
|
|
299
|
+
if (this.diffuse !== null) gl.deleteTexture(this.diffuse);
|
|
300
|
+
if (this.across !== null) gl.deleteTexture(this.across);
|
|
301
|
+
this.drawFramebuffer = null;
|
|
302
|
+
this.resolveFramebuffer = null;
|
|
303
|
+
this.acrossFramebuffer = null;
|
|
304
|
+
this.multisampled = null;
|
|
305
|
+
this.diffuse = null;
|
|
306
|
+
this.across = null;
|
|
307
|
+
this.sharedDepth = null;
|
|
308
|
+
}
|
|
309
|
+
}
|