Skip to content

Commit

Permalink
added some camera stuff to use
Browse files Browse the repository at this point in the history
  • Loading branch information
JediWattson committed Jun 24, 2023
1 parent 172fc6c commit e3719ea
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 67 deletions.
33 changes: 25 additions & 8 deletions components/canvas/buffer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
export const makeBuffer = (device: GPUDevice) => {
import { mat4 } from "gl-matrix";

const makeBuffer = (verticesCoords: number[]) => (device: GPUDevice, uniBuffer: GPUBuffer) => {
// each row contains 3 position values, 3 color values, 3 full points here
const vertices = new Float32Array([
0.0, 0.0, 0.5, 1.0, 0.0, 0.0,
0.0, -0.5, -0.5, 0.0, 1.0, 0.0,
0.0, 0.5, -0.5, 0.0, 0.0, 1.0
]);
const vertices = new Float32Array(verticesCoords);

const descriptor: GPUBufferDescriptor = {
size: vertices.byteLength,
Expand Down Expand Up @@ -32,8 +30,27 @@ export const makeBuffer = (device: GPUDevice) => {
]
}

let t = 0.0
return {
buffer,
bufferLayout
bufferLayout,
update() {
t += 0.01
if (t > 2.0 * Math.PI) {
t -= 2.0 * Math.PI;
}

const model = mat4.create();
mat4.rotate(model, model, t, [0,0,1]);
device.queue.writeBuffer(uniBuffer, 0, <ArrayBuffer>model);

}
}
};
};

// each row contains 3 position values, 3 color values, 3 full points here
export const makeTriangle = makeBuffer([
0.0, 0.0, 0.5, 1.0, 0.0, 0.0,
0.0, -0.5, -0.5, 0.0, 1.0, 0.0,
0.0, 0.5, -0.5, 0.0, 0.0, 1.0
])
48 changes: 48 additions & 0 deletions components/canvas/camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { mat4, vec3 } from "gl-matrix";

export function Deg2Rad(theta: number) : number {
return theta * Math.PI / 180;
}

export function makeCamera(device: GPUDevice, uniBuffer: GPUBuffer) {

const projection = mat4.create();
mat4.perspective(projection, Math.PI/4, 800/600, 0.1, 10);
device.queue.writeBuffer(uniBuffer, 128, <ArrayBuffer>projection);

const eulers = [0, 0, 0];

const position: vec3 = [-2, 0, 0];
const up = vec3.create();
const right = vec3.create();
const target = vec3.create();
const view = mat4.create();

function setMovement() {
const forwards: vec3 = [
Math.cos(Deg2Rad(eulers[2])) * Math.cos(Deg2Rad(eulers[1])),
Math.sin(Deg2Rad(eulers[2])) * Math.cos(Deg2Rad(eulers[1])),
Math.sin(Deg2Rad(eulers[1]))
];

vec3.cross(right, forwards, [0,0,1]);
vec3.cross(up, right, forwards);
vec3.add(target, position, forwards);
mat4.lookAt(view, position, target, up);
device.queue.writeBuffer(uniBuffer, 64, <ArrayBuffer>view);
}

return {
reset() {
eulers.forEach((e, i) => {eulers[i] = 0})
setMovement();
},
update({ movementX, movementY }: { movementX: number, movementY: number }) {
eulers[1] = Math.min(89, Math.max(-89, movementY))
eulers[2] -= movementX / 5;
eulers[2] %= 360;

setMovement();
}
}
}
12 changes: 10 additions & 2 deletions components/canvas/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ import useInit from "./lib";

function Canvas() {
const canvasRef = useRef<CanvasRefType>(null);
useInit(canvasRef);
return <canvas ref={canvasRef} />
const events = useInit(canvasRef);

return (
<canvas
ref={canvasRef}
onClick={events.handleClick}
onMouseMove={events.handleMouseMove}
onMouseOut={events.handleMouseOut}
/>
)
}

export default Canvas;
90 changes: 33 additions & 57 deletions components/canvas/lib.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useEffect, useRef } from "react";
import { EventHandler, MouseEvent, MouseEventHandler, SyntheticEvent, useEffect, useRef } from "react";

import fragmentShader from './fragment.wgsl'
import { makeBuffer } from "./buffer";
import { makeTriangle } from "./buffer";
import { mat4 } from "gl-matrix";
import { makeCamera } from "./camera";

export type CanvasRefType = HTMLCanvasElement | null;

Expand All @@ -11,66 +12,29 @@ function startPipeline(
context: GPUCanvasContext,
pipeline: GPURenderPipeline,
bindGroup: GPUBindGroup,
triangleTexture: GPUBuffer,
uniBuffer: GPUBuffer
triangleMesh: { buffer: GPUBuffer, update: () => void }
): () => void {
let frameId: number;
let t: number = 0.0
function frame() {

t += 0.01
if (t > 2.0 * Math.PI) {
t -= 2.0 * Math.PI;
}

//make transforms
const projection = mat4.create();
// load perspective projection into the projection matrix,
// Field of view = 45 degrees (pi/4)
// Aspect ratio = 800/600
// near = 0.1, far = 10
mat4.perspective(projection, Math.PI/4, 800/600, 0.1, 10);

const view = mat4.create();
//load lookat matrix into the view matrix,
//looking from [-2, 0, 2]
//looking at [0, 0, 0]
//up vector is [0, 0, 1]
mat4.lookAt(view, [-2, 0, 2], [0, 0, 0], [0, 0, 1]);

const model = mat4.create();
//Store, in the model matrix, the model matrix after rotating it by t radians around the z axis.
//(yeah, I know, kinda weird.)
mat4.rotate(model, model, t, [0,0,1]);


// TODO - I'd like to use this, but how?
// const projection = mat4.perspective(Math.PI / 4, 7/6, 0.1, 10);
// const view = mat4.lookAt([-2, 0, 2], [0, 0, 0], [0, 0, 1]);
// let model = mat4.create()
// mat4.rotate(model, [0, 0, 1], t, model);

device.queue.writeBuffer(uniBuffer, 0, <ArrayBuffer>model);
device.queue.writeBuffer(uniBuffer, 64, <ArrayBuffer>view);
device.queue.writeBuffer(uniBuffer, 128, <ArrayBuffer>projection);

function frame() {
triangleMesh.update();
const commandEncoder = device.createCommandEncoder();
const textureView = context.getCurrentTexture().createView();

const renderPassDescriptor: GPURenderPassDescriptor = {
colorAttachments: [
{
view: textureView,
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
loadOp: 'clear',
storeOp: 'store',
view: textureView,
clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
loadOp: 'clear',
storeOp: 'store',
},
],
};

const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, triangleTexture);
passEncoder.setVertexBuffer(0, triangleMesh.buffer);
passEncoder.setBindGroup(0, bindGroup);
passEncoder.draw(3, 1, 0, 0);
passEncoder.end();
Expand All @@ -86,9 +50,8 @@ function startPipeline(
}

function useInit(canvasRef: { current: CanvasRefType }) {

const cleanup = useRef(() => {});
const uniBuffer = useRef<GPUBuffer>();
const camera = useRef({ reset: () => {}, update: (e: MouseEvent) => {} });
const init = async () => {
if (!canvasRef.current) return;
const canvas = canvasRef.current;
Expand All @@ -104,13 +67,14 @@ function useInit(canvasRef: { current: CanvasRefType }) {
alphaMode: 'opaque',
});

const triangleTexture = makeBuffer(device);

uniBuffer.current = device.createBuffer({
const uniBuffer = device.createBuffer({
size: 64 * 3,
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
})

const triangleMesh = makeTriangle(device, uniBuffer);
camera.current = makeCamera(device, uniBuffer);

const bindGroupLayout = device.createBindGroupLayout({
entries: [
{
Expand All @@ -127,7 +91,7 @@ function useInit(canvasRef: { current: CanvasRefType }) {
{
binding: 0,
resource: {
buffer: uniBuffer.current
buffer: uniBuffer
}
}
]
Expand All @@ -144,7 +108,7 @@ function useInit(canvasRef: { current: CanvasRefType }) {
module: device.createShaderModule({
code: fragmentShader
}),
buffers: [triangleTexture.bufferLayout]
buffers: [triangleMesh.bufferLayout]
},
fragment: {
entryPoint: "fs_main",
Expand All @@ -154,21 +118,33 @@ function useInit(canvasRef: { current: CanvasRefType }) {
targets: [{ format }]
}
})

cleanup.current = startPipeline(
device,
context,
pipeline,
bindGroup,
triangleTexture.buffer,
uniBuffer.current,

triangleMesh
);
}

useEffect(() => {
init();
return cleanup.current;
}, [canvasRef.current])

return {
handleClick(e: MouseEvent<HTMLCanvasElement>) {
canvasRef.current?.requestPointerLock();
},
handleMouseOut(e: MouseEvent<HTMLCanvasElement>) {
camera.current.reset();
},
handleMouseMove(e: MouseEvent<HTMLCanvasElement>) {
if(!document.pointerLockElement) return;
camera.current.update(e);
}
}
}

export default useInit;

0 comments on commit e3719ea

Please sign in to comment.