UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

114 lines (107 loc) 3.31 kB
import { UniformBufferFormat, UniformFormat } from "../uniform-buffer-format.js"; import { BlendState } from "../blend-state.js"; import { PRIMITIVE_TRISTRIP, SHADERLANGUAGE_WGSL, UNIFORMTYPE_FLOAT, UNIFORMTYPE_VEC4, BINDGROUP_MESH, CLEARFLAG_COLOR, CLEARFLAG_DEPTH, CLEARFLAG_STENCIL, BINDGROUP_MESH_UB } from "../constants.js"; import { Shader } from "../shader.js"; import { DynamicBindGroup } from "../bind-group.js"; import { UniformBuffer } from "../uniform-buffer.js"; import { DepthState } from "../depth-state.js"; const primitive = { type: PRIMITIVE_TRISTRIP, base: 0, baseVertex: 0, count: 4, indexed: false }; class WebgpuClearRenderer { constructor(device) { const code = ` struct ub_mesh { color : vec4f, depth: f32 } @group(2) @binding(0) var<uniform> ubMesh : ub_mesh; var<private> pos : array<vec2f, 4> = array<vec2f, 4>( vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0), vec2(1.0, -1.0) ); struct VertexOutput { @builtin(position) position : vec4f } @vertex fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput { var output : VertexOutput; output.position = vec4(pos[vertexIndex], ubMesh.depth, 1.0); return output; } @fragment fn fragmentMain() -> @location(0) vec4f { return ubMesh.color; } `; this.shader = new Shader(device, { name: "WebGPUClearRendererShader", shaderLanguage: SHADERLANGUAGE_WGSL, vshader: code, fshader: code }); this.uniformBuffer = new UniformBuffer(device, new UniformBufferFormat(device, [ new UniformFormat("color", UNIFORMTYPE_VEC4), new UniformFormat("depth", UNIFORMTYPE_FLOAT) ]), false); this.dynamicBindGroup = new DynamicBindGroup(); this.colorData = new Float32Array(4); } destroy() { this.shader.destroy(); this.shader = null; this.uniformBuffer.destroy(); this.uniformBuffer = null; } clear(device, renderTarget, options, defaultOptions) { options = options || defaultOptions; const flags = options.flags ?? defaultOptions.flags; if (flags !== 0) { const { uniformBuffer, dynamicBindGroup } = this; uniformBuffer.startUpdate(dynamicBindGroup); device.setBindGroup(BINDGROUP_MESH_UB, dynamicBindGroup.bindGroup, dynamicBindGroup.offsets); device.setBindGroup(BINDGROUP_MESH, device.emptyBindGroup); let blendState; if (flags & CLEARFLAG_COLOR && (renderTarget.colorBuffer || renderTarget.impl.assignedColorTexture)) { const color = options.color ?? defaultOptions.color; this.colorData.set(color); blendState = BlendState.NOBLEND; } else { blendState = BlendState.NOWRITE; } uniformBuffer.set("color", this.colorData); let depthState; if (flags & CLEARFLAG_DEPTH && renderTarget.depth) { const depth = options.depth ?? defaultOptions.depth; uniformBuffer.set("depth", depth); depthState = DepthState.WRITEDEPTH; } else { uniformBuffer.set("depth", 1); depthState = DepthState.NODEPTH; } if (flags & CLEARFLAG_STENCIL && renderTarget.stencil) { } uniformBuffer.endUpdate(); device.setDrawStates(blendState, depthState); device.setShader(this.shader); device.draw(primitive); } } } export { WebgpuClearRenderer };