From 676231e0d8ffdb1e2a69f97c4a87c8c8d75ea5f5 Mon Sep 17 00:00:00 2001 From: abux Date: Fri, 10 Jul 2026 17:22:28 +0100 Subject: [PATCH] window shall be... colored --- src/component/mesh.zig | 0 src/component/root.zig | 4 + src/component/shape.zig | 0 src/plugin.zig | 15 ++- src/resource/cache.zig | 16 ++++ src/resource/render_queue.zig | 13 +++ src/system/device.zig | 5 +- src/system/frame.zig | 132 ++++++++++++++++++++++++++- src/template/camera_render_queue.zig | 1 - src/template/registry.zig | 6 +- 10 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 src/component/mesh.zig create mode 100644 src/component/shape.zig diff --git a/src/component/mesh.zig b/src/component/mesh.zig new file mode 100644 index 0000000..e69de29 diff --git a/src/component/root.zig b/src/component/root.zig index d193c16..19d1dfa 100644 --- a/src/component/root.zig +++ b/src/component/root.zig @@ -4,3 +4,7 @@ pub const Camera = @import("camera.zig"); // --- MATERIALS --- pub const PBRMaterial = @import("pbr_material.zig"); pub const UnlitMaterial = @import("unlit_material.zig"); + +// --- MODEL --- +pub const Mesh = @import("mesh.zig"); +pub const Shape = @import("shape.zig"); diff --git a/src/component/shape.zig b/src/component/shape.zig new file mode 100644 index 0000000..e69de29 diff --git a/src/plugin.zig b/src/plugin.zig index 502ab34..b0288d8 100644 --- a/src/plugin.zig +++ b/src/plugin.zig @@ -1,6 +1,7 @@ //! ---------------------------------------------------- //! ---------------------------------------------------- +const std = @import("std"); const App = @import("app"); const system = @import("system/root.zig"); const resource = @import("resource/root.zig"); @@ -31,6 +32,9 @@ fn build( try ctx.app.resources.set(resource.RenderQueue.init(ctx.app.alloc)); { // TEST + try ctx.app.world.spawn(.{ + component.Camera{}, + }); try ctx.app.world.spawn(.{ component.PBRMaterial{}, }); @@ -47,6 +51,7 @@ fn build( system.frame.begin, system.frame.prepare, + system.frame.draw, }); // --- DEINIT --- @@ -55,9 +60,13 @@ fn build( struct { // TODO: Clean this shit up 🥀 pub fn sys(_ctx: App.scheduler.Context) !void { - if (_ctx.app.resources.getPtr(resource.Cache)) |cache| { - cache.deinit(); - } + const res = try _ctx.app.resources.getMany(struct { + cache: *resource.Cache, + render_queue: *resource.RenderQueue, + }); + + res.cache.deinit(); + res.render_queue.deinit(); } }.sys, diff --git a/src/resource/cache.zig b/src/resource/cache.zig index 43bfb60..1f16785 100644 --- a/src/resource/cache.zig +++ b/src/resource/cache.zig @@ -20,6 +20,15 @@ pub const ShaderID = union(enum) { /// ---------------------------------------------------- pub const PipelineKey = struct { shader: ShaderID, + + pub fn format( + self: @This(), + writer: *std.Io.Writer, + ) std.Io.Writer.Error!void { + try writer.print("shader({s})", .{ + @tagName(self.shader), + }); + } }; // @@ -48,6 +57,13 @@ pub fn deinit(self: *Self) void { } } + { // PIPELINES + var it = self.pipelines.iterator(); + while (it.next()) |entry| { + wgpu.wgpuRenderPipelineRelease(entry.value.*); + } + } + self.shaders.deinit(); self.pipelines.deinit(); } diff --git a/src/resource/render_queue.zig b/src/resource/render_queue.zig index fc2cf66..46fd065 100644 --- a/src/resource/render_queue.zig +++ b/src/resource/render_queue.zig @@ -24,6 +24,10 @@ pub fn init(alloc: std.mem.Allocator) Self { /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn deinit(self: *Self) void { + for (self.data.items) |*queue| { + queue.deinit(); + } + self.data.deinit(self.alloc); } @@ -32,3 +36,12 @@ pub fn deinit(self: *Self) void { pub fn clear(self: *Self) void { self.data.clearRetainingCapacity(); } + +/// ---------------------------------------------------- +/// ---------------------------------------------------- +pub fn append( + self: *Self, + queue: CameraRenderQueue, +) !void { + try self.data.append(self.alloc, queue); +} diff --git a/src/system/device.zig b/src/system/device.zig index 8e30439..3afff2c 100644 --- a/src/system/device.zig +++ b/src/system/device.zig @@ -72,7 +72,7 @@ pub fn init(ctx: App.scheduler.Context) !void { } // --- DEBUG LIMITS --- - std.debug.print("\x1b[35m┏━ ADAPTER LIMITS ━┓\x1b[0m\n", .{}); + std.debug.print("\x1b[35m┏━ ADAPTER LIMITS\x1b[0m\n", .{}); std.debug.print("\x1b[35m┃\x1b[0m Texture Dimentions: ({})1D, ({})2D, ({})3D, ({})Array Layers\n", .{ limits.maxTextureDimension1D, limits.maxTextureDimension2D, @@ -82,7 +82,7 @@ pub fn init(ctx: App.scheduler.Context) !void { std.debug.print("\x1b[35m┗━\x1b[0m\n", .{}); // --- DEBUG INFO --- - std.debug.print("\x1b[35m┏━ ADAPTER INFO ━┓\x1b[0m\n", .{}); + std.debug.print("\x1b[35m┏━ ADAPTER INFO\x1b[0m\n", .{}); std.debug.print( "\x1b[35m┃\x1b[0m Device: {s}\n" ++ "\x1b[35m┃\x1b[0m Backend: {s}\n", @@ -143,6 +143,7 @@ pub fn init(ctx: App.scheduler.Context) !void { .format = caps.formats[0], .width = res.window.width, .height = res.window.height, + .usage = wgpu.WGPUTextureUsage_RenderAttachment, }, ); } diff --git a/src/system/frame.zig b/src/system/frame.zig index a2d41de..ddf5bb9 100644 --- a/src/system/frame.zig +++ b/src/system/frame.zig @@ -10,6 +10,7 @@ const component = @import("../component/root.zig"); const Window = @import("../resource/window.zig"); const Device = @import("../resource/device.zig"); const RenderFrame = @import("../resource/render_frame.zig"); +const RenderQueue = @import("../resource/render_queue.zig"); const Cache = @import("../resource/cache.zig"); const PBRShader = @import("../renderer.zig").PBRShader; @@ -66,6 +67,7 @@ pub fn end(ctx: App.scheduler.Context) !void { window: *Window, device: *Device, render_frame: *RenderFrame, + render_queue: *RenderQueue, }); if (res.render_frame.encoder) |encoder| { @@ -103,11 +105,71 @@ pub fn end(ctx: App.scheduler.Context) !void { // --- RESET FRAME --- res.render_frame.reset(); + res.render_queue.clear(); // --- DEBUG --- sdl.SDL_Delay(2000); // TODO: Remove } +// TODO: Clean this shit up... + +/// ---------------------------------------------------- +/// ---------------------------------------------------- +pub fn draw(ctx: App.scheduler.Context) !void { + // --- GET RESOURCES --- + const res = try ctx.app.resources.getMany(struct { + window: *Window, + device: *Device, + cache: *Cache, + render_frame: *RenderFrame, + render_queue: *RenderQueue, + }); + + // --- QUERY --- + var query = ctx.app.world.query(struct { + camera: *component.Camera, + }, .{}); + while (query.next()) |e| { + _ = e; + try res.render_queue.append( + .init(ctx.app.alloc), + ); + + // TODO: Add opaques Mesh etc + + // const camera_queue = &res.render_queue.data.items[res.render_queue.data.items.len - 1]; + + // try camera_queue.opaques.append( + // res.render_queue.alloc, + // undefined, + // ); + } + + for (res.render_queue.data.items) |camera_queue| { + // --- RENDERPASS --- + const pass = wgpu.wgpuCommandEncoderBeginRenderPass(res.render_frame.encoder, &wgpu.WGPURenderPassDescriptor{ + .colorAttachmentCount = 1, + .colorAttachments = &wgpu.WGPURenderPassColorAttachment{ + .view = res.render_frame.color_view, // TODO: Color View + .loadOp = wgpu.WGPULoadOp_Clear, + .storeOp = wgpu.WGPUStoreOp_Store, + .clearValue = .{ + .r = 0.2, + .g = 0.2, + .b = 0.8, + .a = 1.0, + }, + .depthSlice = wgpu.WGPU_DEPTH_SLICE_UNDEFINED, + }, + }); + defer { + wgpu.wgpuRenderPassEncoderEnd(pass); + wgpu.wgpuRenderPassEncoderRelease(pass); + } + _ = camera_queue; + } +} + /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn prepare(ctx: App.scheduler.Context) !void { @@ -116,8 +178,10 @@ pub fn prepare(ctx: App.scheduler.Context) !void { window: *Window, device: *Device, cache: *Cache, + render_frame: *RenderFrame, }); + // TODO: Clean this shit up | Latr go over each shader, then create pipelines // 1) Prepare Shaders // 2) Prepare Pipelines @@ -171,12 +235,78 @@ pub fn prepare(ctx: App.scheduler.Context) !void { ); // TODO: Only show on debug mode - std.debug.print("\x1b[35m┣━ SHADER\x1b[0m {s}\n", .{@tagName( + std.debug.print("\x1b[35m┏━ MATERIAL\x1b[0m\n", .{}); + std.debug.print("\x1b[35m┃ Shader: \x1b[0m {s}\n", .{@tagName( shader_id, )}); } + // --- PIPELINE KEY --- + const pipe_key: Cache.PipelineKey = .{ + .shader = shader_id, + }; + // TODO: Pipelines + if (!res.cache.pipelines.contains(pipe_key)) { + // --- GET SHADER MODULE --- + const shader_module = res.cache.shaders.getPtr( + pipe_key.shader, + ) orelse return error.NoShader; + + // --- PIPELINE --- + const pipe = wgpu.wgpuDeviceCreateRenderPipeline( + res.device.raw, + &wgpu.WGPURenderPipelineDescriptor{ + .vertex = .{ + .module = shader_module.*, + .entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN }, + }, + .fragment = &wgpu.WGPUFragmentState{ + .module = shader_module.*, + .entryPoint = .{ .data = "fs_main", .length = wgpu.WGPU_STRLEN }, + + .targetCount = 1, + .targets = &wgpu.WGPUColorTargetState{ + .format = wgpu.wgpuTextureGetFormat(res.render_frame.surface_tex.texture), + .blend = &wgpu.WGPUBlendState{ + .color = .{ + .srcFactor = wgpu.WGPUBlendFactor_SrcAlpha, + .dstFactor = wgpu.WGPUBlendFactor_OneMinusSrcAlpha, + .operation = wgpu.WGPUBlendOperation_Add, + }, + .alpha = .{ + .srcFactor = wgpu.WGPUBlendFactor_Zero, + .dstFactor = wgpu.WGPUBlendFactor_One, + .operation = wgpu.WGPUBlendOperation_Add, + }, + }, + .writeMask = wgpu.WGPUColorWriteMask_All, + }, + }, + .primitive = .{ // TODO: Get these from material config or sum + .topology = wgpu.WGPUPrimitiveTopology_TriangleList, + .stripIndexFormat = wgpu.WGPUIndexFormat_Undefined, + .frontFace = wgpu.WGPUFrontFace_CCW, + .cullMode = wgpu.WGPUCullMode_Back, + }, + .multisample = .{ + .count = 1, + .mask = ~@as(u32, 0), + }, + }, + ) orelse return error.RenderPipeline; + errdefer wgpu.wgpuRenderPipelineRelease(pipe); + + // --- ADD NEW -- + try res.cache.pipelines.put( + pipe_key, + pipe, + ); + + // TODO: Only show on debug mode + std.debug.print("\x1b[35m┃ Pipeline: \x1b[0m{f}\n", .{pipe_key}); + std.debug.print("\x1b[35m┗━ \x1b[0m\n", .{}); + } } } } diff --git a/src/template/camera_render_queue.zig b/src/template/camera_render_queue.zig index 2498ada..121369a 100644 --- a/src/template/camera_render_queue.zig +++ b/src/template/camera_render_queue.zig @@ -40,4 +40,3 @@ pub fn clear(self: *Self) void { self.opaques.clearRetainingCapacity(); self.transparents.clearRetainingCapacity(); } - diff --git a/src/template/registry.zig b/src/template/registry.zig index 4be699c..29fab08 100644 --- a/src/template/registry.zig +++ b/src/template/registry.zig @@ -170,6 +170,8 @@ pub fn Registry( // LOOKUP // + // TODO: Change idx to handle.idx + /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn contains(self: Self, key: K) bool { @@ -186,8 +188,8 @@ pub fn Registry( /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn getPtr(self: *Self, key: K) ?*V { - const idx = self.lookup.get(key) orelse return null; - return &self.entries.items[idx].value; + const handle = self.lookup.get(key) orelse return null; + return &self.entries.items[@intCast(handle.idx)].value; } /// ----------------------------------------------------