reze-engine 0.3.6 → 0.3.8
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/README.md +0 -1
- package/dist/engine.d.ts +8 -25
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +235 -588
- package/dist/engine_r.d.ts +132 -0
- package/dist/engine_r.d.ts.map +1 -0
- package/dist/engine_r.js +1489 -0
- package/dist/engine_ts.d.ts +143 -0
- package/dist/engine_ts.d.ts.map +1 -0
- package/dist/engine_ts.js +1575 -0
- package/dist/model.d.ts +59 -11
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +416 -112
- package/package.json +1 -1
- package/src/engine.ts +266 -649
- package/src/model.ts +518 -156
- package/dist/ik.d.ts +0 -32
- package/dist/ik.d.ts.map +0 -1
- package/dist/ik.js +0 -337
- package/dist/pool-scene.d.ts +0 -52
- package/dist/pool-scene.d.ts.map +0 -1
- package/dist/pool-scene.js +0 -1122
- package/dist/pool.d.ts +0 -38
- package/dist/pool.d.ts.map +0 -1
- package/dist/pool.js +0 -422
package/dist/pool.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export interface PoolOptions {
|
|
2
|
-
y?: number;
|
|
3
|
-
size?: number;
|
|
4
|
-
segments?: number;
|
|
5
|
-
}
|
|
6
|
-
export declare class Pool {
|
|
7
|
-
private device;
|
|
8
|
-
private vertexBuffer;
|
|
9
|
-
private indexBuffer;
|
|
10
|
-
private pipeline;
|
|
11
|
-
private bindGroup;
|
|
12
|
-
private bindGroupLayout;
|
|
13
|
-
private uniformBuffer;
|
|
14
|
-
private cameraBindGroupLayout;
|
|
15
|
-
private cameraBindGroup;
|
|
16
|
-
private cameraUniformBuffer;
|
|
17
|
-
private indexCount;
|
|
18
|
-
private y;
|
|
19
|
-
private size;
|
|
20
|
-
private segments;
|
|
21
|
-
private seaColor;
|
|
22
|
-
private seaLight;
|
|
23
|
-
private startTime;
|
|
24
|
-
constructor(device: GPUDevice, cameraBindGroupLayout: GPUBindGroupLayout, cameraUniformBuffer: GPUBuffer, options?: PoolOptions);
|
|
25
|
-
init(): Promise<void>;
|
|
26
|
-
private createGeometry;
|
|
27
|
-
private createShader;
|
|
28
|
-
private createUniforms;
|
|
29
|
-
updateUniforms(): void;
|
|
30
|
-
render(pass: GPURenderPassEncoder, restoreBuffers?: {
|
|
31
|
-
vertexBuffer: GPUBuffer;
|
|
32
|
-
jointsBuffer: GPUBuffer;
|
|
33
|
-
weightsBuffer: GPUBuffer;
|
|
34
|
-
indexBuffer: GPUBuffer;
|
|
35
|
-
}): void;
|
|
36
|
-
dispose(): void;
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=pool.d.ts.map
|
package/dist/pool.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,IAAI;IACf,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,qBAAqB,CAAqB;IAClD,OAAO,CAAC,eAAe,CAAe;IACtC,OAAO,CAAC,mBAAmB,CAAY;IACvC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,CAAC,CAAQ;IACjB,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,SAAS,CAA4B;gBAG3C,MAAM,EAAE,SAAS,EACjB,qBAAqB,EAAE,kBAAkB,EACzC,mBAAmB,EAAE,SAAS,EAC9B,OAAO,CAAC,EAAE,WAAW;IAaV,IAAI;IAMjB,OAAO,CAAC,cAAc;IA4DtB,OAAO,CAAC,YAAY;IAoQpB,OAAO,CAAC,cAAc;IA0Cf,cAAc;IAsBd,MAAM,CACX,IAAI,EAAE,oBAAoB,EAC1B,cAAc,CAAC,EAAE;QACf,YAAY,EAAE,SAAS,CAAA;QACvB,YAAY,EAAE,SAAS,CAAA;QACvB,aAAa,EAAE,SAAS,CAAA;QACxB,WAAW,EAAE,SAAS,CAAA;KACvB;IAqCI,OAAO;CAIf"}
|
package/dist/pool.js
DELETED
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
import { Vec3 } from "./math";
|
|
2
|
-
export class Pool {
|
|
3
|
-
constructor(device, cameraBindGroupLayout, cameraUniformBuffer, options) {
|
|
4
|
-
this.indexCount = 0;
|
|
5
|
-
this.startTime = performance.now();
|
|
6
|
-
this.device = device;
|
|
7
|
-
this.cameraBindGroupLayout = cameraBindGroupLayout;
|
|
8
|
-
this.cameraUniformBuffer = cameraUniformBuffer;
|
|
9
|
-
this.y = options?.y ?? 15;
|
|
10
|
-
this.size = options?.size ?? 100;
|
|
11
|
-
this.segments = options?.segments ?? 50;
|
|
12
|
-
// Hardcoded dark night pool colors (not used in shader, but kept for uniform buffer)
|
|
13
|
-
this.seaColor = new Vec3(0.02, 0.05, 0.12); // Dark night pool base
|
|
14
|
-
this.seaLight = new Vec3(0.1, 0.3, 0.5); // Light cyan for lit areas
|
|
15
|
-
}
|
|
16
|
-
async init() {
|
|
17
|
-
this.createGeometry();
|
|
18
|
-
this.createShader();
|
|
19
|
-
this.createUniforms();
|
|
20
|
-
}
|
|
21
|
-
createGeometry() {
|
|
22
|
-
const segments = this.segments;
|
|
23
|
-
const size = this.size;
|
|
24
|
-
const halfSize = size / 2;
|
|
25
|
-
const step = size / segments;
|
|
26
|
-
// Generate vertices
|
|
27
|
-
const vertices = [];
|
|
28
|
-
for (let i = 0; i <= segments; i++) {
|
|
29
|
-
for (let j = 0; j <= segments; j++) {
|
|
30
|
-
const x = -halfSize + j * step;
|
|
31
|
-
const z = -halfSize + i * step;
|
|
32
|
-
const y = this.y;
|
|
33
|
-
const u = j / segments;
|
|
34
|
-
const v = i / segments;
|
|
35
|
-
// Position (x, y, z) + UV (u, v)
|
|
36
|
-
vertices.push(x, y, z, u, v);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// Generate indices
|
|
40
|
-
const indices = [];
|
|
41
|
-
for (let i = 0; i < segments; i++) {
|
|
42
|
-
for (let j = 0; j < segments; j++) {
|
|
43
|
-
const topLeft = i * (segments + 1) + j;
|
|
44
|
-
const topRight = topLeft + 1;
|
|
45
|
-
const bottomLeft = (i + 1) * (segments + 1) + j;
|
|
46
|
-
const bottomRight = bottomLeft + 1;
|
|
47
|
-
// Two triangles per quad
|
|
48
|
-
indices.push(topLeft, bottomLeft, topRight);
|
|
49
|
-
indices.push(topRight, bottomLeft, bottomRight);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
this.indexCount = indices.length;
|
|
53
|
-
// Create buffers
|
|
54
|
-
this.vertexBuffer = this.device.createBuffer({
|
|
55
|
-
label: "pool vertices",
|
|
56
|
-
size: vertices.length * 4,
|
|
57
|
-
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
58
|
-
});
|
|
59
|
-
this.device.queue.writeBuffer(this.vertexBuffer, 0, new Float32Array(vertices));
|
|
60
|
-
const indexBufferSize = indices.length * 4;
|
|
61
|
-
this.indexBuffer = this.device.createBuffer({
|
|
62
|
-
label: "pool indices",
|
|
63
|
-
size: indexBufferSize,
|
|
64
|
-
usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
|
|
65
|
-
});
|
|
66
|
-
this.device.queue.writeBuffer(this.indexBuffer, 0, new Uint32Array(indices));
|
|
67
|
-
// Verify: segments=50 should give 50*50*6 = 15000 indices = 60000 bytes
|
|
68
|
-
if (this.indexCount !== indices.length) {
|
|
69
|
-
console.warn(`Pool index count mismatch: expected ${indices.length}, got ${this.indexCount}`);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
createShader() {
|
|
73
|
-
const shaderModule = this.device.createShaderModule({
|
|
74
|
-
label: "pool shader",
|
|
75
|
-
code: /* wgsl */ `
|
|
76
|
-
struct CameraUniforms {
|
|
77
|
-
view: mat4x4f,
|
|
78
|
-
projection: mat4x4f,
|
|
79
|
-
viewPos: vec3f,
|
|
80
|
-
_padding: f32,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
struct PoolUniforms {
|
|
84
|
-
time: f32,
|
|
85
|
-
poolY: f32,
|
|
86
|
-
seaColor: vec3f,
|
|
87
|
-
seaLight: vec3f,
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
struct VertexOutput {
|
|
91
|
-
@builtin(position) position: vec4f,
|
|
92
|
-
@location(0) worldPos: vec3f,
|
|
93
|
-
@location(1) uv: vec2f,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
@group(0) @binding(0) var<uniform> camera: CameraUniforms;
|
|
97
|
-
@group(1) @binding(0) var<uniform> pool: PoolUniforms;
|
|
98
|
-
|
|
99
|
-
// Procedural noise function (simplified)
|
|
100
|
-
fn hash(p: vec2f) -> f32 {
|
|
101
|
-
var p3 = fract(vec3f(p.xyx) * vec3f(443.8975, 397.2973, 491.1871));
|
|
102
|
-
p3 += dot(p3, p3.yzx + 19.19);
|
|
103
|
-
return fract((p3.x + p3.y) * p3.z);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
fn noise(p: vec2f) -> f32 {
|
|
107
|
-
let i = floor(p);
|
|
108
|
-
var f = fract(p);
|
|
109
|
-
f = f * f * (3.0 - 2.0 * f);
|
|
110
|
-
|
|
111
|
-
let a = hash(i);
|
|
112
|
-
let b = hash(i + vec2f(1.0, 0.0));
|
|
113
|
-
let c = hash(i + vec2f(0.0, 1.0));
|
|
114
|
-
let d = hash(i + vec2f(1.0, 1.0));
|
|
115
|
-
|
|
116
|
-
return mix(mix(a, b, f.x), mix(c, d, f.x), f.y);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Layered noise for water height (adapted from Shadertoy - matches reference exactly)
|
|
120
|
-
fn waterHeight(uv: vec2f, time: f32) -> f32 {
|
|
121
|
-
var e = 0.0;
|
|
122
|
-
// Match Shadertoy: time*mod(j,.789)*.1 - time*.05
|
|
123
|
-
for (var j = 1.0; j < 6.0; j += 1.0) {
|
|
124
|
-
let timeOffset = time * (j % 0.789) * 0.1 - time * 0.05;
|
|
125
|
-
let scaledUV = uv * (j * 1.789) + j * 159.45 + timeOffset;
|
|
126
|
-
e += noise(scaledUV) / j;
|
|
127
|
-
}
|
|
128
|
-
return e / 6.0;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Calculate water normals from height gradients (matches Shadertoy reference)
|
|
132
|
-
fn waterNormals(uv: vec2f, time: f32) -> vec3f {
|
|
133
|
-
// Match Shadertoy: uv.x *= .25 (scale X differently for more wave detail)
|
|
134
|
-
let scaledUV = vec2f(uv.x * 0.25, uv.y);
|
|
135
|
-
let eps = 0.008; // Match Shadertoy epsilon
|
|
136
|
-
let h = waterHeight(scaledUV, time);
|
|
137
|
-
let hx = waterHeight(scaledUV + vec2f(eps, 0.0), time);
|
|
138
|
-
let hz = waterHeight(scaledUV + vec2f(0.0, eps), time);
|
|
139
|
-
|
|
140
|
-
// Match Shadertoy normal calculation exactly
|
|
141
|
-
let n = vec3f(h - hx, 1.0, h - hz);
|
|
142
|
-
return normalize(n);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
@vertex fn vs(
|
|
146
|
-
@location(0) position: vec3f,
|
|
147
|
-
@location(1) uv: vec2f
|
|
148
|
-
) -> VertexOutput {
|
|
149
|
-
var output: VertexOutput;
|
|
150
|
-
|
|
151
|
-
// Displace Y based on water height - much higher waves
|
|
152
|
-
let time = pool.time;
|
|
153
|
-
// More wave detail - smaller scale for more waves
|
|
154
|
-
// Wave direction: back-left to front-right (both U and V increase)
|
|
155
|
-
let waveUV = uv * 12.0 + vec2f(time * 0.3, time * 0.2); // Front-right direction (both positive)
|
|
156
|
-
let height = waterHeight(waveUV, time) * 2; // Much higher wave amplitude
|
|
157
|
-
let displacedY = position.y + height;
|
|
158
|
-
|
|
159
|
-
let worldPos = vec3f(position.x, displacedY, position.z);
|
|
160
|
-
output.worldPos = worldPos;
|
|
161
|
-
output.uv = uv;
|
|
162
|
-
output.position = camera.projection * camera.view * vec4f(worldPos, 1.0);
|
|
163
|
-
|
|
164
|
-
return output;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
@fragment fn fs(input: VertexOutput) -> @location(0) vec4f {
|
|
168
|
-
let time = pool.time;
|
|
169
|
-
// More wave detail - smaller scale for more waves (matches Shadertoy approach)
|
|
170
|
-
// Wave direction: back-left to front-right (both U and V increase)
|
|
171
|
-
let uv = input.uv * 12.0 + vec2f(time * 0.3, time * 0.2); // Front-right direction (both positive)
|
|
172
|
-
|
|
173
|
-
// Calculate water normals from height gradients (this creates the wave effect)
|
|
174
|
-
let n = waterNormals(uv, time);
|
|
175
|
-
|
|
176
|
-
// View direction
|
|
177
|
-
let viewDir = normalize(camera.viewPos - input.worldPos);
|
|
178
|
-
|
|
179
|
-
// Fresnel effect for reflection (stronger at glancing angles)
|
|
180
|
-
var fresnel = 1.0 - max(dot(n, viewDir), 0.0);
|
|
181
|
-
fresnel = fresnel * fresnel;
|
|
182
|
-
|
|
183
|
-
// Dark night pool - very dark base
|
|
184
|
-
let darkPoolColor = vec3f(0.01, 0.02, 0.05); // Very dark blue-black
|
|
185
|
-
|
|
186
|
-
// Center spotlight effect - reflection-like bright center
|
|
187
|
-
let centerUV = input.uv - vec2f(0.5, 0.5); // Center at (0.5, 0.5)
|
|
188
|
-
let distFromCenter = length(centerUV);
|
|
189
|
-
// Smaller spotlight area with very smooth, subtle gradient
|
|
190
|
-
let spotlightFalloff = 1.0 - smoothstep(0.0, 0.12, distFromCenter); // Smaller radius (0.12)
|
|
191
|
-
|
|
192
|
-
// Reflection-like bright center - brighter, balanced blue
|
|
193
|
-
let spotlightColor = vec3f(0.2, 0.4, 0.6); // Balanced blue
|
|
194
|
-
let spotlightCenter = vec3f(0.5, 0.65, 0.85); // More white center
|
|
195
|
-
|
|
196
|
-
// Very smooth, subtle gradient mix - multiple smoothstep layers for smoother transition
|
|
197
|
-
let falloff1 = smoothstep(0.0, 0.12, distFromCenter); // Outer edge
|
|
198
|
-
let falloff2 = smoothstep(0.0, 0.08, distFromCenter); // Inner edge
|
|
199
|
-
var color = mix(darkPoolColor, spotlightColor, (1.0 - falloff1) * 0.9); // Brighter outer gradient
|
|
200
|
-
color = mix(color, spotlightCenter, (1.0 - falloff2) * (1.0 - falloff2) * 1.0); // Very bright inner reflection
|
|
201
|
-
|
|
202
|
-
// Add reflection-like effect based on view angle and normals
|
|
203
|
-
let reflectionFactor = max(dot(n, vec3f(0.0, 1.0, 0.0)), 0.0); // More reflection when looking down
|
|
204
|
-
let reflectionBrightness = spotlightFalloff * reflectionFactor * 0.5;
|
|
205
|
-
color += spotlightCenter * reflectionBrightness; // Add reflection-like brightness
|
|
206
|
-
|
|
207
|
-
// Wave-based color variation (matches Shadertoy transparency approach)
|
|
208
|
-
// Match Shadertoy: transparency = dot(n, vec3(0.,.2,1.5)) * 12. + 1.5
|
|
209
|
-
var transparency = dot(n, vec3f(0.0, 0.2, 1.5));
|
|
210
|
-
transparency = (transparency * 12.0 + 1.5);
|
|
211
|
-
|
|
212
|
-
// Match Shadertoy color mixing: mix with seaColor and seaLight (brighter, balanced blue)
|
|
213
|
-
let seaColor = vec3f(0.08, 0.18, 0.3); // Balanced blue
|
|
214
|
-
let seaLight = vec3f(0.12, 0.25, 0.45); // Balanced blue
|
|
215
|
-
// Only apply this mixing subtly to avoid green tint
|
|
216
|
-
color = mix(color, seaColor, clamp(transparency, 0.0, 1.0) * 0.3);
|
|
217
|
-
color = mix(color, seaLight, max(0.0, transparency - 1.5) * 0.2);
|
|
218
|
-
|
|
219
|
-
// Enhanced wave-based color variation for more visible waves
|
|
220
|
-
let waveHeight = waterHeight(uv, time);
|
|
221
|
-
let waveContrast = (waveHeight - 0.5) * 0.3; // Amplify wave contrast
|
|
222
|
-
color += vec3f(0.05, 0.08, 0.15) * waveContrast * spotlightFalloff; // Balanced blue wave highlights
|
|
223
|
-
|
|
224
|
-
// Enhanced underwater glow - white/neutral glow with subtle blue tint, much brighter
|
|
225
|
-
let glowIntensity = spotlightFalloff * 0.6 + fresnel * 0.3 + waveHeight * 0.2; // Stronger glow
|
|
226
|
-
let glowColor = vec3f(0.35, 0.35, 0.45); // Brighter glow with subtle blue tint
|
|
227
|
-
color += glowColor * glowIntensity;
|
|
228
|
-
|
|
229
|
-
// Additional subtle white glow around the center, brighter and more white
|
|
230
|
-
let centerGlow = spotlightFalloff * spotlightFalloff * 0.4; // Soft glow falloff
|
|
231
|
-
let whiteGlow = vec3f(0.55, 0.55, 0.6); // Brighter white glow
|
|
232
|
-
color += whiteGlow * centerGlow * 0.7; // Brighter white center glow
|
|
233
|
-
|
|
234
|
-
// Reflection of dark night sky
|
|
235
|
-
let nightSkyColor = vec3f(0.02, 0.04, 0.08); // Very dark night sky
|
|
236
|
-
let reflection = mix(darkPoolColor, nightSkyColor, fresnel * 0.2);
|
|
237
|
-
color = mix(color, reflection, fresnel * 0.3 * (1.0 - spotlightFalloff)); // Less reflection in spotlight
|
|
238
|
-
|
|
239
|
-
// Specular highlights from underwater lights (bokeh-like bright spots)
|
|
240
|
-
let lightDir1 = normalize(vec3f(0.3, -0.4, 0.6));
|
|
241
|
-
let lightDir2 = normalize(vec3f(-0.3, -0.3, 0.7));
|
|
242
|
-
let reflDir1 = reflect(-lightDir1, n);
|
|
243
|
-
let reflDir2 = reflect(-lightDir2, n);
|
|
244
|
-
var specular1 = max(dot(viewDir, reflDir1), 0.0);
|
|
245
|
-
var specular2 = max(dot(viewDir, reflDir2), 0.0);
|
|
246
|
-
specular1 = pow(specular1, 150.0); // Tight, bright highlights
|
|
247
|
-
specular2 = pow(specular2, 180.0);
|
|
248
|
-
// Subtle white/blue highlights (bokeh effect) - darker, less blue
|
|
249
|
-
color += vec3f(0.8, 0.8, 0.9) * specular1 * 1.2 * spotlightFalloff; // Darker white
|
|
250
|
-
color += vec3f(0.4, 0.5, 0.7) * specular2 * 0.9 * spotlightFalloff; // Darker, less blue
|
|
251
|
-
|
|
252
|
-
return vec4f(color, 0.8); // Half transparent water
|
|
253
|
-
}
|
|
254
|
-
`,
|
|
255
|
-
});
|
|
256
|
-
// Create bind group layout for pool uniforms
|
|
257
|
-
this.bindGroupLayout = this.device.createBindGroupLayout({
|
|
258
|
-
label: "pool bind group layout",
|
|
259
|
-
entries: [
|
|
260
|
-
{
|
|
261
|
-
binding: 0,
|
|
262
|
-
visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
|
|
263
|
-
buffer: {
|
|
264
|
-
type: "uniform",
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
],
|
|
268
|
-
});
|
|
269
|
-
// Create render pipeline
|
|
270
|
-
this.pipeline = this.device.createRenderPipeline({
|
|
271
|
-
label: "pool pipeline",
|
|
272
|
-
layout: this.device.createPipelineLayout({
|
|
273
|
-
bindGroupLayouts: [this.cameraBindGroupLayout, this.bindGroupLayout],
|
|
274
|
-
}),
|
|
275
|
-
vertex: {
|
|
276
|
-
module: shaderModule,
|
|
277
|
-
entryPoint: "vs",
|
|
278
|
-
buffers: [
|
|
279
|
-
{
|
|
280
|
-
arrayStride: 5 * 4, // 3 floats (position) + 2 floats (uv)
|
|
281
|
-
attributes: [
|
|
282
|
-
{
|
|
283
|
-
shaderLocation: 0,
|
|
284
|
-
offset: 0,
|
|
285
|
-
format: "float32x3",
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
shaderLocation: 1,
|
|
289
|
-
offset: 3 * 4,
|
|
290
|
-
format: "float32x2",
|
|
291
|
-
},
|
|
292
|
-
],
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
},
|
|
296
|
-
fragment: {
|
|
297
|
-
module: shaderModule,
|
|
298
|
-
entryPoint: "fs",
|
|
299
|
-
targets: [
|
|
300
|
-
{
|
|
301
|
-
format: "bgra8unorm",
|
|
302
|
-
blend: {
|
|
303
|
-
color: {
|
|
304
|
-
srcFactor: "src-alpha",
|
|
305
|
-
dstFactor: "one-minus-src-alpha",
|
|
306
|
-
},
|
|
307
|
-
alpha: {
|
|
308
|
-
srcFactor: "one",
|
|
309
|
-
dstFactor: "one-minus-src-alpha",
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
],
|
|
314
|
-
},
|
|
315
|
-
primitive: {
|
|
316
|
-
topology: "triangle-list",
|
|
317
|
-
cullMode: "none",
|
|
318
|
-
},
|
|
319
|
-
depthStencil: {
|
|
320
|
-
depthWriteEnabled: true,
|
|
321
|
-
depthCompare: "less-equal",
|
|
322
|
-
format: "depth24plus-stencil8",
|
|
323
|
-
},
|
|
324
|
-
multisample: {
|
|
325
|
-
count: 4,
|
|
326
|
-
},
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
createUniforms() {
|
|
330
|
-
// Create uniform buffer
|
|
331
|
-
// WGSL uniform buffers require 16-byte alignment:
|
|
332
|
-
// time: f32 (4) + poolY (4) + padding (8) = 16 bytes
|
|
333
|
-
// seaColor: vec3f (12) + padding (4) = 16 bytes
|
|
334
|
-
// seaLight: vec3f (12) + padding (4) = 16 bytes
|
|
335
|
-
// Total: 48 bytes
|
|
336
|
-
this.uniformBuffer = this.device.createBuffer({
|
|
337
|
-
label: "pool uniforms",
|
|
338
|
-
size: 48,
|
|
339
|
-
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
|
|
340
|
-
});
|
|
341
|
-
// Create bind group
|
|
342
|
-
this.bindGroup = this.device.createBindGroup({
|
|
343
|
-
label: "pool bind group",
|
|
344
|
-
layout: this.bindGroupLayout,
|
|
345
|
-
entries: [
|
|
346
|
-
{
|
|
347
|
-
binding: 0,
|
|
348
|
-
resource: {
|
|
349
|
-
buffer: this.uniformBuffer,
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
],
|
|
353
|
-
});
|
|
354
|
-
// Create camera bind group
|
|
355
|
-
this.cameraBindGroup = this.device.createBindGroup({
|
|
356
|
-
label: "pool camera bind group",
|
|
357
|
-
layout: this.cameraBindGroupLayout,
|
|
358
|
-
entries: [
|
|
359
|
-
{
|
|
360
|
-
binding: 0,
|
|
361
|
-
resource: {
|
|
362
|
-
buffer: this.cameraUniformBuffer,
|
|
363
|
-
},
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
updateUniforms() {
|
|
369
|
-
const time = (performance.now() - this.startTime) / 1000.0;
|
|
370
|
-
// WGSL uniform buffer layout (16-byte aligned):
|
|
371
|
-
// offset 0: time (f32), poolY (f32), padding (8 bytes)
|
|
372
|
-
// offset 16: seaColor (vec3f), padding (4 bytes)
|
|
373
|
-
// offset 32: seaLight (vec3f), padding (4 bytes)
|
|
374
|
-
const data = new Float32Array(12);
|
|
375
|
-
data[0] = time;
|
|
376
|
-
data[1] = this.y;
|
|
377
|
-
// data[2-3] = padding (unused)
|
|
378
|
-
data[4] = this.seaColor.x;
|
|
379
|
-
data[5] = this.seaColor.y;
|
|
380
|
-
data[6] = this.seaColor.z;
|
|
381
|
-
// data[7] = padding (unused)
|
|
382
|
-
data[8] = this.seaLight.x;
|
|
383
|
-
data[9] = this.seaLight.y;
|
|
384
|
-
data[10] = this.seaLight.z;
|
|
385
|
-
// data[11] = padding (unused)
|
|
386
|
-
this.device.queue.writeBuffer(this.uniformBuffer, 0, data);
|
|
387
|
-
}
|
|
388
|
-
render(pass, restoreBuffers) {
|
|
389
|
-
this.updateUniforms();
|
|
390
|
-
// Set pool's pipeline and bind groups FIRST
|
|
391
|
-
pass.setPipeline(this.pipeline);
|
|
392
|
-
pass.setBindGroup(0, this.cameraBindGroup);
|
|
393
|
-
pass.setBindGroup(1, this.bindGroup);
|
|
394
|
-
// IMPORTANT: Set pool's own buffers AFTER setting pipeline
|
|
395
|
-
// Pool only needs vertex buffer 0 (position + UV), but we must keep buffers 1 and 2 set
|
|
396
|
-
// for subsequent model rendering (eyes, hair, etc.)
|
|
397
|
-
pass.setVertexBuffer(0, this.vertexBuffer);
|
|
398
|
-
// Explicitly keep model's buffers 1 and 2 set - pool pipeline doesn't use them but they must stay
|
|
399
|
-
if (restoreBuffers) {
|
|
400
|
-
pass.setVertexBuffer(1, restoreBuffers.jointsBuffer);
|
|
401
|
-
pass.setVertexBuffer(2, restoreBuffers.weightsBuffer);
|
|
402
|
-
}
|
|
403
|
-
// Set pool's index buffer - this MUST be set to override model's index buffer
|
|
404
|
-
pass.setIndexBuffer(this.indexBuffer, "uint32");
|
|
405
|
-
// Draw all pool indices starting from 0
|
|
406
|
-
// Parameters: indexCount, instanceCount, firstIndex, baseVertex, firstInstance
|
|
407
|
-
// We always draw from index 0 with all indices
|
|
408
|
-
pass.drawIndexed(this.indexCount, 1, 0, 0, 0);
|
|
409
|
-
// Restore model's buffers for subsequent rendering (eyes, hair, etc.)
|
|
410
|
-
// This ensures vertex buffer 0 and index buffer are restored to model's buffers
|
|
411
|
-
if (restoreBuffers) {
|
|
412
|
-
pass.setVertexBuffer(0, restoreBuffers.vertexBuffer);
|
|
413
|
-
pass.setVertexBuffer(1, restoreBuffers.jointsBuffer);
|
|
414
|
-
pass.setVertexBuffer(2, restoreBuffers.weightsBuffer);
|
|
415
|
-
pass.setIndexBuffer(restoreBuffers.indexBuffer, "uint32");
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
dispose() {
|
|
419
|
-
// Buffers will be cleaned up automatically when device is lost
|
|
420
|
-
// But we could explicitly destroy them if needed
|
|
421
|
-
}
|
|
422
|
-
}
|