Skip to content

Commit

Permalink
Cleanup, add example
Browse files Browse the repository at this point in the history
  • Loading branch information
mhochsteger committed Jan 14, 2025
1 parent 426ee4f commit e569b07
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 316 deletions.
144 changes: 144 additions & 0 deletions example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "47ea5096-89f7-40e7-8538-73ee285f3309",
"metadata": {},
"source": [
"## Hello world\n",
"\n",
"The code below draws a (hard-coded) triangle to the screen and contains the bare minimum to draw something with custom WebGPU shaders."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ebd100f7-36eb-4178-869a-5fade1604ce9",
"metadata": {},
"outputs": [],
"source": [
"import webgpu.jupyter\n",
"\n",
"shader_code = \"\"\"\n",
"\n",
"// Data structure which is the output of the vertex shader and the input of the fragment shader\n",
"struct FragmentInput {\n",
" @builtin(position) p: vec4<f32>,\n",
" @location(0) color: vec4<f32>,\n",
"};\n",
"\n",
"// Vertex shader, returns a FragmentInput object\n",
"@vertex\n",
"fn vertex_main(\n",
" @builtin(vertex_index) vertex_index : u32\n",
") -> FragmentInput {\n",
"\n",
" var pos = array<vec4f, 3>(\n",
" vec4f( 0.0, 0.5, 0., 1.),\n",
" vec4f(-0.5, -0.5, 0., 1.),\n",
" vec4f( 0.5, -0.5, 0., 1.)\n",
" );\n",
"\n",
" var color = array<vec4f, 3>(\n",
" vec4f(1., 0., 0., 1.),\n",
" vec4f(0., 1., 0., 1.),\n",
" vec4f(0., 0., 1., 1.)\n",
" );\n",
" \n",
" return FragmentInput( pos[vertex_index], color[vertex_index] );\n",
"}\n",
"\n",
"@fragment\n",
"fn fragment_main(input: FragmentInput) -> @location(0) vec4f {\n",
" return input.color;\n",
"}\n",
"\"\"\"\n",
"\n",
"\n",
"def draw_function_in_pyodide(data):\n",
" \"\"\"This function will be serialized and sent to the pyodide environment within the browser.\n",
" Packages like \"js\" or \"pyodide.ffi\" are not available in the usual python environment.\n",
" \"\"\"\n",
" # interface for the Javascript environment in the browser, provided by pyodide\n",
" import js\n",
" import pyodide.ffi\n",
"\n",
" # webgpu.jupyter initializes the pyodide environment as soon as you import it\n",
" from webgpu.jupyter import gpu\n",
"\n",
" # Some necessary data structures defined by the WebGPU standard\n",
" from webgpu.webgpu_api import (\n",
" CompareFunction,\n",
" DepthStencilState,\n",
" FragmentState,\n",
" PrimitiveState,\n",
" PrimitiveTopology,\n",
" TextureFormat,\n",
" VertexState,\n",
" )\n",
"\n",
" device = gpu.device\n",
"\n",
" # compile the shader code\n",
" # open the JS console (F12 in most browsers) to check for compile errors\n",
" shader_module = device.createShaderModule(data[\"shader_code\"])\n",
"\n",
" # Create the render pipeline object, this defines the used vertex and fragment shader and behaviour of depth buffer, output color format etc.\n",
" pipeline = device.createRenderPipeline(\n",
" device.createPipelineLayout([]),\n",
" vertex=VertexState(module=shader_module, entryPoint=\"vertex_main\"),\n",
" fragment=FragmentState(\n",
" module=shader_module,\n",
" entryPoint=\"fragment_main\",\n",
" targets=[gpu.color_target],\n",
" ),\n",
" primitive=PrimitiveState(topology=PrimitiveTopology.triangle_list),\n",
" depthStencil=DepthStencilState(\n",
" format=gpu.depth_format,\n",
" depthWriteEnabled=True,\n",
" depthCompare=CompareFunction.less,\n",
" ),\n",
" multisample=gpu.multisample,\n",
" )\n",
"\n",
" def render_function(t):\n",
" \"\"\"Render function, this function will be called every time a new frame is requested\"\"\"\n",
" encoder = gpu.device.createCommandEncoder()\n",
" render_pass = gpu.begin_render_pass(encoder)\n",
" render_pass.setPipeline(pipeline)\n",
" render_pass.draw(3)\n",
" render_pass.end()\n",
" gpu.device.queue.submit([encoder.finish()])\n",
"\n",
" render_function = pyodide.ffi.create_proxy(render_function)\n",
" gpu.input_handler.render_function = render_function\n",
" js.requestAnimationFrame(render_function)\n",
"\n",
"\n",
"# Call draw_function_in_pyodide with the shader code as argument within the pyodide environment\n",
"webgpu.jupyter.DrawCustom({\"shader_code\": shader_code}, draw_function_in_pyodide)\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.1"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit e569b07

Please sign in to comment.