From 68af5702785bacc1786d6243aabd6f21cffe2a55 Mon Sep 17 00:00:00 2001 From: Peter Li Date: Fri, 2 May 2025 08:51:10 -0700 Subject: [PATCH] added skybox objs --- engine/rend/src/sgpu/SkyboxSystem.zig | 148 +++++++++++++++++++ engine/rend/src/sgpu/embedded/skybox.obj | 40 +++++ engine/rend/src/sgpu/renderer.zig | 180 +++++++++++------------ 3 files changed, 276 insertions(+), 92 deletions(-) create mode 100644 engine/rend/src/sgpu/SkyboxSystem.zig create mode 100644 engine/rend/src/sgpu/embedded/skybox.obj diff --git a/engine/rend/src/sgpu/SkyboxSystem.zig b/engine/rend/src/sgpu/SkyboxSystem.zig new file mode 100644 index 0000000..e2a8ed2 --- /dev/null +++ b/engine/rend/src/sgpu/SkyboxSystem.zig @@ -0,0 +1,148 @@ +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + +allocator: std.mem.Allocator, + +device: *gpu.GPUDevice = undefined, + +skyboxMesh: ?rend.IndexedMesh = null, +skyboxTexture: ?*rend.Texture = null, +skyboxTextureName: ?core.Name = null, +skyboxPipeline: *gpu.GPUGraphicsPipeline = undefined, +skyboxColor: core.colors.Color = .{ .r = 71.0 / 256.0, .g = 200.0 / 256.0, .b = 1.0, .a = 1.0 }, + +skyboxMeshName: core.Name = core.DefineName("m_skybox"), + +sampler: *gpu.GPUSampler = undefined, + +pub fn create(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + self.* = .{ .allocator = allocator }; + + return self; +} + +pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void { + self.device = device; + + _ = try core.fs().installFileBytesMount("embedded:skybox_mesh.obj", @constCast(&skybox_mesh_obj), true); + + try assets.load( + assets.MakeImportRefOptions( + "Mesh", + "m_skybox", + .{ .path = "embedded:skybox_mesh.obj" }, + ), + ); + + try self.createPipeline(); +} + +fn createPipeline(self: *@This()) !void { + const ctx = rend.context(); + const vertex = try ctx.loadShader("skybox.vert", skybox_vert.LoadArgs); + const fragment = try ctx.loadShader("skybox.frag", skybox_frag.LoadArgs); + + var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); + pci.vertex_shader = vertex; + pci.fragment_shader = fragment; + + var attributes = try ctx.generateVertexAttributeList(); + defer attributes.deinit(); + + pci.vertex_input_state = .{ + .num_vertex_buffers = 1, + .vertex_buffer_descriptions = &[_]gpu.GPUVertexBufferDescription{ + .{ .slot = 0, .pitch = @sizeOf(rend.MeshVertex), .input_rate = .vertexinputrateVertex, .instance_step_rate = 0 }, + }, + .num_vertex_attributes = @intCast(attributes.items.len), + .vertex_attributes = @ptrCast(attributes.items.ptr), + }; + + pci.target_info.num_color_targets = 1; + pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ + .{ + .format = self.device.getGPUSwapchainTextureFormat(ctx.window), + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + }; + + pci.rasterizer_state.fill_mode = .fillmodeFill; + self.skyboxPipeline = self.device.createGPUGraphicsPipeline(&pci); + + self.sampler = self.device.createGPUSampler(&std.mem.zeroInit(gpu.GPUSamplerCreateInfo, .{ + .min_filter = .filterNearest, + .mag_filter = .filterNearest, + .mipmap_mode = .samplermipmapmodeNearest, + .address_mode_u = .sampleraddressmodeRepeat, + .address_mode_v = .sampleraddressmodeRepeat, + .address_mode_w = .sampleraddressmodeRepeat, + })); +} + +pub fn destroy(self: *@This()) void { + self.allocator.destroy(self); +} + +pub fn render(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = rend.context().swapchainTexture.?, + .clear_color = self.skyboxColor, + .load_op = .loadopClear, + .store_op = .storeopStore, + }); + + if (self.skyboxMesh == null) { + self.skyboxMesh = rend.getMeshByName(&self.skyboxMeshName); + } + + if (self.skyboxTexture == null) { + if (self.skyboxTextureName) |*name| { + self.skyboxTexture = rend.getTexture(name); + } + } + + if (self.skyboxTexture) |skyboxTexture| { + if (self.skyboxMesh) |skyboxMesh| { + const ctx = rend.context(); + const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); + + self.uploadSkyboxUniforms(cmd); + + renderpass.bindGPUVertexStorageBuffers(0, &ctx.ssboScene, 1); + renderpass.bindGPUVertexBuffers(0, &.{ .buffer = ctx.meshPool.vertexBuffer, .offset = 0 }, 1); + renderpass.bindGPUIndexBuffer(&.{ .buffer = ctx.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); + + renderpass.bindGPUGraphicsPipeline(self.skyboxPipeline); + renderpass.bindGPUFragmentSamplers(0, &.{ .texture = skyboxTexture.texture, .sampler = self.sampler }, 1); + renderpass.drawGPUIndexedPrimitives(skyboxMesh.index.size, 1, skyboxMesh.index.start, @intCast(skyboxMesh.vertex.start), 0); + renderpass.endGPURenderPass(); + } + } +} + +pub fn uploadSkyboxUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + _ = self; + + var data = std.mem.zeroes([@sizeOf(skybox_vert.Uniforms) / 8 + 1]usize); + const ptr: *skybox_vert.Uniforms = @ptrCast(@alignCast(&data)); + + if (rend.context().activeCamera) |camera| { + ptr.ViewProjection = @bitCast(camera.noTranslate); + } + + cmd.pushGPUVertexUniformData(0, &data, @sizeOf(skybox_vert.Uniforms)); +} + +const skybox_mesh_obj align(8) = @embedFile("embedded/skybox.obj").*; + +const std = @import("std"); +const core = @import("core"); +const rend = @import("../rend.zig"); +const sdl3 = @import("sdl3"); +const gpu = sdl3.gpu; +const assets = @import("assets"); + +const skybox_vert = @import("skybox.vert"); +const skybox_frag = @import("skybox.frag"); + +const renderer = rend.renderer; diff --git a/engine/rend/src/sgpu/embedded/skybox.obj b/engine/rend/src/sgpu/embedded/skybox.obj new file mode 100644 index 0000000..3a156f6 --- /dev/null +++ b/engine/rend/src/sgpu/embedded/skybox.obj @@ -0,0 +1,40 @@ +# Blender v3.6.4 OBJ File: '' +# www.blender.org +mtllib skybox.mtl +o Cube +v 100.000000 100.000000 -100.000000 +v 100.000000 -100.000000 -100.000000 +v 100.000000 100.000000 100.000000 +v 100.000000 -100.000000 100.000000 +v -100.000000 100.000000 -100.000000 +v -100.000000 -100.000000 -100.000000 +v -100.000000 100.000000 100.000000 +v -100.000000 -100.000000 100.000000 +vt 0.625000 0.500000 +vt 0.625000 0.750000 +vt 0.875000 0.750000 +vt 0.875000 0.500000 +vt 0.375000 0.750000 +vt 0.375000 1.000000 +vt 0.625000 1.000000 +vt 0.375000 0.000000 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.000000 +vt 0.125000 0.500000 +vt 0.125000 0.750000 +vt 0.375000 0.500000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +usemtl Material +s off +f 1/1/1 3/2/1 7/3/1 5/4/1 +f 4/5/2 8/6/2 7/7/2 3/2/2 +f 8/8/3 6/9/3 5/10/3 7/11/3 +f 6/12/4 8/13/4 4/5/4 2/14/4 +f 2/14/5 4/5/5 3/2/5 1/1/5 +f 6/9/6 2/14/6 1/1/6 5/10/6 diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 3f6d606..11348d6 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -63,16 +63,18 @@ pub const Renderer = struct { shadowDepthDebugOutput: *gpu.GPUTexture = undefined, shadowCastingPipeline: *gpu.GPUGraphicsPipeline = undefined, + skyboxSystem: *SkyboxSystem = undefined, + // transients DO NOT TOUCH swapchainTexture: ?*gpu.GPUTexture = undefined, - skyboxMesh: ?rend.IndexedMesh = null, - skyboxTexture: ?*rend.Texture = null, - skyboxTextureName: ?core.Name = null, - skyboxPipeline: *gpu.GPUGraphicsPipeline = undefined, - skyboxColor: core.colors.Color = .{ .r = 71.0 / 256.0, .g = 200.0 / 256.0, .b = 1.0, .a = 1.0 }, + // skyboxMesh: ?rend.IndexedMesh = null, + // skyboxTexture: ?*rend.Texture = null, + // skyboxTextureName: ?core.Name = null, + // skyboxPipeline: *gpu.GPUGraphicsPipeline = undefined, + // skyboxColor: core.colors.Color = .{ .r = 71.0 / 256.0, .g = 200.0 / 256.0, .b = 1.0, .a = 1.0 }, - skyboxMeshName: core.Name = core.DefineName("m_skybox"), + // skyboxMeshName: core.Name = core.DefineName("m_skybox"), pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); @@ -138,7 +140,7 @@ pub const Renderer = struct { self.debugDrawSys = try self.createRendererEngineObject(DebugDrawSystem); try self.createDirectionalShadowsPipeline(); - try self.setupSkybox(); + self.skyboxSystem = try self.createRendererEngineObject(SkyboxSystem); } pub fn createDirectionalShadowsPipeline(self: *@This()) !void { @@ -146,49 +148,49 @@ pub const Renderer = struct { try self.createShadowCastingPipeline(); } - pub fn setupSkybox(self: *@This()) !void { - try assets.load( - assets.MakeImportRefOptions( - "Mesh", - "m_skybox", - .{ .path = "meshes/skybox.obj" }, - ), - ); + // pub fn setupSkybox(self: *@This()) !void { + // try assets.load( + // assets.MakeImportRefOptions( + // "Mesh", + // "m_skybox", + // .{ .path = "meshes/skybox.obj" }, + // ), + // ); - try self.createSkyboxPipeline(); - } + // try self.createSkyboxPipeline(); + // } - pub fn createSkyboxPipeline(self: *@This()) !void { - const vertex = try self.loadShader("skybox.vert", skybox_vert.LoadArgs); - const fragment = try self.loadShader("skybox.frag", skybox_frag.LoadArgs); + // pub fn createSkyboxPipeline(self: *@This()) !void { + // const vertex = try self.loadShader("skybox.vert", skybox_vert.LoadArgs); + // const fragment = try self.loadShader("skybox.frag", skybox_frag.LoadArgs); - var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); - pci.vertex_shader = vertex; - pci.fragment_shader = fragment; + // var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); + // pci.vertex_shader = vertex; + // pci.fragment_shader = fragment; - var attributes = try self.generateVertexAttributeList(); - defer attributes.deinit(); + // var attributes = try self.generateVertexAttributeList(); + // defer attributes.deinit(); - pci.vertex_input_state = .{ - .num_vertex_buffers = 1, - .vertex_buffer_descriptions = &[_]gpu.GPUVertexBufferDescription{ - .{ .slot = 0, .pitch = @sizeOf(rend.MeshVertex), .input_rate = .vertexinputrateVertex, .instance_step_rate = 0 }, - }, - .num_vertex_attributes = @intCast(attributes.items.len), - .vertex_attributes = @ptrCast(attributes.items.ptr), - }; + // pci.vertex_input_state = .{ + // .num_vertex_buffers = 1, + // .vertex_buffer_descriptions = &[_]gpu.GPUVertexBufferDescription{ + // .{ .slot = 0, .pitch = @sizeOf(rend.MeshVertex), .input_rate = .vertexinputrateVertex, .instance_step_rate = 0 }, + // }, + // .num_vertex_attributes = @intCast(attributes.items.len), + // .vertex_attributes = @ptrCast(attributes.items.ptr), + // }; - pci.target_info.num_color_targets = 1; - pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ - .{ - .format = self.device.getGPUSwapchainTextureFormat(self.window), - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), - }, - }; + // pci.target_info.num_color_targets = 1; + // pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ + // .{ + // .format = self.device.getGPUSwapchainTextureFormat(self.window), + // .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + // }, + // }; - pci.rasterizer_state.fill_mode = .fillmodeFill; - self.skyboxPipeline = self.device.createGPUGraphicsPipeline(&pci); - } + // pci.rasterizer_state.fill_mode = .fillmodeFill; + // self.skyboxPipeline = self.device.createGPUGraphicsPipeline(&pci); + // } pub fn createSamplers(self: *@This()) !void { core.engine_log("creating blocky sampler", .{}); @@ -479,17 +481,6 @@ pub const Renderer = struct { return rv; } - pub fn uploadSkyboxUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { - var data = std.mem.zeroes([@sizeOf(skybox_vert.Uniforms) / 8 + 1]usize); - const ptr: *skybox_vert.Uniforms = @ptrCast(@alignCast(&data)); - - if (self.activeCamera) |camera| { - ptr.ViewProjection = @bitCast(camera.noTranslate); - } - - cmd.pushGPUVertexUniformData(0, &data, @sizeOf(skybox_vert.Uniforms)); - } - pub fn uploadUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) !void { { var data = std.mem.zeroes([@sizeOf(meshes_vert.Uniforms) / 8 + 1]usize); @@ -570,10 +561,6 @@ pub const Renderer = struct { const cmd = self.device.acquireGPUCommandBuffer(); self.frameUploads(); - for (self.preDraws.items) |interface| { - interface.func(interface.ptr, cmd); - } - // mesh pre-iteration const container = rend.MeshComponent.BaseContainer; const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount); @@ -590,7 +577,9 @@ pub const Renderer = struct { } } - self.drawDirectionalShadowMap(cmd); + for (self.preDraws.items) |interface| { + interface.func(interface.ptr, cmd); + } self.draw(cmd); } @@ -653,41 +642,50 @@ pub const Renderer = struct { _ = cmd.submitGPUCommandBuffer(); return; } - // render the skybox + + // preMeshPasses + self.drawDirectionalShadowMap(cmd); + // + + // draw skybox { - if (self.skyboxMesh == null) { - self.skyboxMesh = getMeshByName(&self.skyboxMeshName); - } - if (self.skyboxTexture == null) { - if (self.skyboxTextureName) |*name| { - self.skyboxTexture = getTexture(name); - } - } - - if (self.skyboxTexture) |skyboxTexture| { - if (self.skyboxMesh) |skyboxMesh| { - const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.swapchainTexture.?, - .clear_color = self.skyboxColor, - .load_op = .loadopClear, - .store_op = .storeopStore, - }); - - const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); - - self.uploadSkyboxUniforms(cmd); - renderpass.bindGPUGraphicsPipeline(self.skyboxPipeline); - renderpass.bindGPUFragmentSamplers(0, &.{ .texture = skyboxTexture.texture, .sampler = self.blockySampler }, 1); - renderpass.drawGPUIndexedPrimitives(skyboxMesh.index.size, 1, skyboxMesh.index.start, @intCast(skyboxMesh.vertex.start), 0); - renderpass.endGPURenderPass(); - } - } + self.skyboxSystem.render(cmd); } + // render the skybox + // { + // if (self.skyboxMesh == null) { + // self.skyboxMesh = getMeshByName(&self.skyboxMeshName); + // } + // if (self.skyboxTexture == null) { + // if (self.skyboxTextureName) |*name| { + // self.skyboxTexture = getTexture(name); + // } + // } + // + // if (self.skyboxTexture) |skyboxTexture| { + // if (self.skyboxMesh) |skyboxMesh| { + // const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + // .texture = self.swapchainTexture.?, + // .clear_color = self.skyboxColor, + // .load_op = .loadopClear, + // .store_op = .storeopStore, + // }); + // + // const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); + // + // self.uploadSkyboxUniforms(cmd); + // renderpass.bindGPUGraphicsPipeline(self.skyboxPipeline); + // renderpass.bindGPUFragmentSamplers(0, &.{ .texture = skyboxTexture.texture, .sampler = self.blockySampler }, 1); + // renderpass.drawGPUIndexedPrimitives(skyboxMesh.index.size, 1, skyboxMesh.index.start, @intCast(skyboxMesh.vertex.start), 0); + // renderpass.endGPURenderPass(); + // } + // } + // } + // can cache this const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ .texture = self.swapchainTexture.?, - .clear_color = self.skyboxColor, .load_op = .loadopLoad, .store_op = .storeopStore, }); @@ -788,9 +786,6 @@ const lit_mesh_frag = @import("lit_mesh.frag"); const depthOnly = @import("depthOnly.frag"); const sample_vert = @import("sample.vert"); -const skybox_vert = @import("skybox.vert"); -const skybox_frag = @import("skybox.frag"); - const MeshVertices = meshes_vert.Scene; const MeshUniforms = meshes_vert.Uniforms; @@ -802,6 +797,7 @@ pub const MeshPool = mesh_pool.MeshPool; pub const TextureList = @import("TextureList.zig"); const DebugDrawSystem = @import("DebugDrawSystem.zig"); +const SkyboxSystem = @import("SkyboxSystem.zig"); // debug api @@ -842,7 +838,7 @@ pub fn registerRendererObject(comptime T: type, object: *anyopaque) !void { } pub fn setSkyboxTexture(name: []const u8) void { - gRenderer.skyboxTextureName = core.MakeName(name); + gRenderer.skyboxSystem.skyboxTextureName = core.MakeName(name); } pub const getMesh = mesh_pool.getMesh;