.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gallery/triangle.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_gallery_triangle.py: Triangle -------- Example use of the wgpu API to draw a triangle. The triangle is a classic example representing the simplest possible visualisation because it does not need buffers or textures. The same example in other languages / API's: * Rust wgpu: https://github.com/gfx-rs/wgpu-rs/blob/master/examples/hello-triangle/main.rs * C wgpu: https://github.com/gfx-rs/wgpu/blob/master/examples/triangle/main.c * Python Vulkan: https://github.com/realitix/vulkan/blob/master/example/contribs/example_glfw.py This example is set up so it can be run with any canvas. Running this file as a script will use rendercanvas with the auto-backend. .. GENERATED FROM PYTHON SOURCE LINES 21-26 .. code-block:: Python from typing import Callable import wgpu .. GENERATED FROM PYTHON SOURCE LINES 27-63 .. code-block:: Python def setup_drawing_sync( context, power_preference="high-performance", limits=None, format=None ) -> Callable: """Setup to draw a triangle on the given context. Returns the draw function. """ adapter = wgpu.gpu.request_adapter_sync(power_preference=power_preference) device = adapter.request_device_sync(required_limits=limits) pipeline_kwargs = get_render_pipeline_kwargs(context, device, format) render_pipeline = device.create_render_pipeline(**pipeline_kwargs) return get_draw_function(context, device, render_pipeline, asynchronous=False) async def setup_drawing_async(context, limits=None, format=None) -> Callable: """Setup to async-draw a triangle on the given context. Returns the draw function. """ adapter = await wgpu.gpu.request_adapter_async(power_preference="high-performance") device = await adapter.request_device_async(required_limits=limits) pipeline_kwargs = get_render_pipeline_kwargs(context, device, format) render_pipeline = await device.create_render_pipeline_async(**pipeline_kwargs) return get_draw_function(context, device, render_pipeline, asynchronous=True) .. GENERATED FROM PYTHON SOURCE LINES 64-136 .. code-block:: Python def get_render_pipeline_kwargs( context, device, render_texture_format ) -> wgpu.RenderPipelineDescriptor: if render_texture_format is None: render_texture_format = context.get_preferred_format(device.adapter) context.configure(device=device, format=render_texture_format) vert_shader = device.create_shader_module(code=shader_source) frag_shader = device.create_shader_module(code=shader_source) pipeline_layout = device.create_pipeline_layout(bind_group_layouts=[]) return wgpu.RenderPipelineDescriptor( layout=pipeline_layout, vertex=wgpu.VertexState( module=vert_shader, entry_point="vs_main", ), depth_stencil=None, multisample=None, fragment=wgpu.FragmentState( module=frag_shader, entry_point="fs_main", targets=[ wgpu.ColorTargetState( format=render_texture_format, blend={"color": {}, "alpha": {}}, ) ], ), ) def get_draw_function( context, device: wgpu.GPUDevice, render_pipeline: wgpu.GPURenderPipeline, *, asynchronous: bool, ) -> Callable: def draw_frame_sync(): current_texture = context.get_current_texture() command_encoder = device.create_command_encoder() render_pass = command_encoder.begin_render_pass( color_attachments=[ wgpu.RenderPassColorAttachment( view=current_texture.create_view(), resolve_target=None, clear_value=(0, 0, 0, 1), load_op="clear", store_op="store", ) ], ) render_pass.set_pipeline(render_pipeline) # render_pass.set_bind_group(0, no_bind_group) render_pass.draw(3, 1, 0, 0) render_pass.end() device.queue.submit([command_encoder.finish()]) async def draw_frame_async(): draw_frame_sync() # nothing async here if asynchronous: return draw_frame_async else: return draw_frame_sync .. GENERATED FROM PYTHON SOURCE LINES 137-184 .. code-block:: Python shader_source = """ struct VertexInput { @builtin(vertex_index) vertex_index : u32, }; struct VertexOutput { @location(0) color : vec4, @builtin(position) pos: vec4, }; @vertex fn vs_main(in: VertexInput) -> VertexOutput { var positions = array, 3>( vec2(0.0, -0.5), vec2(0.5, 0.5), vec2(-0.5, 0.75), ); var colors = array, 3>( // srgb colors vec3(1.0, 1.0, 0.0), vec3(1.0, 0.0, 1.0), vec3(0.0, 1.0, 1.0), ); let index = i32(in.vertex_index); var out: VertexOutput; out.pos = vec4(positions[index], 0.0, 1.0); out.color = vec4(colors[index], 1.0); return out; } @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { let physical_color = pow(in.color.rgb, vec3(2.2)); // gamma correct return vec4(physical_color, in.color.a); } """ if __name__ == "__main__": from rendercanvas.auto import RenderCanvas, loop canvas = RenderCanvas(size=(640, 480), title="wgpu triangle example") context = canvas.get_wgpu_context() draw_frame = setup_drawing_sync(context) canvas.request_draw(draw_frame) loop.run() .. _sphx_glr_download_gallery_triangle.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: triangle.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: triangle.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: triangle.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_ .. only:: html Interactive example =================== This uses Pyodide. If this does not work, your browser may not have sufficient support for wasm/pyodide/wgpu (check your browser dev console). Stdout (print statements) will also appear in the browser console. .. raw:: html