161 lines
4.5 KiB
JavaScript
161 lines
4.5 KiB
JavaScript
import { getPath } from "./common.js";
|
|
|
|
function parseHeader(buffer)
|
|
{
|
|
const array = new Uint32Array(buffer);
|
|
/*
|
|
console.log("index count", icosphereU32[0]);
|
|
console.log("index buffer offset", icosphereU32[1]);
|
|
console.log("index buffer size", icosphereU32[2]);
|
|
console.log("vertex buffer offset", icosphereU32[3]);
|
|
console.log("vertex buffer size", icosphereU32[4]);
|
|
*/
|
|
|
|
return {
|
|
indexCount: array[0],
|
|
indexOffset: array[1],
|
|
indexSize: array[2],
|
|
vertexOffset: array[3],
|
|
vertexSize: array[4],
|
|
};
|
|
}
|
|
|
|
class LightRenderer {
|
|
constructor(device, canvasFormat, viewUniformBuffer,
|
|
shaderModule, binBuffer, label)
|
|
{
|
|
//////////////////////////////////////////////////////////////////////
|
|
// buffer
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
const header = parseHeader(binBuffer);
|
|
this.header = header;
|
|
|
|
this.buffer = device.createBuffer({
|
|
label: `${label} renderer buffer`,
|
|
size: header.indexSize + header.vertexSize,
|
|
usage: GPUBufferUsage.INDEX | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
|
|
});
|
|
this.indexOffset = 0;
|
|
this.vertexOffset = header.indexSize;
|
|
|
|
device.queue.writeBuffer(this.buffer, this.indexOffset,
|
|
binBuffer, header.indexOffset, header.indexSize);
|
|
device.queue.writeBuffer(this.buffer, this.vertexOffset,
|
|
binBuffer, header.vertexOffset, header.vertexSize);
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// pipeline
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
const bindGroupLayouts = [
|
|
device.createBindGroupLayout({
|
|
label: `${label} view matrix bind group layout`,
|
|
entries: [{
|
|
binding: 0,
|
|
visibility: GPUShaderStage.VERTEX,
|
|
buffer: { type: "uniform" }
|
|
},/* {
|
|
binding: 1,
|
|
visibility: GPUShaderStage.VERTEX,
|
|
buffer: { type: "read-only-storage" }
|
|
}*/]
|
|
}),
|
|
];
|
|
|
|
const pipelineLayout = device.createPipelineLayout({
|
|
label: `${label} pipeline layout`,
|
|
bindGroupLayouts: bindGroupLayouts,
|
|
});
|
|
|
|
const vertexBufferLayouts = [{
|
|
arrayStride: 36,
|
|
attributes: [{
|
|
format: "float32x3",
|
|
offset: 0,
|
|
shaderLocation: 0,
|
|
}, {
|
|
format: "float32x2",
|
|
offset: 12,
|
|
shaderLocation: 1,
|
|
}, {
|
|
format: "float16x4",
|
|
offset: 20,
|
|
shaderLocation: 2,
|
|
}, {
|
|
format: "float16x4",
|
|
offset: 28,
|
|
shaderLocation: 3,
|
|
}],
|
|
stepMode: "vertex",
|
|
}];
|
|
|
|
this.renderPipeline = device.createRenderPipeline({
|
|
label: `${label} pipeline`,
|
|
layout: pipelineLayout,
|
|
vertex: {
|
|
module: shaderModule,
|
|
entryPoint: "vertexMain",
|
|
buffers: vertexBufferLayouts,
|
|
},
|
|
fragment: {
|
|
module: shaderModule,
|
|
entryPoint: "fragmentMain",
|
|
targets: [{
|
|
format: canvasFormat,
|
|
}]
|
|
},
|
|
primitive: {
|
|
topology: "triangle-list",
|
|
},
|
|
depthStencil: {
|
|
depthWriteEnabled: true,
|
|
depthCompare: "less",
|
|
format: "depth24plus",
|
|
},
|
|
});
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// bind group
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
this.bindGroups = [
|
|
device.createBindGroup({
|
|
label: `${label} bind group`,
|
|
layout: bindGroupLayouts[0],
|
|
entries: [{
|
|
binding: 0,
|
|
resource: { buffer: viewUniformBuffer },
|
|
}],
|
|
}),
|
|
];
|
|
}
|
|
|
|
render(renderPass)
|
|
{
|
|
renderPass.setPipeline(this.renderPipeline);
|
|
renderPass.setVertexBuffer(0, this.buffer, this.vertexOffset, this.header.vertexSize);
|
|
renderPass.setIndexBuffer(this.buffer, "uint16", this.indexOffset, this.header.indexSize);
|
|
renderPass.setBindGroup(0, this.bindGroups[0]);
|
|
renderPass.drawIndexed(this.header.indexCount);
|
|
}
|
|
}
|
|
|
|
async function loadLight(device, canvasFormat, viewUniformBuffer)
|
|
{
|
|
const lightWgsl = getPath("light.wgsl");
|
|
const shaderModule = device.createShaderModule({
|
|
label: "light shader",
|
|
code: await lightWgsl,
|
|
});
|
|
|
|
const response = await fetch("obj/icosphere.bin");
|
|
const binBuffer = await response.arrayBuffer();
|
|
|
|
const renderer = new LightRenderer(device, canvasFormat, viewUniformBuffer,
|
|
shaderModule, binBuffer, "light");
|
|
return renderer;
|
|
}
|
|
|
|
export { loadLight };
|