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) }) */