304 lines
6.1 KiB
JavaScript
304 lines
6.1 KiB
JavaScript
|
|
import sdl from '@kmamal/sdl'
|
||
|
|
|
||
|
|
import gpu from '@kmamal/gpu'
|
||
|
|
|
||
|
|
import Shader from "../../framework/WebGpu_node.js"
|
||
|
|
|
||
|
|
import Matrix4 from "../../framework/Matrix4.js"
|
||
|
|
|
||
|
|
import Vector3 from "../../framework/Vector3.js"
|
||
|
|
|
||
|
|
import Camera from "../../framework/Camera.js";
|
||
|
|
|
||
|
|
import EventManager from "../../framework/eventManager_node.js";
|
||
|
|
|
||
|
|
import { readFileSync } from "node:fs";
|
||
|
|
|
||
|
|
|
||
|
|
const window = sdl.video.createWindow({ webgpu: true })
|
||
|
|
|
||
|
|
var canvas = window;
|
||
|
|
|
||
|
|
const instance = gpu.create([ 'verbose=1' ])
|
||
|
|
|
||
|
|
console.log("devices", gpu)
|
||
|
|
|
||
|
|
const adapter = await instance.requestAdapter()
|
||
|
|
|
||
|
|
const device = await adapter.requestDevice()
|
||
|
|
|
||
|
|
|
||
|
|
const renderer = gpu.renderGPUDeviceToWindow({ device, window })
|
||
|
|
|
||
|
|
|
||
|
|
canvas.getContext = function() {
|
||
|
|
|
||
|
|
return renderer;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var renderShader = new Shader( device );
|
||
|
|
|
||
|
|
|
||
|
|
renderShader.setCanvas( canvas );
|
||
|
|
|
||
|
|
renderShader.topology = "triangle-list";
|
||
|
|
|
||
|
|
await renderShader.setup( "../../shaders/triangle-list.wgsl");
|
||
|
|
|
||
|
|
async function loadJSON( pathName ) {
|
||
|
|
|
||
|
|
const json = await readFileSync( pathName, 'utf8' )
|
||
|
|
|
||
|
|
return JSON.parse( json );
|
||
|
|
}
|
||
|
|
|
||
|
|
var camera = new Camera( [0, 0, 1115], [0, -.3, 0], [0, 1, 0] );
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var eventManager = new EventManager( canvas );
|
||
|
|
|
||
|
|
eventManager.setup( canvas, camera );
|
||
|
|
|
||
|
|
eventManager.registerEventListenersNode();
|
||
|
|
|
||
|
|
var frameCount = 0;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var model = await loadJSON("../../models/demo.json");
|
||
|
|
|
||
|
|
var mesh = model.meshes[0];
|
||
|
|
|
||
|
|
|
||
|
|
const instanceCount = 100;
|
||
|
|
const instancePositions = new Float32Array(instanceCount * 4); // vec4 per instance
|
||
|
|
|
||
|
|
for (let i = 0; i < instanceCount; i++) {
|
||
|
|
|
||
|
|
const x = (i % 10) * 300.0;
|
||
|
|
const y = Math.floor(i / 10) * 350.0;
|
||
|
|
|
||
|
|
instancePositions[i * 4 + 0] = x - 500;
|
||
|
|
instancePositions[i * 4 + 1] = 0;
|
||
|
|
instancePositions[i * 4 + 2] = y - 500;
|
||
|
|
instancePositions[i * 4 + 3] = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
renderShader.setAttribute( "position", mesh.vertices );
|
||
|
|
|
||
|
|
renderShader.setAttribute( "normal", mesh.normals );
|
||
|
|
|
||
|
|
renderShader.setVariable( "instancePositions", instancePositions );
|
||
|
|
|
||
|
|
|
||
|
|
var faces = mesh.faces;
|
||
|
|
|
||
|
|
const indexArray = new Uint32Array(faces.length * 3);
|
||
|
|
|
||
|
|
for (let i = 0; i < faces.length; i++) {
|
||
|
|
|
||
|
|
indexArray[i * 3 + 0] = faces[i][0];
|
||
|
|
|
||
|
|
indexArray[i * 3 + 1] = faces[i][1];
|
||
|
|
|
||
|
|
indexArray[i * 3 + 2] = faces[i][2];
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
renderShader.setIndices( indexArray );
|
||
|
|
|
||
|
|
var lastFrameTime = 0;
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
function updateTimeDelta() {
|
||
|
|
|
||
|
|
const now = performance.now();
|
||
|
|
|
||
|
|
deltaTimeValue = ( now - lastFrameTime ) / 1000;
|
||
|
|
|
||
|
|
lastFrameTime = now;
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
var frameCount = 0;
|
||
|
|
|
||
|
|
var deltaTimeValue = 0;
|
||
|
|
|
||
|
|
var vertexCount = 1;
|
||
|
|
|
||
|
|
const render = () => {
|
||
|
|
|
||
|
|
if (window.destroyed) { return }
|
||
|
|
|
||
|
|
updateTimeDelta();
|
||
|
|
|
||
|
|
const viewMatrixData = camera.getViewMatrix();
|
||
|
|
|
||
|
|
const projectionMatrixData = Matrix4.createProjectionMatrix( camera, canvas )
|
||
|
|
|
||
|
|
const viewProjectionMatrix = Matrix4.multiply( projectionMatrixData, viewMatrixData );
|
||
|
|
|
||
|
|
const cameraWorldMatrix = Matrix4.invert( viewMatrixData );
|
||
|
|
|
||
|
|
const cameraPosition = Matrix4.getColumn( cameraWorldMatrix, 3 );
|
||
|
|
|
||
|
|
renderShader.setVariable( "viewProjectionMatrix", viewProjectionMatrix );
|
||
|
|
|
||
|
|
renderShader.setVariable( "cameraPosition", cameraPosition );
|
||
|
|
|
||
|
|
frameCount++;
|
||
|
|
|
||
|
|
|
||
|
|
renderShader.renderToCanvas( vertexCount, 60, 0, frameCount )
|
||
|
|
|
||
|
|
|
||
|
|
renderer.swap()
|
||
|
|
|
||
|
|
|
||
|
|
frameCount++;
|
||
|
|
|
||
|
|
setTimeout(render, 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
render();
|
||
|
|
|
||
|
|
|
||
|
|
window.on('close', () => {
|
||
|
|
device.destroy()
|
||
|
|
gpu.destroy(instance)
|
||
|
|
})
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//console.log(model);
|
||
|
|
|
||
|
|
/*
|
||
|
|
const renderer = gpu.renderGPUDeviceToWindow({ device, window })
|
||
|
|
|
||
|
|
const positions = new Float32Array([
|
||
|
|
...[ 1.0, -1.0, 0.0 ],
|
||
|
|
...[ -1.0, -1.0, 0.0 ],
|
||
|
|
...[ 0.0, 1.0, 0.0 ],
|
||
|
|
])
|
||
|
|
|
||
|
|
const colors = new Float32Array([
|
||
|
|
...[ 1.0, 0.0, 0.0 ],
|
||
|
|
...[ 0.0, 1.0, 0.0 ],
|
||
|
|
...[ 0.0, 0.0, 1.0 ],
|
||
|
|
])
|
||
|
|
|
||
|
|
const indices = new Uint16Array([ 0, 1, 2 ])
|
||
|
|
|
||
|
|
const createBuffer = (arr, usage) => {
|
||
|
|
const buffer = device.createBuffer({
|
||
|
|
size: (arr.byteLength + 3) & ~3,
|
||
|
|
usage,
|
||
|
|
mappedAtCreation: true,
|
||
|
|
})
|
||
|
|
|
||
|
|
const writeArray = arr instanceof Uint16Array
|
||
|
|
? new Uint16Array(buffer.getMappedRange())
|
||
|
|
: new Float32Array(buffer.getMappedRange())
|
||
|
|
writeArray.set(arr)
|
||
|
|
buffer.unmap()
|
||
|
|
return buffer
|
||
|
|
}
|
||
|
|
|
||
|
|
const positionBuffer = createBuffer(positions, gpu.GPUBufferUsage.VERTEX)
|
||
|
|
const colorBuffer = createBuffer(colors, gpu.GPUBufferUsage.VERTEX)
|
||
|
|
const indexBuffer = createBuffer(indices, gpu.GPUBufferUsage.INDEX)
|
||
|
|
|
||
|
|
const vertexShaderFile = path.join(__dirname, 'vertex.wgsl')
|
||
|
|
const vertexShaderCode = await fs.promises.readFile(vertexShaderFile, 'utf8')
|
||
|
|
|
||
|
|
const fragmentShaderFile = path.join(__dirname, 'fragment.wgsl')
|
||
|
|
const fragmentShaderCode = await fs.promises.readFile(fragmentShaderFile, 'utf8')
|
||
|
|
|
||
|
|
const pipeline = device.createRenderPipeline({
|
||
|
|
layout: 'auto',
|
||
|
|
vertex: {
|
||
|
|
module: device.createShaderModule({ code: vertexShaderCode }),
|
||
|
|
entryPoint: 'main',
|
||
|
|
buffers: [
|
||
|
|
{
|
||
|
|
attributes: [
|
||
|
|
{
|
||
|
|
shaderLocation: 0,
|
||
|
|
offset: 0,
|
||
|
|
format: 'float32x3',
|
||
|
|
},
|
||
|
|
],
|
||
|
|
arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
|
||
|
|
stepMode: 'vertex',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
attributes: [
|
||
|
|
{
|
||
|
|
shaderLocation: 1,
|
||
|
|
offset: 0,
|
||
|
|
format: 'float32x3',
|
||
|
|
},
|
||
|
|
],
|
||
|
|
arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
|
||
|
|
stepMode: 'vertex',
|
||
|
|
},
|
||
|
|
],
|
||
|
|
},
|
||
|
|
fragment: {
|
||
|
|
module: device.createShaderModule({ code: fragmentShaderCode }),
|
||
|
|
entryPoint: 'main',
|
||
|
|
targets: [ { format: renderer.getPreferredFormat() } ],
|
||
|
|
},
|
||
|
|
primitive: {
|
||
|
|
topology: 'triangle-list',
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
const render = () => {
|
||
|
|
if (window.destroyed) { return }
|
||
|
|
|
||
|
|
const commandEncoder = device.createCommandEncoder()
|
||
|
|
|
||
|
|
const renderPass = commandEncoder.beginRenderPass({
|
||
|
|
colorAttachments: [
|
||
|
|
{
|
||
|
|
view: renderer.getCurrentTextureView(),
|
||
|
|
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
|
||
|
|
loadOp: 'clear',
|
||
|
|
storeOp: 'store',
|
||
|
|
},
|
||
|
|
],
|
||
|
|
})
|
||
|
|
renderPass.setPipeline(pipeline)
|
||
|
|
renderPass.setViewport(0, 0, width, height, 0, 1)
|
||
|
|
renderPass.setScissorRect(0, 0, width, height)
|
||
|
|
renderPass.setVertexBuffer(0, positionBuffer)
|
||
|
|
renderPass.setVertexBuffer(1, colorBuffer)
|
||
|
|
renderPass.setIndexBuffer(indexBuffer, 'uint16')
|
||
|
|
renderPass.drawIndexed(3)
|
||
|
|
renderPass.end()
|
||
|
|
|
||
|
|
device.queue.submit([ commandEncoder.finish() ])
|
||
|
|
|
||
|
|
renderer.swap()
|
||
|
|
|
||
|
|
setTimeout(render, 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
render()
|
||
|
|
|
||
|
|
window.on('close', () => {
|
||
|
|
device.destroy()
|
||
|
|
gpu.destroy(instance)
|
||
|
|
})
|
||
|
|
|
||
|
|
*/
|