Skip to content

Commit

Permalink
Started working on the code-editor
Browse files Browse the repository at this point in the history
  • Loading branch information
iwoplaza committed Jul 9, 2024
1 parent f01dcc4 commit 138999f
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 2 deletions.
2 changes: 2 additions & 0 deletions apps/wigsill-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
"preview": "vite preview"
},
"dependencies": {
"@monaco-editor/react": "^4.6.0",
"classnames": "^2.5.1",
"dat.gui": "^0.7.9",
"jotai": "^2.8.4",
"jotai-location": "^0.5.5",
"monaco-editor": "^0.50.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"typed-binary": "^4.0.0",
Expand Down
11 changes: 11 additions & 0 deletions apps/wigsill-examples/src/CodeEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Editor from '@monaco-editor/react';

export function CodeEditor() {
return (
<Editor
height="90vh"
defaultLanguage="typescript"
defaultValue="// some comment"
/>
);
}
2 changes: 2 additions & 0 deletions apps/wigsill-examples/src/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { CodeResolver } from './CodeResolver';
import { CodeEditor } from './CodeEditor';

export function Home() {
return (
<div className="px-6 py-4">
<p>Edit `sampleShader.ts` and see the change in resolved code.</p>
<CodeResolver />
<CodeEditor />
</div>
);
}
192 changes: 192 additions & 0 deletions apps/wigsill-examples/src/examples/BasicTriangleExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import * as dat from 'dat.gui';
import { WGSLRuntime } from 'wigsill';
import { ProgramBuilder, makeArena, u32, wgsl } from 'wigsill';

import { useExampleWithCanvas } from '../common/useExampleWithCanvas';
import { useEffect } from 'react';

async function init(gui: dat.GUI, canvas: HTMLCanvasElement) {
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter!.requestDevice();
const runtime = new WGSLRuntime(device);

const xSpanData = wgsl.memory(u32).alias('x-span');
const ySpanData = wgsl.memory(u32).alias('y-span');

const mainArena = makeArena({
bufferBindingType: 'uniform',
memoryEntries: [xSpanData, ySpanData],
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.UNIFORM,
});

const context = canvas.getContext('webgpu') as GPUCanvasContext;

const devicePixelRatio = window.devicePixelRatio;
canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();

context.configure({
device,
format: presentationFormat,
alphaMode: 'premultiplied',
});

const mainCode = wgsl`
struct VertexOutput {
@builtin(position) pos: vec4f,
@location(0) uv: vec2f,
}
@vertex
fn main_vert(
@builtin(vertex_index) VertexIndex: u32
) -> VertexOutput {
var pos = array<vec2f, 4>(
vec2(0.5, 0.5), // top-right
vec2(-0.5, 0.5), // top-left
vec2(0.5, -0.5), // bottom-right
vec2(-0.5, -0.5) // bottom-left
);
var uv = array<vec2f, 4>(
vec2(1., 1.), // top-right
vec2(0., 1.), // top-left
vec2(1., 0.), // bottom-right
vec2(0., 0.) // bottom-left
);
var output: VertexOutput;
output.pos = vec4f(pos[VertexIndex], 0.0, 1.0);
output.uv = uv[VertexIndex];
return output;
}
@fragment
fn main_frag(
@builtin(position) Position: vec4f,
@location(0) uv: vec2f,
) -> @location(0) vec4f {
let red = floor(uv.x * f32(${xSpanData})) / f32(${xSpanData});
let green = floor(uv.y * f32(${ySpanData})) / f32(${ySpanData});
return vec4(red, green, 0.5, 1.0);
}
`;

const program = new ProgramBuilder(runtime, mainCode).build({
bindingGroup: 0,
shaderStage: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
arenas: [mainArena],
});

const shaderModule = device.createShaderModule({
code: program.code,
});

const pipeline = device.createRenderPipeline({
layout: device.createPipelineLayout({
bindGroupLayouts: [program.bindGroupLayout],
}),
vertex: {
module: shaderModule,
entryPoint: 'main_vert',
},
fragment: {
module: shaderModule,
entryPoint: 'main_frag',
targets: [
{
format: presentationFormat,
},
],
},
primitive: {
topology: 'triangle-strip',
},
});

/// UI

const state = {
xSpan: 16,
ySpan: 16,
};

xSpanData.write(runtime, state.xSpan);
ySpanData.write(runtime, state.ySpan);

gui.add(state, 'xSpan', 1, 16).onChange(() => {
xSpanData.write(runtime, state.xSpan);
});
gui.add(state, 'ySpan', 1, 16).onChange(() => {
ySpanData.write(runtime, state.ySpan);
});

let running = true;

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

const renderPassDescriptor: GPURenderPassDescriptor = {
colorAttachments: [
{
view: textureView,
clearValue: [0, 0, 0, 1],
loadOp: 'clear',
storeOp: 'store',
},
],
};

const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setBindGroup(0, program.bindGroup);
passEncoder.draw(4);
passEncoder.end();

device.queue.submit([commandEncoder.finish()]);

if (running) {
requestAnimationFrame(frame);
}
}

requestAnimationFrame(frame);

return {
dispose() {
running = false;
},
};
}

export function BasicTriangleExample() {
const canvasRef = useExampleWithCanvas(init);

useEffect(() => {
import('wigsill').then((wigsill) => {
const require = (moduleKey: string) => {
if (moduleKey === 'wigsill') {
return wigsill;
}
throw new Error(`Module ${moduleKey} not found.`);
};

const mod = Function(`
return async (require) => {
const { wgsl } = require('wigsill');
return 'bruh';
};
`);

const result: Promise<string> = mod()(require);

result.then((value) => {
console.log(value);
});
}, []);
});

return <canvas className="w-full h-screen" ref={canvasRef}></canvas>;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as dat from 'dat.gui';
import { useExampleWithCanvas } from '../common/useExampleWithCanvas';
import { createRef, RefObject } from 'react';

import { useExampleWithCanvas } from '../common/useExampleWithCanvas';

function init(videoRef: RefObject<HTMLVideoElement>) {
return async function (gui: dat.GUI, canvas: HTMLCanvasElement) {
const adapter = await navigator.gpu.requestAdapter();
Expand Down Expand Up @@ -200,6 +201,7 @@ fn frag_main(@location(0) fragUV : vec2f) -> @location(0) vec4f {
export function CameraThresholdingExample() {
const videoRef: RefObject<HTMLVideoElement> = createRef();
const canvasRef = useExampleWithCanvas(init(videoRef));
// const canvasRef = useExampleWithCanvas(useCallback(() => init(videoRef), []));
const [width, height] = [500, 375];

return (
Expand Down
7 changes: 6 additions & 1 deletion apps/wigsill-examples/src/examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { CameraThresholdingExample } from './CameraThresholdingExample';
import { BasicTriangleExample } from './BasicTriangleExample';
import { GradientTilesExample } from './GradientTilesExample';
import { CameraThresholdingExample } from './CameraThresholdingExample';

export const examples = {
'basic-triangle': {
label: 'Basic Triangle',
component: BasicTriangleExample,
},
'gradient-tiles': {
label: 'Gradient tiles',
component: GradientTilesExample,
Expand Down
36 changes: 36 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 138999f

Please sign in to comment.