This commit is contained in:
2026-04-12 01:06:31 +07:00
commit 10d660cbcb
1066 changed files with 228596 additions and 0 deletions

View File

@@ -0,0 +1,302 @@
# WebGPU Rendering
Modern GPU API for next-generation graphics.
## WebGPU Renderer
Next-generation rendering backend:
```javascript
import WebGPU from 'three/addons/capabilities/WebGPU.js';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
// Check support
if (WebGPU.isAvailable()) {
const renderer = new WebGPURenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Use setAnimationLoop (not requestAnimationFrame)
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
} else {
const warning = WebGPU.getErrorMessage();
document.body.appendChild(warning);
}
```
## Benefits of WebGPU
- Better performance (lower CPU overhead)
- Compute shaders
- Modern GPU features
- Unified shading language (WGSL)
- Better multi-threading support
- More predictable behavior
## Compute Shaders
GPU-accelerated computation:
```javascript
import { storageBuffer, uniform, Fn } from 'three/nodes';
import { StorageBufferAttribute } from 'three/addons/renderers/common/StorageBufferAttribute.js';
// Create storage buffer
const particleCount = 10000;
const positionBuffer = new StorageBufferAttribute(particleCount * 3, 3);
// Fill initial positions
for (let i = 0; i < particleCount; i++) {
positionBuffer.setXYZ(
i,
Math.random() * 10 - 5,
Math.random() * 10 - 5,
Math.random() * 10 - 5
);
}
// Create compute shader
const computeParticles = Fn(() => {
const position = storageBuffer(positionBuffer);
const time = uniform('time', 0);
const index = instanceIndex;
// Update position
const pos = position.element(index);
pos.y.addAssign(sin(time.add(index)).mul(0.01));
// Wrap around
If(pos.y.greaterThan(5), () => {
pos.y.assign(-5);
});
})();
// Create compute node
const computeNode = computeParticles.compute(particleCount);
// Execute in render loop
renderer.setAnimationLoop(() => {
renderer.compute(computeNode);
renderer.render(scene, camera);
});
```
## Storage Buffers
GPU-accessible memory:
```javascript
import { storage, Fn, vec3, float } from 'three/nodes';
// Define storage buffer structure
const particleData = storage(
new THREE.StorageBufferAttribute(count * 7, 7), // 7 floats per particle
'vec3', // position
'vec3', // velocity
'float' // life
);
// Access in compute shader
const updateParticle = Fn(() => {
const data = particleData.element(instanceIndex);
const position = data.xyz;
const velocity = data.toVec3(3); // offset 3
const life = data.element(6);
// Update
position.addAssign(velocity.mul(deltaTime));
life.subAssign(deltaTime);
})();
```
## WebGPU Node Materials
Use TSL (Three Shading Language) with WebGPU:
```javascript
import { MeshStandardNodeMaterial, texture, normalMap } from 'three/nodes';
const material = new MeshStandardNodeMaterial();
// Node-based material definition
material.colorNode = texture(diffuseTexture);
material.normalNode = normalMap(normalTexture);
material.roughnessNode = float(0.5);
material.metalnessNode = float(0.8);
// Works with both WebGL and WebGPU automatically
```
## Indirect Drawing
Efficient rendering with compute-generated draw calls:
```javascript
import { IndirectStorageBufferAttribute } from 'three/addons/renderers/common/IndirectStorageBufferAttribute.js';
// Create indirect buffer
const indirectBuffer = new IndirectStorageBufferAttribute(count, 5);
// 5 elements: count, instanceCount, first, baseInstance, (padding)
// Update with compute shader
const updateIndirect = Fn(() => {
const indirect = storage(indirectBuffer);
// Compute visibility and update instance count
const visible = computeVisibility();
If(visible, () => {
indirect.element(1).addAssign(1); // increment instanceCount
});
})();
// Render using indirect buffer
renderer.drawIndirect(mesh, indirectBuffer);
```
## Multi-Render-Target (MRT)
Render to multiple textures simultaneously:
```javascript
import { WebGPURenderTarget } from 'three/addons/renderers/webgpu/WebGPURenderTarget.js';
const renderTarget = new WebGPURenderTarget(width, height, {
count: 3, // number of render targets
format: THREE.RGBAFormat
});
// Access individual textures
const albedoTexture = renderTarget.textures[0];
const normalTexture = renderTarget.textures[1];
const depthTexture = renderTarget.textures[2];
// Use in deferred rendering pipeline
renderer.setRenderTarget(renderTarget);
renderer.render(scene, camera);
```
## Async Shader Compilation
Avoid frame drops:
```javascript
// Compile materials ahead of time
await renderer.compileAsync(scene, camera);
// Start rendering after compilation
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
```
## Performance Monitoring
GPU timestamp queries:
```javascript
// Query GPU timing
const timestampQuery = renderer.getTimestampQuery();
timestampQuery.begin();
renderer.render(scene, camera);
timestampQuery.end();
timestampQuery.getResult().then((duration) => {
console.log(`GPU time: ${duration}ms`);
});
```
## WebGPU-Specific Features
### Texture Compression
```javascript
// BC7 compression (higher quality)
const texture = new THREE.CompressedTexture(
mipmaps,
width,
height,
THREE.RGBA_BPTC_Format
);
```
### Depth Textures
```javascript
const depthTexture = new THREE.DepthTexture(width, height);
depthTexture.type = THREE.FloatType; // 32-bit depth
depthTexture.format = THREE.DepthFormat;
```
### Storage Textures
```javascript
import { storageTexture } from 'three/nodes';
// Read-write texture in compute shader
const writeableTexture = storageTexture(texture);
const computeShader = Fn(() => {
const coord = vec2(instanceIndex % width, instanceIndex / width);
const color = vec4(1, 0, 0, 1);
writeableTexture.store(coord, color);
})();
```
## Migration from WebGL
Most Three.js code works with both:
```javascript
// WebGL
const renderer = new THREE.WebGLRenderer();
// WebGPU (drop-in replacement for most cases)
const renderer = new WebGPURenderer();
// Exceptions:
// - Custom shaders: need to use Node materials or WGSL
// - Some extensions not available
// - Compute shaders only in WebGPU
```
## WGSL (WebGPU Shading Language)
Native shader language for WebGPU:
```wgsl
@group(0) @binding(0) var<storage, read_write> positions: array<vec3f>;
@group(0) @binding(1) var<uniform> time: f32;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id: vec3u) {
let index = global_id.x;
if (index >= arrayLength(&positions)) {
return;
}
var pos = positions[index];
pos.y += sin(time + f32(index)) * 0.01;
positions[index] = pos;
}
```
## Browser Support
As of 2025:
- ✅ Chrome 113+
- ✅ Edge 113+
- ✅ Safari 18+ (macOS/iOS)
- ❌ Firefox (in development)
Check support: `WebGPU.isAvailable()`
## Best Practices
- Use compute shaders for particle systems, physics
- Leverage storage buffers for large datasets
- Async compile before rendering
- Use Node materials instead of custom GLSL
- Test on both WebGL and WebGPU
- Provide WebGL fallback for unsupported browsers