Skip to content

Commit

Permalink
Setup WebGPU render pipeline with GPU buffers, bind groups, encoders,…
Browse files Browse the repository at this point in the history
… vertex/fragment shaders, normalized data, etc.
  • Loading branch information
ZainGS committed Aug 13, 2024
1 parent 6c5526a commit 8dda2cb
Show file tree
Hide file tree
Showing 13 changed files with 286 additions and 153 deletions.
138 changes: 50 additions & 88 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,128 +1,90 @@
// src/main.ts

// src/main.ts
import { SceneGraph } from './scene-graph/scene-graph';
import { Rectangle } from './scene-graph/rectangle';
import { Circle } from './scene-graph/circle';
import { WebGPURenderer } from './renderer/webgpu-renderer';
import { WebGPURenderStrategy } from './renderer/webgpu-render-strategy';
import { CanvasRenderer } from './renderer/canvas-renderer';
import { CanvasRenderStrategy } from './renderer/canvas-render-strategy';

async function main() {
// Set up the canvas and WebGPURenderer
async function webGPURendering() {
// Set up the canvas
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
canvas.width = 800;
canvas.height = 600;

// Create the WebGPU renderer
const webgpuRenderer = new WebGPURenderer(canvas);

// Initialize the WebGPU context and pipeline
await webgpuRenderer.initialize();

// Get the device and pipeline from the WebGPU renderer
const device = webgpuRenderer.getDevice();
const pipeline = webgpuRenderer.getPipeline();

// Create the WebGPU render strategy
const webGPURenderStrategy = new WebGPURenderStrategy(device, pipeline);
const webgpuRenderStrategy = new WebGPURenderStrategy(device, pipeline, canvas);

// Create the scene graph
const sceneGraph = new SceneGraph(webGPURenderStrategy);

// Create a rectangle with the WebGPU render strategy
const sceneGraph = new SceneGraph(webgpuRenderStrategy);

const rect = new Rectangle(webGPURenderStrategy, 100, 50, 'red', 'black', 2);
// Create a dynamic rectangle
const rect = new Rectangle(webgpuRenderStrategy, 200, 100, { r: 0, g: 0, b: 1, a: 1 }, { r: 0, g: 0, b: 0, a: 1 }, 2);
rect.x = 150;
rect.y = 100;
rect.y = 150;

// Add the rectangle to the scene graph
sceneGraph.root.addChild(rect);
// Create a dynamic circle
const circle = new Circle(webgpuRenderStrategy, 50, { r: 1, g: 0, b: 0, a: 1 }, { r: 0, g: 0, b: 0, a: 1 }, 2);
circle.x = 400;
circle.y = 300;

// Add the shapes to the scene graph
sceneGraph.root.addChild(rect);
sceneGraph.root.addChild(circle);

// Start the rendering loop
function renderLoop() {
webgpuRenderer.render(sceneGraph);
requestAnimationFrame(renderLoop);
}

renderLoop();
}

main();

/*
///////////////////////////////////////////////////////////////////////////
CANVAS
///////////////////////////////////////////////////////////////////////////
import { SceneGraph } from './scene-graph/scene-graph';
import { Rectangle } from './scene-graph/rectangle';
import { CanvasRenderer } from './renderer/canvas-renderer';
import { CanvasRenderStrategy } from './renderer/canvas-render-strategy';
// Set up the canvas
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
canvas.width = 800;
canvas.height = 600;
// Create the scene graph
const sceneGraph = new SceneGraph();
// Create the canvas render strategy
const canvasRenderStrategy = new CanvasRenderStrategy();
// Create a rectangle
const rect = new Rectangle(canvasRenderStrategy, 100, 50, 'red', 'black', 2);
rect.x = 150;
rect.y = 100;
// Add a click event to change the color of the rectangle
rect.onClick = () => {
rect.fillColor = rect.fillColor === 'red' ? 'green' : 'red';
console.log("Rectangle clicked! Color changed.");
};
// Add the rectangle to the scene graph
sceneGraph.root.addChild(rect);
// Create the renderer
const renderer = new CanvasRenderer(canvas, sceneGraph);
// Start the rendering loop manually
renderer.start();
/////////////////////////////////////////////////////////////////////////////
WEBGPU
/////////////////////////////////////////////////////////////////////////////
// src/main.ts
import { SceneGraph } from './scene-graph/scene-graph';
import { Rectangle } from './scene-graph/rectangle';
import { WebGPURenderer } from './renderer/webgpu-renderer';
import { WebGPURenderStrategy } from './rendering/webgpu-render-strategy';
async function main() {
// Set up the canvas and WebGPURenderer
async function canvasRendering() {
// Set up the canvas
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const webgpuRenderer = new WebGPURenderer(canvas);
await webgpuRenderer.initialize();
canvas.width = 800;
canvas.height = 600;

const device = webgpuRenderer.getDevice();
const pipeline = webgpuRenderer.getPipeline();
// Create the canvas render strategy
const canvasRenderStrategy = new CanvasRenderStrategy();

// Create the scene graph
const sceneGraph = new SceneGraph();
const sceneGraph = new SceneGraph(canvasRenderStrategy);

// Create the WebGPU render strategy
const webGPURenderStrategy = new WebGPURenderStrategy(device, pipeline);
var red = {r:1,g:0,b:0,a:1};
var black = {r:0,g:0,b:0,a:1};

// Create a rectangle with the WebGPU render strategy
const rect = new Rectangle(webGPURenderStrategy, 100, 50, 'red', 'black', 2);
// Create a rectangle
const rect = new Rectangle(canvasRenderStrategy, 100, 50, red, black, 2);
rect.x = 150;
rect.y = 100;

// Add a click event to change the color of the rectangle
rect.onClick = () => {
rect.fillColor = rect.fillColor === red ? black : red;
console.log("Rectangle clicked! Color changed.");
};

// Add the rectangle to the scene graph
sceneGraph.root.addChild(rect);

// Start the rendering loop
function renderLoop() {
webgpuRenderer.render(sceneGraph);
requestAnimationFrame(renderLoop);
}
renderLoop();
}
// Create the renderer
const renderer = new CanvasRenderer(canvas, sceneGraph);

main();
// Start the rendering loop manually
renderer.start();
}

*/
//canvasRendering();
webGPURendering();
23 changes: 12 additions & 11 deletions src/renderer/canvas-render-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import { Rectangle } from '../scene-graph/rectangle';
import { Circle } from '../scene-graph/circle';
import { Line } from '../scene-graph/line';
import { Polygon } from '../scene-graph/polygon';
import { rgbaToCssString } from '../utils/color';

export class CanvasRenderStrategy implements RenderStrategy {
render(node: Node, ctxOrEncoder: CanvasRenderingContext2D | GPURenderPassEncoder, pipeline?: GPURenderPipeline): void {
render(node: Node, ctxOrEncoder: CanvasRenderingContext2D | GPURenderPassEncoder): void {
if (ctxOrEncoder instanceof CanvasRenderingContext2D) {
if (!node.visible) return;

Expand Down Expand Up @@ -41,28 +42,28 @@ export class CanvasRenderStrategy implements RenderStrategy {
}

private drawRectangle(rect: Rectangle, ctx: CanvasRenderingContext2D) {
if (rect.fillColor !== 'transparent') {
ctx.fillStyle = rect.fillColor;
if (rect.fillColor.a !== 0) {
ctx.fillStyle = rgbaToCssString(rect.fillColor);
ctx.fillRect(0, 0, rect.boundingBox!.width, rect.boundingBox!.height);
}

if (rect.strokeWidth > 0) {
ctx.strokeStyle = rect.strokeColor;
ctx.strokeStyle = rgbaToCssString(rect.strokeColor);
ctx.lineWidth = rect.strokeWidth;
ctx.strokeRect(0, 0, rect.boundingBox!.width, rect.boundingBox!.height);
}
}

private drawCircle(circle: Circle, ctx: CanvasRenderingContext2D) {
if (circle.fillColor !== 'transparent') {
ctx.fillStyle = circle.fillColor;
if (circle.fillColor.a !== 0) {
ctx.fillStyle = rgbaToCssString(circle.fillColor);
ctx.beginPath();
ctx.arc(circle.boundingBox!.width / 2, circle.boundingBox!.height / 2, circle.boundingBox!.width / 2, 0, Math.PI * 2);
ctx.fill();
}

if (circle.strokeWidth > 0) {
ctx.strokeStyle = circle.strokeColor;
ctx.strokeStyle = rgbaToCssString(circle.strokeColor);
ctx.lineWidth = circle.strokeWidth;
ctx.stroke();
}
Expand All @@ -72,7 +73,7 @@ export class CanvasRenderStrategy implements RenderStrategy {
ctx.beginPath();
ctx.moveTo(line.startX, line.startY);
ctx.lineTo(line.endX, line.endY);
ctx.strokeStyle = line.strokeColor;
ctx.strokeStyle = rgbaToCssString(line.strokeColor);
ctx.lineWidth = line.strokeWidth;
ctx.stroke();
}
Expand All @@ -89,13 +90,13 @@ export class CanvasRenderStrategy implements RenderStrategy {

ctx.closePath();

if (polygon.fillColor !== 'transparent') {
ctx.fillStyle = polygon.fillColor;
if (polygon.fillColor.a !== 0) {
ctx.fillStyle = rgbaToCssString(polygon.fillColor);
ctx.fill();
}

if (polygon.strokeWidth > 0) {
ctx.strokeStyle = polygon.strokeColor;
ctx.strokeStyle = rgbaToCssString(polygon.strokeColor);
ctx.lineWidth = polygon.strokeWidth;
ctx.stroke();
}
Expand Down
Loading

0 comments on commit 8dda2cb

Please sign in to comment.