添加WebGPU游戏基本功能:几何体、纹理和着色器支持

This commit is contained in:
SpecialX
2025-11-19 11:15:29 +08:00
parent 4648ca10ad
commit 7d5265bced
6 changed files with 175 additions and 23 deletions

View File

@@ -1,11 +1,16 @@
import shaderSource from './shaders/shader.wgsl?raw';
import { QuadGeometry } from './geometry';
import { Texture } from './texture';
class Renderer{
private device! : GPUDevice;
private context! : GPUCanvasContext;
private pipeline! : GPURenderPipeline;
private postitionBuffer! : GPUBuffer;
private colorBuffer! : GPUBuffer;
private texCoordBuffer! : GPUBuffer;
private textureBindGroup! : GPUBindGroup;
private testTexture! : Texture;
public async initialize()
{
@@ -37,25 +42,18 @@ class Renderer{
format: navigator.gpu.getPreferredCanvasFormat()
})
this.testTexture = await Texture.createTextureFromUrl(this.device, 'assets/UVEditorColorGrid.png');
this.prepareModel();
this.postitionBuffer = this.CreateBuffer(new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, 0.5,
0.5, 0.5,
0.5, -0.5
]));
this.colorBuffer = this.CreateBuffer(new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
]));
const geometry = new QuadGeometry();
this.postitionBuffer = this.CreateBuffer(new Float32Array(geometry.positions));
this.colorBuffer = this.CreateBuffer(new Float32Array(geometry.colors));
this.texCoordBuffer = this.CreateBuffer(new Float32Array(geometry.texCoords));
}
private CreateBuffer(data: Float32Array)
@@ -102,12 +100,27 @@ class Renderer{
}]
}
const textureCoordBufferLayout : GPUVertexBufferLayout =
{
arrayStride: 2 * Float32Array.BYTES_PER_ELEMENT,
attributes: [
{
shaderLocation: 2,
offset: 0,
format: 'float32x2'
}],
stepMode: 'vertex'
}
const vertexState: GPUVertexState = {
module : shaderModule,
entryPoint: "VertexMain",
buffers:
[postitionBufferLayout,
colorBufferLayout]
[
postitionBufferLayout,
colorBufferLayout,
textureCoordBufferLayout
]
}
const fragmentState: GPUFragmentState = {
@@ -115,18 +128,65 @@ class Renderer{
entryPoint: "FragmentMain",
targets: [
{
format: navigator.gpu.getPreferredCanvasFormat()
format: navigator.gpu.getPreferredCanvasFormat(),
blend: {
color: {
srcFactor: 'one',
dstFactor: 'zero',
operation: 'add'
},
alpha: {
srcFactor: 'one',
dstFactor: 'zero',
operation: 'add'
}
}
}
]
}
const textureBindGroupLayout = this.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.FRAGMENT,
sampler: {}
},
{
binding: 1,
visibility: GPUShaderStage.FRAGMENT,
texture: {}
}
]
});
const pipelineLayout = this.device.createPipelineLayout({
bindGroupLayouts: [
textureBindGroupLayout
]
});
this.textureBindGroup = this.device.createBindGroup({
layout: textureBindGroupLayout,
entries: [
{
binding: 0,
resource: this.testTexture.sampler
},
{
binding: 1,
resource: this.testTexture.texture.createView()
}
]
});
this.pipeline = this.device.createRenderPipeline({
vertex: vertexState,
fragment: fragmentState,
primitive:{
topology: 'triangle-list',
},
layout: "auto"
layout: pipelineLayout
});
@@ -154,6 +214,8 @@ class Renderer{
passEncoder.setPipeline(this.pipeline );
passEncoder.setVertexBuffer(0, this.postitionBuffer);
passEncoder.setVertexBuffer(1, this.colorBuffer);
passEncoder.setVertexBuffer(2, this.texCoordBuffer);
passEncoder.setBindGroup(0, this.textureBindGroup)
passEncoder.draw(6);
passEncoder.end();