Files
WebGPU-Framework/demos/NodeJS/index.js

304 lines
6.1 KiB
JavaScript
Raw Normal View History

2025-11-18 11:45:56 +01:00
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)
})
*/