render-zig

A 3D rendering engine written in Zig
git clone git://git.christianermann.dev/render-zig
Log | Files | Refs

commit a51c3d95e2075ca372cc57e66951f0445156eb13
parent 90673dac563c9dd955aa7c15b186d7fb028c8735
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sat, 27 Apr 2024 21:56:23 -0400

Render triangle using buffers

Diffstat:
Msrc/main.zig | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/src/main.zig b/src/main.zig @@ -327,6 +327,117 @@ const DefaultRenderPipeline = struct { } }; +const f32x3 = @Vector(3, f32); + +const UnlitRenderPipeline = struct { + gpu_pipeline: *gpu.RenderPipeline, + vtx_buffer: *gpu.Buffer, + idx_buffer: *gpu.Buffer, + + pub fn init(app: *App) UnlitRenderPipeline { + const triangle_vtx = [3]f32x3{ .{ 0.0, 0.5, 0.0 }, .{ -0.5, -0.5, 0.0 }, .{ 0.5, -0.5, 0.0 } }; + const vtx_buffer_descriptor = gpu.Buffer.Descriptor{ + .size = 3 * @sizeOf(f32x3), + .usage = .{ .vertex = true, .copy_dst = true }, + .mapped_at_creation = .false, + }; + const vtx_buffer = app.device.createBuffer(&vtx_buffer_descriptor); + app.queue.writeBuffer(vtx_buffer, 0, &triangle_vtx); + + const vtx_attributes = [_]gpu.VertexAttribute{ + .{ .format = .float32x3, .shader_location = 0, .offset = 0 }, + }; + const vtx_buffer_layout = gpu.VertexBufferLayout.init(.{ + .array_stride = @sizeOf(f32x3), + .step_mode = .vertex, + .attributes = &vtx_attributes, + }); + + const triangle_idx = [3]u32{ 0, 1, 2 }; + const idx_buffer_descriptor = gpu.Buffer.Descriptor{ + .size = 3 * @sizeOf(u32), + .usage = .{ .index = true, .copy_dst = true }, + .mapped_at_creation = .false, + }; + const idx_buffer = app.device.createBuffer(&idx_buffer_descriptor); + app.queue.writeBuffer(idx_buffer, 0, &triangle_idx); + + const vs = + \\ struct VertexInput { + \\ @location(0) position: vec3<f32>, + \\ }; + \\ + \\ @vertex fn main(in: VertexInput) -> @builtin(position) vec4<f32> { + \\ return vec4<f32>(in.position, 1.0); + \\ } + ; + const vs_module = app.device.createShaderModuleWGSL("default vertex shader", vs); + defer vs_module.release(); + + const vertex = gpu.VertexState.init(.{ + .module = vs_module, + .entry_point = "main", + .buffers = &.{vtx_buffer_layout}, + }); + + const fs = + \\ @fragment fn main() -> @location(0) vec4<f32> { + \\ return vec4<f32>(1.0, 0.0, 0.0, 1.0); + \\ } + ; + const fs_module = app.device.createShaderModuleWGSL("default fragment shader", fs); + defer fs_module.release(); + + const blend: gpu.BlendState = .{}; + const color_target = gpu.ColorTargetState{ + .format = app.swap_chain.format, + .blend = &blend, + .write_mask = gpu.ColorWriteMaskFlags.all, + }; + const fragment = gpu.FragmentState.init(.{ + .module = fs_module, + .entry_point = "main", + .targets = &.{color_target}, + }); + + const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ + .label = "default render pipeline", + .fragment = &fragment, + .layout = null, + .depth_stencil = null, + .vertex = vertex, + .multisample = .{}, + .primitive = .{ + .topology = .triangle_list, + .front_face = .ccw, + .cull_mode = .back, + }, + }; + + return .{ + .gpu_pipeline = app.device.createRenderPipeline(&pipeline_descriptor), + .vtx_buffer = vtx_buffer, + .idx_buffer = idx_buffer, + }; + } + + pub fn frame(ptr: *anyopaque, pass: *gpu.RenderPassEncoder) void { + const self: *UnlitRenderPipeline = @ptrCast(@alignCast(ptr)); + pass.setPipeline(self.gpu_pipeline); + + pass.setVertexBuffer(0, self.vtx_buffer, 0, @sizeOf(f32x3) * 3); + pass.setIndexBuffer(self.idx_buffer, .uint32, 0, @sizeOf(u32) * 3); + pass.drawIndexed(3, 1, 0, 0, 0); + } + + pub fn pipeline(self: *UnlitRenderPipeline) RenderPipeline { + return .{ + .ptr = self, + .frameFn = frame, + }; + } +}; + pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; const allocator = gpa.allocator(); @@ -335,7 +446,7 @@ pub fn main() !void { try app.init(allocator); defer app.deinit(); - var drp = DefaultRenderPipeline.init(&app); + var drp = UnlitRenderPipeline.init(&app); const pipelines = [_]RenderPipeline{drp.pipeline()};