UNPKG

@giraphics/grpkggfx

Version:
155 lines (151 loc) 5.84 kB
import { device } from '../renderer/webgpurenderer'; import { mat4, vec3 } from 'gl-matrix'; import { triangleVertexArray, triangleVertexCount, cubeVertexArray, cubeVertexCount } from './vertices'; const wgslShaders = { vertex: ` [[block]] struct Uniforms { modelViewProjectionMatrix : mat4x4<f32>; }; [[binding(0), group(0)]] var<uniform> uniforms : Uniforms; struct VertexOutput { [[builtin(position)]] Position : vec4<f32>; [[location(0)]] fragColor : vec4<f32>; }; [[stage(vertex)]] fn main([[location(0)]] position : vec4<f32>, [[location(1)]] color : vec4<f32>) -> VertexOutput { return VertexOutput(uniforms.modelViewProjectionMatrix * position, color); } `, fragment: ` [[stage(fragment)]] fn main([[location(0)]] fragColor : vec4<f32>) -> [[location(0)]] vec4<f32> { return fragColor; } `, }; const positionOffset = 0; const colorOffset = 4 * 4; // Byte offset of object color attribute. const vertexSize = 4 * 10; // Byte size of one object. export class RenderObject { constructor(device, verticesArray, vertexCount, parameter) { this.x = 0; this.y = 0; this.z = 0; this.rotX = 0; this.rotY = 0; this.rotZ = 0; this.matrixSize = 4 * 16; // 4x4 matrix this.offset = 256; // uniformBindGroup offset must be 256-byte aligned this.uniformBufferSize = this.offset + this.matrixSize; this.modelViewProjectionMatrix = mat4.create(); this.vertexCount = vertexCount; this.renderPipeline = device.createRenderPipeline({ vertex: { module: device.createShaderModule({ code: wgslShaders.vertex, }), entryPoint: 'main', buffers: [ { arrayStride: vertexSize, attributes: [ { // position shaderLocation: 0, offset: positionOffset, format: 'float32x4', }, { // color shaderLocation: 1, offset: colorOffset, format: 'float32x4', }, ], }, ], }, fragment: { module: device.createShaderModule({ code: wgslShaders.fragment, }), entryPoint: 'main', targets: [ { format: 'bgra8unorm', }, ], }, primitive: { topology: 'triangle-list', cullMode: 'back', }, depthStencil: { depthWriteEnabled: true, depthCompare: 'less', format: 'depth24plus-stencil8', }, }); this.uniformBuffer = device.createBuffer({ size: this.uniformBufferSize, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, }); this.uniformBindGroup = device.createBindGroup({ layout: this.renderPipeline.getBindGroupLayout(0), entries: [ { binding: 0, resource: { buffer: this.uniformBuffer, offset: 0, size: this.matrixSize, }, }, ], }); this.verticesBuffer = device.createBuffer({ size: verticesArray.byteLength, usage: GPUBufferUsage.VERTEX, mappedAtCreation: true, }); new Float32Array(this.verticesBuffer.getMappedRange()).set(verticesArray); this.verticesBuffer.unmap(); this.setTransformation(parameter); } static cube(parameter) { return new RenderObject(device, cubeVertexArray, cubeVertexCount, parameter); } static pyramid(parameter) { return new RenderObject(device, triangleVertexArray, triangleVertexCount, parameter); } draw(passEncoder, device, camera) { this.updateTransformationMatrix(camera.getCameraViewProjMatrix()); passEncoder.setPipeline(this.renderPipeline); device.queue.writeBuffer(this.uniformBuffer, 0, this.modelViewProjectionMatrix.buffer, this.modelViewProjectionMatrix.byteOffset, this.modelViewProjectionMatrix.byteLength); passEncoder.setVertexBuffer(0, this.verticesBuffer); passEncoder.setBindGroup(0, this.uniformBindGroup); passEncoder.draw(this.vertexCount, 1, 0, 0); } updateTransformationMatrix(cameraProjectionMatrix) { // MOVE / TRANSLATE OBJECT const modelMatrix = mat4.create(); mat4.translate(modelMatrix, modelMatrix, vec3.fromValues(this.x, this.y, this.z)); mat4.rotateX(modelMatrix, modelMatrix, this.rotX); mat4.rotateY(modelMatrix, modelMatrix, this.rotY); mat4.rotateZ(modelMatrix, modelMatrix, this.rotZ); // PROJECT ON CAMERA mat4.multiply(this.modelViewProjectionMatrix, cameraProjectionMatrix, modelMatrix); } setTransformation(parameter) { if (parameter == null) { return; } this.x = parameter.x ? parameter.x : 0; this.y = parameter.y ? parameter.y : 0; this.z = parameter.z ? parameter.z : 0; this.rotX = parameter.rotX ? parameter.rotX : 0; this.rotY = parameter.rotY ? parameter.rotY : 0; this.rotZ = parameter.rotZ ? parameter.rotZ : 0; } }