reze-engine 0.1.10 → 0.1.12

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 CHANGED
@@ -1,99 +1,104 @@
1
- # Reze Engine
2
-
3
- A lightweight engine built with WebGPU and TypeScript for real-time 3D anime character MMD model rendering.
4
-
5
- ## Usage
6
-
7
- ```typescript
8
- export default function Home() {
9
- const canvasRef = useRef<HTMLCanvasElement>(null)
10
- const engineRef = useRef<Engine | null>(null)
11
- const [engineError, setEngineError] = useState<string | null>(null)
12
- const [loading, setLoading] = useState(true)
13
- const [stats, setStats] = useState<EngineStats>({
14
- fps: 0,
15
- frameTime: 0,
16
- memoryUsed: 0,
17
- drawCalls: 0,
18
- vertices: 0,
19
- triangles: 0,
20
- materials: 0,
21
- textures: 0,
22
- textureMemory: 0,
23
- bufferMemory: 0,
24
- gpuMemory: 0,
25
- })
26
- const [progress, setProgress] = useState(0)
27
-
28
- const initEngine = useCallback(async () => {
29
- if (canvasRef.current) {
30
- // Initialize engine
31
- try {
32
- const engine = new Engine(canvasRef.current)
33
- engineRef.current = engine
34
- await engine.init()
35
- await engine.loadModel("/models/塞尔凯特/塞尔凯特.pmx")
36
- setLoading(false)
37
-
38
- engine.runRenderLoop(() => {
39
- setStats(engine.getStats())
40
- })
41
- } catch (error) {
42
- setEngineError(error instanceof Error ? error.message : "Unknown error")
43
- }
44
- }
45
- }, [])
46
-
47
- useEffect(() => {
48
- void (async () => {
49
- initEngine()
50
- })()
51
-
52
- // Cleanup on unmount
53
- return () => {
54
- if (engineRef.current) {
55
- engineRef.current.dispose()
56
- }
57
- }
58
- }, [initEngine])
59
-
60
- useEffect(() => {
61
- if (loading) {
62
- const interval = setInterval(() => {
63
- setProgress((prev) => {
64
- if (prev >= 100) {
65
- return 0
66
- }
67
- return prev + 1
68
- })
69
- }, 50)
70
-
71
- return () => clearInterval(interval)
72
- }
73
- }, [loading])
74
-
75
- return (
76
- <div
77
- className="fixed inset-0 w-full h-full overflow-hidden touch-none"
78
- style={{
79
- background:
80
- "radial-gradient(ellipse at center, rgba(35, 35, 45, 0.8) 0%, rgba(35, 35, 45, 0.8) 8%, rgba(8, 8, 12, 0.95) 65%, rgba(0, 0, 0, 1) 100%)",
81
- }}
82
- >
83
- <Header stats={stats} />
84
-
85
- {engineError && (
86
- <div className="absolute inset-0 w-full h-full flex items-center justify-center text-white p-6">
87
- Engine Error: {engineError}
88
- </div>
89
- )}
90
- {loading && !engineError && (
91
- <div className="absolute inset-0 max-w-xs mx-auto w-full h-full flex items-center justify-center text-white p-6">
92
- <Progress value={progress} className="rounded-none" />
93
- </div>
94
- )}
95
- <canvas ref={canvasRef} className="absolute inset-0 w-full h-full touch-none z-1" />
96
- </div>
97
- )
98
- }
99
- ```
1
+ # Reze Engine
2
+
3
+ A lightweight engine built with WebGPU and TypeScript for real-time 3D anime character MMD model rendering.
4
+
5
+ ## Features
6
+
7
+ - Physics
8
+ - Alpha blending
9
+ - Post alpha eye rendering
10
+ - Rim lighting
11
+ - Bloom
12
+ - Outlines
13
+ - Toon shading with directional lights
14
+ - MSAA 4x anti-aliasing
15
+ - GPU-accelerated skinning
16
+ - Bone rotation api
17
+
18
+ ## Usage
19
+
20
+ ```typescript
21
+ export default function Home() {
22
+ const canvasRef = useRef<HTMLCanvasElement>(null)
23
+ const engineRef = useRef<Engine | null>(null)
24
+ const [engineError, setEngineError] = useState<string | null>(null)
25
+ const [loading, setLoading] = useState(true)
26
+ const [stats, setStats] = useState<EngineStats>({
27
+ fps: 0,
28
+ frameTime: 0,
29
+ gpuMemory: 0,
30
+ })
31
+ const [progress, setProgress] = useState(0)
32
+
33
+ const initEngine = useCallback(async () => {
34
+ if (canvasRef.current) {
35
+ // Initialize engine
36
+ try {
37
+ const engine = new Engine(canvasRef.current)
38
+ engineRef.current = engine
39
+ await engine.init()
40
+ await engine.loadModel("/models/塞尔凯特/塞尔凯特.pmx")
41
+ setLoading(false)
42
+
43
+ engine.runRenderLoop(() => {
44
+ setStats(engine.getStats())
45
+ })
46
+ } catch (error) {
47
+ setEngineError(error instanceof Error ? error.message : "Unknown error")
48
+ }
49
+ }
50
+ }, [])
51
+
52
+ useEffect(() => {
53
+ void (async () => {
54
+ initEngine()
55
+ })()
56
+
57
+ // Cleanup on unmount
58
+ return () => {
59
+ if (engineRef.current) {
60
+ engineRef.current.dispose()
61
+ }
62
+ }
63
+ }, [initEngine])
64
+
65
+ useEffect(() => {
66
+ if (loading) {
67
+ const interval = setInterval(() => {
68
+ setProgress((prev) => {
69
+ if (prev >= 100) {
70
+ return 0
71
+ }
72
+ return prev + 1
73
+ })
74
+ }, 50)
75
+
76
+ return () => clearInterval(interval)
77
+ }
78
+ }, [loading])
79
+
80
+ return (
81
+ <div
82
+ className="fixed inset-0 w-full h-full overflow-hidden touch-none"
83
+ style={{
84
+ background:
85
+ "radial-gradient(ellipse at center, rgba(35, 35, 45, 0.8) 0%, rgba(35, 35, 45, 0.8) 8%, rgba(8, 8, 12, 0.95) 65%, rgba(0, 0, 0, 1) 100%)",
86
+ }}
87
+ >
88
+ <Header stats={stats} />
89
+
90
+ {engineError && (
91
+ <div className="absolute inset-0 w-full h-full flex items-center justify-center text-white p-6">
92
+ Engine Error: {engineError}
93
+ </div>
94
+ )}
95
+ {loading && !engineError && (
96
+ <div className="absolute inset-0 max-w-xs mx-auto w-full h-full flex items-center justify-center text-white p-6">
97
+ <Progress value={progress} className="rounded-none" />
98
+ </div>
99
+ )}
100
+ <canvas ref={canvasRef} className="absolute inset-0 w-full h-full touch-none z-1" />
101
+ </div>
102
+ )
103
+ }
104
+ ```
package/dist/engine.d.ts CHANGED
@@ -54,6 +54,9 @@ export declare class Engine {
54
54
  private linearSampler;
55
55
  bloomThreshold: number;
56
56
  bloomIntensity: number;
57
+ private rimLightIntensity;
58
+ private rimLightPower;
59
+ private rimLightColor;
57
60
  private currentModel;
58
61
  private modelDir;
59
62
  private physics;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/engine.js CHANGED
@@ -11,7 +11,11 @@ export class Engine {
11
11
  this.sampleCount = 4; // MSAA 4x
12
12
  // Bloom settings
13
13
  this.bloomThreshold = 0.3;
14
- this.bloomIntensity = 0.13;
14
+ this.bloomIntensity = 0.1;
15
+ // Rim light settings
16
+ this.rimLightIntensity = 0.35;
17
+ this.rimLightPower = 2.0;
18
+ this.rimLightColor = [1.0, 1.0, 1.0];
15
19
  this.currentModel = null;
16
20
  this.modelDir = "";
17
21
  this.physics = null;
@@ -102,9 +106,11 @@ export class Engine {
102
106
 
103
107
  struct MaterialUniforms {
104
108
  alpha: f32,
109
+ rimIntensity: f32,
110
+ rimPower: f32,
105
111
  _padding1: f32,
112
+ rimColor: vec3f,
106
113
  _padding2: f32,
107
- _padding3: f32,
108
114
  };
109
115
 
110
116
  struct VertexOutput {
@@ -175,7 +181,13 @@ export class Engine {
175
181
  lightAccum += toonFactor * radiance * nDotL;
176
182
  }
177
183
 
178
- let color = albedo * lightAccum;
184
+ // Rim light calculation
185
+ let viewDir = normalize(camera.viewPos - input.worldPos);
186
+ var rimFactor = 1.0 - max(dot(n, viewDir), 0.0);
187
+ rimFactor = pow(rimFactor, material.rimPower);
188
+ let rimLight = material.rimColor * material.rimIntensity * rimFactor;
189
+
190
+ let color = albedo * lightAccum + rimLight;
179
191
  let finalAlpha = material.alpha;
180
192
  if (finalAlpha < 0.001) {
181
193
  discard;
@@ -215,8 +227,10 @@ export class Engine {
215
227
  struct MaterialUniforms {
216
228
  alpha: f32,
217
229
  alphaMultiplier: f32, // New: multiplier for alpha (0.5 for over-eyes, 1.0 for over-non-eyes)
230
+ rimIntensity: f32,
231
+ rimPower: f32,
232
+ rimColor: vec3f,
218
233
  _padding1: f32,
219
- _padding2: f32,
220
234
  };
221
235
 
222
236
  struct VertexOutput {
@@ -286,7 +300,13 @@ export class Engine {
286
300
  lightAccum += toonFactor * radiance * nDotL;
287
301
  }
288
302
 
289
- let color = albedo * lightAccum;
303
+ // Rim light calculation
304
+ let viewDir = normalize(camera.viewPos - input.worldPos);
305
+ var rimFactor = 1.0 - max(dot(n, viewDir), 0.0);
306
+ rimFactor = pow(rimFactor, material.rimPower);
307
+ let rimLight = material.rimColor * material.rimIntensity * rimFactor;
308
+
309
+ let color = albedo * lightAccum + rimLight;
290
310
  let finalAlpha = material.alpha * material.alphaMultiplier;
291
311
  if (finalAlpha < 0.001) {
292
312
  discard;
@@ -1501,11 +1521,16 @@ export class Engine {
1501
1521
  const EPSILON = 0.001;
1502
1522
  const isTransparent = materialAlpha < 1.0 - EPSILON;
1503
1523
  // Create material uniform data - for hair materials, we'll create two versions
1504
- const materialUniformData = new Float32Array(4);
1524
+ // MaterialUniforms struct: alpha, rimIntensity, rimPower, _padding1, rimColor (vec3), _padding2
1525
+ const materialUniformData = new Float32Array(8);
1505
1526
  materialUniformData[0] = materialAlpha;
1506
- materialUniformData[1] = 1.0; // alphaMultiplier: 1.0 for normal rendering
1507
- materialUniformData[2] = 0.0;
1508
- materialUniformData[3] = 0.0;
1527
+ materialUniformData[1] = this.rimLightIntensity;
1528
+ materialUniformData[2] = this.rimLightPower;
1529
+ materialUniformData[3] = 0.0; // _padding1
1530
+ materialUniformData[4] = this.rimLightColor[0]; // rimColor.r
1531
+ materialUniformData[5] = this.rimLightColor[1]; // rimColor.g
1532
+ materialUniformData[6] = this.rimLightColor[2]; // rimColor.b
1533
+ materialUniformData[7] = 0.0; // _padding2
1509
1534
  const materialUniformBuffer = this.device.createBuffer({
1510
1535
  label: `material uniform: ${mat.name}`,
1511
1536
  size: materialUniformData.byteLength,
@@ -1538,11 +1563,16 @@ export class Engine {
1538
1563
  }
1539
1564
  else if (mat.isHair) {
1540
1565
  // For hair materials, create two bind groups: one for over-eyes (alphaMultiplier = 0.5) and one for over-non-eyes (alphaMultiplier = 1.0)
1541
- const materialUniformDataOverEyes = new Float32Array(4);
1566
+ // Hair MaterialUniforms struct: alpha, alphaMultiplier, rimIntensity, rimPower, rimColor (vec3), _padding1
1567
+ const materialUniformDataOverEyes = new Float32Array(8);
1542
1568
  materialUniformDataOverEyes[0] = materialAlpha;
1543
1569
  materialUniformDataOverEyes[1] = 0.5; // alphaMultiplier: 0.5 for over-eyes
1544
- materialUniformDataOverEyes[2] = 0.0;
1545
- materialUniformDataOverEyes[3] = 0.0;
1570
+ materialUniformDataOverEyes[2] = this.rimLightIntensity;
1571
+ materialUniformDataOverEyes[3] = this.rimLightPower;
1572
+ materialUniformDataOverEyes[4] = this.rimLightColor[0]; // rimColor.r
1573
+ materialUniformDataOverEyes[5] = this.rimLightColor[1]; // rimColor.g
1574
+ materialUniformDataOverEyes[6] = this.rimLightColor[2]; // rimColor.b
1575
+ materialUniformDataOverEyes[7] = 0.0; // _padding1
1546
1576
  const materialUniformBufferOverEyes = this.device.createBuffer({
1547
1577
  label: `material uniform (over eyes): ${mat.name}`,
1548
1578
  size: materialUniformDataOverEyes.byteLength,
@@ -1569,10 +1599,40 @@ export class Engine {
1569
1599
  bindGroup: bindGroupOverEyes,
1570
1600
  isTransparent,
1571
1601
  });
1602
+ // Create material uniform for hair over non-eyes (alphaMultiplier = 1.0)
1603
+ const materialUniformDataOverNonEyes = new Float32Array(8);
1604
+ materialUniformDataOverNonEyes[0] = materialAlpha;
1605
+ materialUniformDataOverNonEyes[1] = 1.0; // alphaMultiplier: 1.0 for over-non-eyes
1606
+ materialUniformDataOverNonEyes[2] = this.rimLightIntensity;
1607
+ materialUniformDataOverNonEyes[3] = this.rimLightPower;
1608
+ materialUniformDataOverNonEyes[4] = this.rimLightColor[0]; // rimColor.r
1609
+ materialUniformDataOverNonEyes[5] = this.rimLightColor[1]; // rimColor.g
1610
+ materialUniformDataOverNonEyes[6] = this.rimLightColor[2]; // rimColor.b
1611
+ materialUniformDataOverNonEyes[7] = 0.0; // _padding1
1612
+ const materialUniformBufferOverNonEyes = this.device.createBuffer({
1613
+ label: `material uniform (over non-eyes): ${mat.name}`,
1614
+ size: materialUniformDataOverNonEyes.byteLength,
1615
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
1616
+ });
1617
+ this.device.queue.writeBuffer(materialUniformBufferOverNonEyes, 0, materialUniformDataOverNonEyes);
1618
+ const bindGroupOverNonEyes = this.device.createBindGroup({
1619
+ label: `material bind group (over non-eyes): ${mat.name}`,
1620
+ layout: this.hairBindGroupLayout,
1621
+ entries: [
1622
+ { binding: 0, resource: { buffer: this.cameraUniformBuffer } },
1623
+ { binding: 1, resource: { buffer: this.lightUniformBuffer } },
1624
+ { binding: 2, resource: diffuseTexture.createView() },
1625
+ { binding: 3, resource: this.textureSampler },
1626
+ { binding: 4, resource: { buffer: this.skinMatrixBuffer } },
1627
+ { binding: 5, resource: toonTexture.createView() },
1628
+ { binding: 6, resource: this.textureSampler },
1629
+ { binding: 7, resource: { buffer: materialUniformBufferOverNonEyes } },
1630
+ ],
1631
+ });
1572
1632
  this.hairDrawsOverNonEyes.push({
1573
1633
  count: matCount,
1574
1634
  firstIndex: runningFirstIndex,
1575
- bindGroup,
1635
+ bindGroup: bindGroupOverNonEyes,
1576
1636
  isTransparent,
1577
1637
  });
1578
1638
  }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "A WebGPU-based MMD model renderer",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "type": "module",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/reze-engine/reze-engine"
10
+ "url": "https://github.com/AmyangXYZ/reze-engine"
11
11
  },
12
12
  "exports": {
13
13
  ".": {