UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

101 lines (92 loc) 3.44 kB
import { UniformBufferFormat, UniformFormat } from '../uniform-buffer-format.js'; import { BlendState } from '../blend-state.js'; import { SHADERLANGUAGE_WGSL, UNIFORMTYPE_VEC4, UNIFORMTYPE_FLOAT, BINDGROUP_MESH_UB, BINDGROUP_MESH, CLEARFLAG_COLOR, CLEARFLAG_DEPTH, CLEARFLAG_STENCIL, CULLFACE_NONE, PRIMITIVE_TRISTRIP } 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); if (flags & CLEARFLAG_COLOR && (renderTarget.colorBuffer || renderTarget.impl.assignedColorTexture)) { const color = options.color ?? defaultOptions.color; this.colorData.set(color); device.setBlendState(BlendState.NOBLEND); } else { device.setBlendState(BlendState.NOWRITE); } uniformBuffer.set('color', this.colorData); if (flags & CLEARFLAG_DEPTH && renderTarget.depth) { const depth = options.depth ?? defaultOptions.depth; uniformBuffer.set('depth', depth); device.setDepthState(DepthState.WRITEDEPTH); } else { uniformBuffer.set('depth', 1); device.setDepthState(DepthState.NODEPTH); } if (flags & CLEARFLAG_STENCIL && renderTarget.stencil) ; uniformBuffer.endUpdate(); device.setCullMode(CULLFACE_NONE); device.setShader(this.shader); device.draw(primitive); } } } export { WebgpuClearRenderer };