From c008e5232d043aa69abe44fe8f12f1496c63149c Mon Sep 17 00:00:00 2001 From: peterino2 Date: Wed, 24 Sep 2025 01:06:42 -0700 Subject: [PATCH] added split between transparent and opaque renderpasses --- engine/core/src/ecs.zig | 2 +- engine/core/src/engine.zig | 2 +- engine/papyrus/src/DrawCommand.zig | 1 + engine/papyrus/src/papyrus.zig | 3 +- engine/rend/build.zig | 1 + engine/rend/build.zig.zon | 1 + engine/rend/shaders/lit_mesh.frag.hlsl | 4 +- engine/rend/shaders/postProc.frag.hlsl | 5 +- engine/rend/shaders/sceneShared.hlsli | 2 +- engine/rend/shaders/ssao.frag.hlsl | 5 + .../rend/src/animations/animationSystem.zig | 2 - engine/rend/src/particles/particles.zig | 64 +++- engine/rend/src/rend.zig | 2 + engine/rend/src/sgpu/renderer.zig | 302 ++++++++++++------ engine/sys/src/sys.zig | 10 +- engine/sys/src/systemProc.zig | 167 +++++++++- engine/ui/src/sgpu/papyrusSgpu.zig | 24 ++ engine/ui/src/sgpu/textRenderer.zig | 12 +- extras/bsp/src/maploader.zig | 2 - projects/build.zig | 1 + .../content/_shaders/dxil/lit_mesh.frag.dxil | Bin 8412 -> 8412 bytes .../content/_shaders/msl/lit_mesh.frag.msl | 4 +- .../content/_shaders/spv/lit_mesh.frag.spv | Bin 8096 -> 8096 bytes projects/sampleGame/externGame/externGame.zig | 3 +- 24 files changed, 494 insertions(+), 125 deletions(-) diff --git a/engine/core/src/ecs.zig b/engine/core/src/ecs.zig index 97b7798..cde16b3 100644 --- a/engine/core/src/ecs.zig +++ b/engine/core/src/ecs.zig @@ -325,7 +325,7 @@ pub fn defineComponent(comptime Component: type, allocator: std.mem.Allocator) ! const ContainerType = @TypeOf(Component.BaseContainer.*); Component.BaseContainer = try ContainerType.create(allocator); - core.engine_log("Component container created " ++ @typeName(Component) ++ " @{x}", .{@intFromPtr(Component.BaseContainer)}); + core.engine_log("Component container created " ++ @typeName(Component) ++ " @{x} component size = {d} containerType = {s}", .{ @intFromPtr(Component.BaseContainer), @sizeOf(Component), @TypeOf(Component.BaseContainer.*).EcsContainerInterfaceVTable.containerTypeName }); const container = makeEcsContainerRef(Component.BaseContainer); try registerEcsContainer(container, core.MakeName(Component.ComponentName)); diff --git a/engine/core/src/engine.zig b/engine/core/src/engine.zig index d440043..fc7a618 100644 --- a/engine/core/src/engine.zig +++ b/engine/core/src/engine.zig @@ -406,7 +406,7 @@ pub const Engine = struct { pub const NeonObjectParams = struct { can_tick: ?bool = null, responds_to_events: bool = false, - isCore: bool = false, + isCore: bool = false, // if set true, object destruction order matters. }; const Src = std.builtin.SourceLocation; diff --git a/engine/papyrus/src/DrawCommand.zig b/engine/papyrus/src/DrawCommand.zig index aa5f78b..1c7bf44 100644 --- a/engine/papyrus/src/DrawCommand.zig +++ b/engine/papyrus/src/DrawCommand.zig @@ -35,5 +35,6 @@ pub const PrimitiveText = struct { fontHandle: u32, // this is just a core.Name handle flags: packed struct { setSourceGeometry: bool, + debugText: bool = false, }, }; diff --git a/engine/papyrus/src/papyrus.zig b/engine/papyrus/src/papyrus.zig index 0657f9d..1c4f5d9 100644 --- a/engine/papyrus/src/papyrus.zig +++ b/engine/papyrus/src/papyrus.zig @@ -1251,7 +1251,7 @@ pub const Context = struct { } try drawList.append(.{ - .node = .{}, + .node = .{ .index = @intCast(i) }, .primitive = .{ .Text = .{ .text = LocText.fromUtf8Z(textData), @@ -1263,6 +1263,7 @@ pub const Context = struct { .fontHandle = fontHandle, .flags = .{ .setSourceGeometry = false, + .debugText = true, }, }, }, diff --git a/engine/rend/build.zig b/engine/rend/build.zig index 2f4d1b4..e3c7c87 100644 --- a/engine/rend/build.zig +++ b/engine/rend/build.zig @@ -6,6 +6,7 @@ const dependencyList = [_][]const u8{ "assets", "sdl3", "platform", + "sys", "shaderTypes", "objLoader", "zgltf", diff --git a/engine/rend/build.zig.zon b/engine/rend/build.zig.zon index 102ade7..fd916b9 100644 --- a/engine/rend/build.zig.zon +++ b/engine/rend/build.zig.zon @@ -5,6 +5,7 @@ .core = .{ .path = "../core" }, .assets = .{ .path = "../assets" }, .platform = .{ .path = "../platform" }, + .sys = .{.path = "../sys"}, .sdl3 = .{ .path = "../../lib/sdl3" }, .ozz = .{ .path = "../../lib/ozz" }, diff --git a/engine/rend/shaders/lit_mesh.frag.hlsl b/engine/rend/shaders/lit_mesh.frag.hlsl index 2bfe7a6..3c0141e 100644 --- a/engine/rend/shaders/lit_mesh.frag.hlsl +++ b/engine/rend/shaders/lit_mesh.frag.hlsl @@ -187,6 +187,7 @@ PixelOutput main( float4 s; int texMode = scene[Instance].textureMode; + int flags = scene[Instance].flags; if ((texMode & 0xf0) == 0x10) // YUV { float3 offset = float3(-0.0625, -0.5, -0.5); @@ -247,10 +248,11 @@ PixelOutput main( PixelOutput o; o.Position = float4(WorldPos, 1.0); + o.Normal = float4(ScreenNormal, 1.0); o.Color = float4(c2, alpha); - o.Emissive = float4(0.0, 0.0, 0.0, 1.0); + o.Emissive = float4(0.0, 0.0, 0.0, 0.0); if(c2.x > 1.0) o.Emissive.x = c2.x; if(c2.y > 1.0) o.Emissive.y = c2.y; if(c2.z > 1.0) o.Emissive.z = c2.z; diff --git a/engine/rend/shaders/postProc.frag.hlsl b/engine/rend/shaders/postProc.frag.hlsl index 8ac160b..79e9386 100644 --- a/engine/rend/shaders/postProc.frag.hlsl +++ b/engine/rend/shaders/postProc.frag.hlsl @@ -133,7 +133,8 @@ float4 main(float2 UV : TEXCOORD0) : SV_Target0 #if 0 float4 ssao = SsaoTexture.Sample(Sampler2, uv); - c = ssao.xyz; + //c.x += (1.0 - ssao.x) * 0.7; + c = ssao; #else float3 ssao = blurSSAO(uv); @@ -143,8 +144,6 @@ float4 main(float2 UV : TEXCOORD0) : SV_Target0 //float4 x = SsaoTexture.Sample(Sampler2, uv); //c = x; - // c = float3(ssao, ssao, ssao); - c.x *= 1.0 + 0.000001 * EmissiveTexture.Sample(Sampler1, uv).x; c.x *= 1.0 + 0.000001 * ColorTexture.Sample(Sampler0, uv).x; c.x *= 1.0 + 0.000001 * SsaoTexture.Sample(Sampler2, uv).x; diff --git a/engine/rend/shaders/sceneShared.hlsli b/engine/rend/shaders/sceneShared.hlsli index eaf113d..ff43e35 100644 --- a/engine/rend/shaders/sceneShared.hlsli +++ b/engine/rend/shaders/sceneShared.hlsli @@ -5,7 +5,7 @@ struct Scene uint textureMode; // 0 = regular triple, // 0x10 = video yuv, // bit 0 == srgb correction - // bit 1 == fullbright + // bit 1 == fullbright // 0x2 // bit 2 = reserved // bit 3 = reserved // bit 4 - 7 = color space: diff --git a/engine/rend/shaders/ssao.frag.hlsl b/engine/rend/shaders/ssao.frag.hlsl index 2f5c2e4..ef6f517 100644 --- a/engine/rend/shaders/ssao.frag.hlsl +++ b/engine/rend/shaders/ssao.frag.hlsl @@ -98,7 +98,12 @@ float4 main(float2 UV: TEXCOORD0) : SV_Target0 // float x = length(c); // c = float4(x, x, x, 1.0); +#if 1 c = occlusion; +#else + + c = mul(View, PositionTexture.Sample(Sampler0, uv)).z / 100; // texture(gPosition, offset.xy).z; // get depth value of kernel sample +#endif //float j = x.z; //c = float4(x, 1.0); diff --git a/engine/rend/src/animations/animationSystem.zig b/engine/rend/src/animations/animationSystem.zig index 2707e1a..1e18a8c 100644 --- a/engine/rend/src/animations/animationSystem.zig +++ b/engine/rend/src/animations/animationSystem.zig @@ -433,7 +433,6 @@ pub const AnimationSystem = struct { Animator.allocator = alloc; core.engine_logs("Animation System initialized"); - try core.defineComponent(Animator, alloc); return self; } @@ -464,7 +463,6 @@ pub const AnimationSystem = struct { } self.slots.deinit(); - core.undefineComponent(Animator); self.arena.deinit(); self.skeletons.deinit(self.backingAllocator); self.animTracks.deinit(self.backingAllocator); diff --git a/engine/rend/src/particles/particles.zig b/engine/rend/src/particles/particles.zig index cf2bd2f..c7605ad 100644 --- a/engine/rend/src/particles/particles.zig +++ b/engine/rend/src/particles/particles.zig @@ -101,6 +101,52 @@ pub const RenderInfo = struct { } }; +pub const ParticleTimelineBurst = struct { + count: u32, +}; + +pub const ParticleTimeline = struct { func: ParticleTimelineFunc = .{} }; + +pub const ParticleTimelineFunc = union(enum(u8)) { burst: ParticleTimelineBurst }; + +pub const VfxEmitter = struct { + emitter: ParticleEmitter, + timeline: ParticleTimeline, + parent: u32, + transform: core.Mat, +}; + +pub const VfxComponent = struct { + // aims to replace the ParticleEmitter + // instead of having just one particle emitter, the VfxComponent manages scenes for multiple particle emitters + + pub var BaseContainer: *core.SparseSet(VfxComponent) = undefined; + pub const ComponentName = "rend.VfxComponent"; + pub const ScriptExports: []const []const u8 = &.{}; + + entity: core.Entity = undefined, + emitterList: std.MultiArrayList(VfxEmitter) = .{}, + + pub fn initECS(self: *@This(), handle: core.SetHandle) void { + self.entity = core.Entity{ .handle = handle }; + } + + pub fn addEmitter(self: *@This()) *ParticleEmitter { + _ = self; + } + + pub fn update(self: *@This(), dt: f64) void { + _ = dt; + _ = self; + } + + pub fn deinitECS(self: *@This(), handle: core.SetHandle) void { + for (self.emitters.items) |emitter| { + emitter.deinitECS(handle); + } + } +}; + pub const ParticleEmitter = struct { pub var BaseContainer: *core.SparseSet(ParticleEmitter) = undefined; pub const ComponentName = "ParticleEmitter"; @@ -324,7 +370,7 @@ pub const ParticleEmitter = struct { var t_whiteName: core.Name = core.DefineName("t_white"); var m_quad: core.Name = core.DefineName("m_screenPlane"); - pub fn initECS(self: *@This(), handle: core.SetHandle) void { + pub fn initECS(self: *@This(), handle: core.ObjectHandle) void { // get the mesh component self.entity = core.Entity{ .handle = handle }; @@ -338,15 +384,21 @@ pub const ParticleEmitter = struct { } } + pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void { + _ = handle; + self.deinit(); + } + pub fn deinit(self: *@This()) void { - _ = self; + self.life.deinit(gParticleAllocator); + self.particlesPVA.deinit(gParticleAllocator); + self.finals.deinit(gParticleAllocator); + self.size.deinit(gParticleAllocator); } }; var gParticleAllocator: std.mem.Allocator = undefined; -pub const Effect = struct {}; - pub const ParticleSystem = struct { particleArena: std.heap.ArenaAllocator, allocator: std.mem.Allocator, @@ -366,8 +418,6 @@ pub const ParticleSystem = struct { ParticleRandRangef.randomEngine = std.Random.DefaultPrng.init(0x1234); ParticleRandRangef.randomFunc = ParticleRandRangef.randomEngine.random(); - try core.defineComponent(ParticleEmitter, allocator); - return self; } @@ -383,8 +433,6 @@ pub const ParticleSystem = struct { } pub fn destroy(self: *@This()) void { - core.undefineComponent(ParticleEmitter); - self.particleArena.deinit(); self.allocator.destroy(self); } diff --git a/engine/rend/src/rend.zig b/engine/rend/src/rend.zig index ab3abbe..cdc8cbf 100644 --- a/engine/rend/src/rend.zig +++ b/engine/rend/src/rend.zig @@ -80,6 +80,8 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me pub const ComponentList = struct { pub const _MeshComponent = MeshComponent; pub const _CameraComponent = CameraComponent; + pub const _Animator = Animator; + pub const _ParticleEmitter = ParticleEmitter; }; pub fn setupFromModule() void { diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 42f1ed3..021f290 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -15,7 +15,8 @@ pub const Renderer = struct { shaderformat: gpu.GPUShaderFormat = undefined, entrypoint: []const u8 = "main", testPipeline: *gpu.GPUGraphicsPipeline = undefined, - meshPipe: *gpu.GPUGraphicsPipeline = undefined, + opaquePipe: *gpu.GPUGraphicsPipeline = undefined, + transparentPipe: *gpu.GPUGraphicsPipeline = undefined, scissor: gpu.Rect = undefined, // .{ .x = 0, .y = 0, .w = 1600, .h = 900 }, colorBuffer: *gpu.GPUBuffer = undefined, @@ -40,6 +41,7 @@ pub const Renderer = struct { preDraws: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer) void }) = .{}, shaderReloads: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, + shaderReloadFinished: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, depthTexture: *gpu.GPUTexture = undefined, depthFormat: gpu.GPUTextureFormat = .textureformatD32Float, @@ -122,6 +124,12 @@ pub const Renderer = struct { } } + pub fn reloadPluginShadersFinished(self: *@This()) void { + for (self.shaderReloadFinished.items) |interface| { + interface.func(interface.ptr); + } + } + pub fn createRenderTargets(self: *@This()) !void { var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); @@ -145,6 +153,9 @@ pub const Renderer = struct { gci.format = self.normalTargetFormat; self.state.normalTarget = self.device.createGPUTexture(&gci); + + self.swapchainTargetFormat = self.device.getGPUSwapchainTextureFormat(self.window); + core.graphics_log("swapchain format: {any}", .{self.swapchainTargetFormat}); } pub fn startRenderer(self: *@This()) !void { @@ -165,7 +176,8 @@ pub const Renderer = struct { core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix}); core.engine_log("using renderer... scientist", .{}); - try self.createMeshPipeline(); + try self.createOpaquePipeline(); + try self.createTransparentsPipeline(); try self.createBuffers(); try self.createDepthTexture(); try self.createRenderTargets(); @@ -350,6 +362,7 @@ pub const Renderer = struct { if (@hasDecl(T, "onShaderReload")) { try self.shaderReloads.append(self.allocator, .{ .ptr = object, .func = T.onShaderReload }); + try self.shaderReloadFinished.append(self.allocator, .{ .ptr = object, .func = T.onShaderReloadFinished }); } } @@ -480,69 +493,120 @@ pub const Renderer = struct { self.shadowCastingPipeline = self.device.createGPUGraphicsPipeline(&pci); } - pub fn createMeshPipeline(self: *@This()) !void { - const vertex = try self.loadShader("meshes.vert", meshes_vert.LoadArgs); - const fragment = try self.loadShader("lit_mesh.frag", lit_mesh_frag.LoadArgs); + const CreatePipelineInfo = struct { + attributes: ?std.ArrayList(gpu.GPUVertexAttribute) = null, + pci: gpu.GPUGraphicsPipelineCreateInfo = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo), + vertexBuffers: std.ArrayListUnmanaged(gpu.GPUVertexBufferDescription) = .{}, + colorTargets: std.ArrayListUnmanaged(gpu.GPUColorTargetDescription) = .{}, - var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); - pci.vertex_shader = vertex; - pci.fragment_shader = fragment; + pub fn init() @This() { + return .{}; + } - //var attributes = try self.generateVertexAttributeList(); - var attributes = try self.addVertexAttributes(&pci); - defer attributes.deinit(); + pub fn addMeshPci(self: *@This(), vertexShader: []const u8, fragmentShader: []const u8) !void { + const ctx = context(); + const pci = &self.pci; - 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), - }; + const vertex = try ctx.loadShader(vertexShader, meshes_vert.LoadArgs); + const fragment = try ctx.loadShader(fragmentShader, lit_mesh_frag.LoadArgs); + pci.vertex_shader = vertex; + pci.fragment_shader = fragment; - pci.depth_stencil_state.compare_op = .compareopLess; - pci.depth_stencil_state.enable_depth_test = true; - pci.depth_stencil_state.enable_depth_write = true; - pci.depth_stencil_state.write_mask = 0xff; + self.attributes = try addVertexAttributesFromStruct(rend.MeshVertex, pci); - self.swapchainTargetFormat = self.device.getGPUSwapchainTextureFormat(self.window); - core.graphics_log("swapchain format: {any}", .{self.swapchainTargetFormat}); - pci.target_info.has_depth_stencil_target = true; - pci.target_info.depth_stencil_format = self.depthFormat; - pci.target_info.num_color_targets = 4; - pci.target_info.color_target_descriptions = &[4]gpu.GPUColorTargetDescription{ - .{ - .format = self.hdrTextureFormat, - //.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), - .blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{ - .alpha_blend_op = .blendopAdd, - .color_blend_op = .blendopAdd, - .src_color_blendfactor = .blendfactorSrcAlpha, - .dst_color_blendfactor = .blendfactorOneMinusSrcAlpha, - .src_alpha_blendfactor = .blendfactorSrcAlpha, - .dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha, - .enable_blend = true, - }), - }, - .{ - .format = self.hdrTextureFormat, - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), - }, - .{ - .format = self.positionTargetFormat, - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), - }, - .{ - .format = self.normalTargetFormat, - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), - }, - }; + try self.vertexBuffers.appendSlice(ctx.allocator, &[_]gpu.GPUVertexBufferDescription{ + .{ + .slot = 0, + .pitch = @sizeOf(rend.MeshVertex), + .input_rate = .vertexinputrateVertex, + .instance_step_rate = 0, + }, + }); - pci.rasterizer_state.fill_mode = .fillmodeFill; - pci.rasterizer_state.cull_mode = .cullmodeBack; - pci.rasterizer_state.front_face = .frontfaceClockwise; - self.meshPipe = self.device.createGPUGraphicsPipeline(&pci); + pci.vertex_input_state = .{ + .num_vertex_buffers = 1, + .vertex_buffer_descriptions = self.vertexBuffers.items.ptr, + .num_vertex_attributes = @intCast(self.attributes.?.items.len), + .vertex_attributes = @ptrCast(self.attributes.?.items.ptr), + }; + + pci.depth_stencil_state.compare_op = .compareopLess; + pci.depth_stencil_state.enable_depth_test = true; + pci.depth_stencil_state.enable_depth_write = true; + pci.depth_stencil_state.write_mask = 0xff; + + pci.target_info.has_depth_stencil_target = true; + pci.target_info.depth_stencil_format = ctx.depthFormat; + pci.target_info.num_color_targets = 4; + + try self.colorTargets.appendSlice(ctx.allocator, &[4]gpu.GPUColorTargetDescription{ + .{ + .format = ctx.hdrTextureFormat, + //.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + .blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{ + .alpha_blend_op = .blendopAdd, + .color_blend_op = .blendopAdd, + .src_color_blendfactor = .blendfactorSrcAlpha, + .dst_color_blendfactor = .blendfactorOneMinusSrcAlpha, + .src_alpha_blendfactor = .blendfactorSrcAlpha, + .dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha, + .enable_blend = true, + }), + }, + .{ + .format = ctx.hdrTextureFormat, + // .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + .blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{ + .alpha_blend_op = .blendopAdd, + .color_blend_op = .blendopAdd, + .src_color_blendfactor = .blendfactorSrcAlpha, + .dst_color_blendfactor = .blendfactorOneMinusSrcAlpha, + .src_alpha_blendfactor = .blendfactorSrcAlpha, + .dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha, + .enable_blend = true, + }), + }, + .{ + .format = ctx.positionTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + .{ + .format = ctx.normalTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + }); + pci.target_info.color_target_descriptions = self.colorTargets.items.ptr; + + pci.rasterizer_state.fill_mode = .fillmodeFill; + pci.rasterizer_state.cull_mode = .cullmodeBack; + pci.rasterizer_state.front_face = .frontfaceClockwise; + } + + pub fn deinit(self: *@This()) void { + if (self.attributes) |*a| { + a.deinit(); + } + self.vertexBuffers.deinit(context().allocator); + self.colorTargets.deinit(context().allocator); + } + }; + + pub fn createTransparentsPipeline(self: *@This()) !void { + var createInfo = CreatePipelineInfo.init(); + try createInfo.addMeshPci("meshes.vert", "lit_mesh.frag"); + defer createInfo.deinit(); + + createInfo.pci.depth_stencil_state.enable_depth_write = false; + + self.transparentPipe = self.device.createGPUGraphicsPipeline(&createInfo.pci); + } + + pub fn createOpaquePipeline(self: *@This()) !void { + var createInfo = CreatePipelineInfo.init(); + try createInfo.addMeshPci("meshes.vert", "lit_mesh.frag"); + defer createInfo.deinit(); + + self.opaquePipe = self.device.createGPUGraphicsPipeline(&createInfo.pci); } pub fn createBuffers(self: *@This()) !void { @@ -864,34 +928,39 @@ pub const Renderer = struct { renderpass.endGPURenderPass(); } - pub fn drawMeshes(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { - // can cache this - const targetInfo: [4]gpu.GPUColorTargetInfo = .{ - std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.state.targetTexture, - .load_op = .loadopLoad, - .store_op = .storeopStore, - }), - std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.state.emissiveTarget, - .load_op = .loadopClear, - .store_op = .storeopStore, - }), - std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.state.positionTarget, - .load_op = .loadopClear, - .store_op = .storeopStore, - }), - std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.state.normalTarget, - .load_op = .loadopClear, - .store_op = .storeopStore, - }), - }; + var meshRenderPassTargetInfo: ?[4]gpu.GPUColorTargetInfo = null; - const depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{ + pub fn beginMeshRenderPass(self: *@This(), cmd: *gpu.GPUCommandBuffer, pipeline: *gpu.GPUGraphicsPipeline, clearDepth: bool) *gpu.GPURenderPass { + if (meshRenderPassTargetInfo == null) { + meshRenderPassTargetInfo = .{ + std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.state.targetTexture, + .load_op = .loadopLoad, + .store_op = .storeopStore, + }), + std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.state.emissiveTarget, + .load_op = .loadopClear, + .store_op = .storeopStore, + }), + std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.state.positionTarget, + .load_op = .loadopClear, + .store_op = .storeopStore, + }), + std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.state.normalTarget, + .load_op = .loadopClear, + .store_op = .storeopStore, + }), + }; + } + + const targetInfo = meshRenderPassTargetInfo.?; + + var depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{ .texture = self.depthTexture, - .load_op = .loadopClear, + .load_op = .loadopLoad, .store_op = .storeopDontCare, .stencil_load_op = .loadopDontCare, .stencil_store_op = .storeopDontCare, @@ -899,6 +968,10 @@ pub const Renderer = struct { .clear_stencil = 0, }); + if (clearDepth) { + depthTarget.load_op = .loadopClear; + } + self.state.pass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget); const renderpass = self.state.pass.?; renderpass.setGPUScissor(&self.scissor); @@ -913,10 +986,14 @@ pub const Renderer = struct { renderpass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1); renderpass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); - renderpass.bindGPUGraphicsPipeline(self.meshPipe); + renderpass.bindGPUGraphicsPipeline(pipeline); renderpass.bindGPUFragmentSamplers(self.shadowDepthTextureSlot, &.{ .texture = self.shadowDepthTexture, .sampler = self.blockySampler }, 1); - try self.uploadUniforms(cmd); + return renderpass; + } + + pub fn drawOpaques(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + const renderpass = self.beginMeshRenderPass(cmd, self.opaquePipe, true); //rendering each mesh { @@ -959,6 +1036,13 @@ pub const Renderer = struct { } } + renderpass.endGPURenderPass(); + self.state.pass = null; + } + + pub fn drawTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + const renderpass = self.beginMeshRenderPass(cmd, self.transparentPipe, false); + for (self.postMesh.items) |interface| { interface.func(interface.ptr, cmd, renderpass); } @@ -967,6 +1051,14 @@ pub const Renderer = struct { self.state.pass = null; } + pub fn drawMeshes(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + // can cache this + try self.uploadUniforms(cmd); + + self.drawOpaques(cmd); + self.drawTransparents(cmd); + } + pub fn renderTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { const targetInfo: [4]gpu.GPUColorTargetInfo = .{ std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ @@ -1080,6 +1172,8 @@ pub const Renderer = struct { self.preDraws.deinit(self.allocator); self.postRenders.deinit(self.allocator); self.shaderReloads.deinit(self.allocator); + self.shaderReloadFinished.deinit(self.allocator); + self.uploads.deinit(self.allocator); self.destroys.deinit(self.allocator); self.allocator.destroy(self); @@ -1123,16 +1217,37 @@ const SkyboxSystem = @import("SkyboxSystem.zig"); // debug api pub fn reloadShaders() !void { - _ = core.shell.runCmd(context().allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch { - core.graphics_logs("shader cook script failed"); + if (core.BuildOption("static_build")) { + core.graphics_logs("skipping shader hotreload, not available in static build"); return; - }; - try context().createMeshPipeline(); - try context().createPostProcessingPipeline(); - try context().ssaoSystem.createPipeline(); + } + + // _ = core.shell.runCmd(context().allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch { + // core.graphics_logs("shader cook script failed"); + // return; + // }; + try sys.start_CompileShaders(null, reloadShadersFinished); context().reloadPluginShaders(); } +pub fn reloadShadersFinished(ctx: ?*anyopaque) void { + _ = ctx; + + context().createOpaquePipeline() catch { + core.engine_errs("unable to rebuild pipeline"); + }; + context().createTransparentsPipeline() catch { + core.engine_errs("unable to rebuild pipeline"); + }; + context().createPostProcessingPipeline() catch { + core.engine_errs("unable to rebuild pipeline"); + }; + context().ssaoSystem.createPipeline() catch { + core.engine_errs("unable to rebuild pipeline"); + }; + context().reloadPluginShadersFinished(); +} + // ====== renderer API ======= pub fn createInstance() !void { _ = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true }); @@ -1199,6 +1314,7 @@ const tracy = core.tracy; const animationSystem = rend.animationSystem; +const sys = @import("sys"); const builtin = @import("builtin"); pub const SsaoSystem = @import("ssao.zig"); pub const ParticleRenderer = @import("ParticleRenderer.zig"); diff --git a/engine/sys/src/sys.zig b/engine/sys/src/sys.zig index c20e6f2..9923445 100644 --- a/engine/sys/src/sys.zig +++ b/engine/sys/src/sys.zig @@ -1,9 +1,13 @@ const std = @import("std"); pub const core = @import("core"); +pub const systemProc = @import("systemProc.zig"); -pub const SubprocessTask = @import("systemProc.zig").SubprocessTask; +pub const SubprocessTask = systemProc.SubprocessTask; +pub const SystemRunner = systemProc.SystemRunner; pub const runCommand = SubprocessTask.runCommand; +pub const start_CompileShaders = systemProc.start_CompileShaders; + // TODO get rid of core.ModuleDescription // it's really not needed anymore with the // new backlog API @@ -26,8 +30,12 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me _ = args; _ = spec; _ = allocator; + + _ = try core.createObject(SystemRunner, .{ .can_tick = true }); } +pub fn setupFromModule() void {} + pub fn shutdown_module(allocator: std.mem.Allocator) void { _ = allocator; } diff --git a/engine/sys/src/systemProc.zig b/engine/sys/src/systemProc.zig index b64c84d..bfcf7c4 100644 --- a/engine/sys/src/systemProc.zig +++ b/engine/sys/src/systemProc.zig @@ -39,12 +39,12 @@ pub const SubprocessTask = struct { self.mutex.lock(); self.stderr = .{}; self.stdout = .{}; - debugPrint("running task", .{}); + core.engine_log("running task", .{}); for (self.args) |arg| { - debugPrint("{s}", .{arg}); + core.engine_log("{s}", .{arg}); } - debugPrint("cwd = {s}", .{self.workingDir.?}); + core.engine_log("cwd = {s}", .{self.workingDir.?}); self.child = std.process.Child.init(self.args, self.allocator); self.child.?.stdout_behavior = .Inherit; self.child.?.stderr_behavior = .Inherit; @@ -77,7 +77,7 @@ pub const SubprocessTask = struct { self.mutex.lock(); if (self.child) |*child| { _ = child; - debugPrint("destroying child process", .{}); + core.engine_log("destroying child process", .{}); } self.mutex.unlock(); self.stdout.deinit(self.allocator); @@ -141,3 +141,162 @@ pub const SubprocessTask = struct { return task; } }; + +fn findRootDir(allocator: std.mem.Allocator) ![]u8 { + var current_dir = std.fs.cwd(); + + // Start from current directory and walk up + var path_components = std.ArrayList([]const u8).init(allocator); + defer path_components.deinit(); + + // Try current directory first + current_dir.access("content.txt", .{}) catch { + // content.txt not found, need to walk up + var temp_dir = current_dir; + + while (true) { + // Try to go up one directory + const parent_dir = temp_dir.openDir("..", .{}) catch return error.RootNotFound; + temp_dir = parent_dir; + + // Check if content.txt exists in parent directory + temp_dir.access("content.txt", .{}) catch { + continue; + }; + + // Found content.txt, get the absolute path + return try temp_dir.realpathAlloc(allocator, "."); + } + }; + + // content.txt found in current directory + return try current_dir.realpathAlloc(allocator, "."); +} + +pub fn start_CompileShaders(context: ?*anyopaque, callback: ?*const fn (?*anyopaque) void) !void { + const self = core.EngineObject(SystemRunner).get(); + + const root_dir = findRootDir(self.allocator) catch { + core.engine_log("Could not find BacklogEngine root directory (content.txt not found)", .{}); + return; + }; + + defer self.allocator.free(root_dir); + core.engine_log("Found root directory: {s}", .{root_dir}); + + const compile_shaders_dir = try std.fs.path.join(self.allocator, &.{ root_dir, "tools", "compileShaders" }); + defer self.allocator.free(compile_shaders_dir); + + var compile_shaders_name = core.MakeName(compile_shaders_dir); + + core.engine_log("CompileShaders directory: {s}", .{compile_shaders_dir}); + + const exe_path = try std.fs.path.join(self.allocator, &.{ compile_shaders_dir, "zig-out", "bin", "compileShaders.exe" }); + defer self.allocator.free(exe_path); + core.engine_log("Looking for executable at: {s}", .{exe_path}); + + // Check if compileShaders.exe exists + if (std.fs.cwd().access(exe_path, .{})) |_| { + // File exists, run it directly + core.engine_log("CompileShaders executable found, running directly", .{}); + try self.commandQueue.pushLocked(.{ .subprocess = .{ + .onComplete = callback, + .context = context, + .task = try SubprocessTask.runCommand( + self.allocator, + &.{"zig-out/bin/compileShaders.exe"}, + compile_shaders_name.utf8(), + ), + } }); + } else |_| { + // File doesn't exist, build it first + core.engine_log("CompileShaders executable not found, building first", .{}); + try self.commandQueue.pushLocked(.{ + .subprocess = .{ .task = try SubprocessTask.runCommand( + self.allocator, + &.{ "zig", "build", "install" }, + compile_shaders_name.utf8(), + ) }, + }); + + // Then run it + core.engine_log("Queuing compileShaders execution after build", .{}); + try self.commandQueue.pushLocked(.{ + .subprocess = .{ + .context = context, + .onComplete = callback, + .task = try SubprocessTask.runCommand( + self.allocator, + &.{"zig-out/bin/compileShaders.exe"}, + compile_shaders_name.utf8(), + ), + }, + }); + } +} + +const Task = union(enum(u8)) { + subprocess: struct { + task: *SubprocessTask, + onComplete: ?*const fn (?*anyopaque) void = null, + context: ?*anyopaque = null, + }, +}; + +pub const SystemRunner = struct { + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "sys.SystemRunner"); + + allocator: std.mem.Allocator, + + commandQueue: core.RingQueue(Task), + activeCommand: ?Task = null, + + pub fn create(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + + self.* = .{ + .allocator = allocator, + .commandQueue = try core.RingQueue(Task).init(self.allocator, 256), + }; + + return self; + } + + pub fn tick(self: *@This(), dt: f64) void { + _ = dt; + if (self.activeCommand == null) { + if (self.commandQueue.popFromLocked()) |task| { + switch (task) { + .subprocess => |t| { + self.activeCommand = task; + // core.engine_log("starting task {any}", .{t.args}); + t.task.run() catch { + self.activeCommand = null; + return; + }; + }, + //.func => |f| { + //f(self); + // }, + } + } + } + + if (self.activeCommand) |active| { + if (active.subprocess.task.checkComplete()) { + if (active.subprocess.onComplete) |onComplete| { + onComplete(active.subprocess.context); + } + + active.subprocess.task.destroy(); + core.engine_logs("task complete"); + self.activeCommand = null; + } + } + } + + pub fn destroy(self: *@This()) void { + self.commandQueue.deinit(); + self.allocator.destroy(self); + } +}; diff --git a/engine/ui/src/sgpu/papyrusSgpu.zig b/engine/ui/src/sgpu/papyrusSgpu.zig index f8ebd6e..40b89eb 100644 --- a/engine/ui/src/sgpu/papyrusSgpu.zig +++ b/engine/ui/src/sgpu/papyrusSgpu.zig @@ -25,6 +25,8 @@ fontTextures: std.AutoHashMapUnmanaged(u32, *rend.Texture) = .{}, textRenderers: std.AutoHashMapUnmanaged(*papyrus.Context, *TextRenderer) = .{}, +reloadingShaders: bool = false, + const DrawCommand = union(enum(u8)) { rect: struct { ssboIndex: u32, @@ -126,6 +128,12 @@ pub fn create(allocator: std.mem.Allocator) !*@This() { return self; } +pub fn tick(self: *@This(), dt: f64) void { + self.screenContext.tick(dt) catch { + core.engine_errs("unable to tick papyrus"); + }; +} + pub fn setup(self: *@This()) !void { core.graphics_log("imgui startup", .{}); @@ -269,9 +277,15 @@ pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void { } pub fn onShaderReload(p: *anyopaque) void { + const self: *@This() = @ptrCast(@alignCast(p)); + self.reloadingShaders = true; +} + +pub fn onShaderReloadFinished(p: *anyopaque) void { const self: *@This() = @ptrCast(@alignCast(p)); self.createRectPipeline() catch return; // you think i give a remote fuck about leaks? this is a debug function son. self.createTextPipeline() catch return; + self.reloadingShaders = false; } pub fn getTextRenderer(self: *@This(), ctx: *papyrus.Context) ?*TextRenderer { @@ -294,7 +308,17 @@ pub fn getFontSampler(self: *@This(), fontHandle: u32) ?gpu.GPUTextureSamplerBin } pub fn drawToTarget(self: *@This(), cmd: *gpu.GPUCommandBuffer, ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void { + const stashedDrawDebug = ctx.drawDebug; + + if (self.reloadingShaders) { + ctx.pushDebugText("recompiling shaders...", .{}) catch {}; + ctx.pushDebugText("...", .{}) catch {}; + } + + ctx.drawDebug = stashedDrawDebug or self.reloadingShaders; + ctx.makeDrawList(&self.drawList, &self.stringArena) catch return; + ctx.drawDebug = stashedDrawDebug; const textRenderer = self.getTextRenderer(ctx); diff --git a/engine/ui/src/sgpu/textRenderer.zig b/engine/ui/src/sgpu/textRenderer.zig index 7aabe86..8f32db7 100644 --- a/engine/ui/src/sgpu/textRenderer.zig +++ b/engine/ui/src/sgpu/textRenderer.zig @@ -96,6 +96,7 @@ pub const TextRenderer = struct { textInstances: std.ArrayListUnmanaged(*TextMeshBuffer) = .{}, deadList: std.ArrayListUnmanaged(*TextMeshBuffer) = .{}, assignedBuffers: std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = .{}, + linearBuffers: std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = .{}, // set of mesh buffers for linearlly allocated text allocator: std.mem.Allocator, lastUpdateTime: f64 = 0, @@ -298,8 +299,10 @@ pub const TextRenderer = struct { pub fn getOrAllocMeshBuffer(self: *@This(), node: papyrus.NodeHandle, text: papyrus.DrawCommand.PrimitiveText) !*TextMeshBuffer { const textLen = text.text.getRead().len; + const assignedBuffers: *std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = if (text.flags.debugText) &self.linearBuffers else &self.assignedBuffers; + // 1. get the assigned buffer; - if (self.assignedBuffers.get(node)) |buffer| { + if (assignedBuffers.get(node)) |buffer| { if (textLen <= buffer.capacity) { return buffer; } @@ -307,7 +310,7 @@ pub const TextRenderer = struct { core.engine_log("recycling text buffer {any}", .{node}); // if the buffer is too small for the text, dont use that one and add it to the dead list. try self.deadList.append(self.allocator, buffer); - _ = self.assignedBuffers.remove(node); + _ = assignedBuffers.remove(node); } // 2. if no text renderer is available, search through the deadList until you find a TextMeshBuffer @@ -318,7 +321,7 @@ pub const TextRenderer = struct { for (self.deadList.items, 0..) |buffer, i| { if (textLen <= buffer.capacity) { - try self.assignedBuffers.put(self.allocator, node, buffer); + try assignedBuffers.put(self.allocator, node, buffer); foundIndex = i; foundBuffer = buffer; } @@ -344,7 +347,7 @@ pub const TextRenderer = struct { core.engine_log("creating text buffer {any} with length {d} for textLen = {d}", .{ node, newBufferLength, textLen }); const newBuffer = try TextMeshBuffer.create(self.allocator, newBufferLength); - try self.assignedBuffers.put(self.allocator, node, newBuffer); + try assignedBuffers.put(self.allocator, node, newBuffer); try self.textInstances.append(self.allocator, newBuffer); return newBuffer; } @@ -369,6 +372,7 @@ pub const TextRenderer = struct { } self.geo.destroy(); + self.linearBuffers.deinit(self.allocator); self.assignedBuffers.deinit(self.allocator); self.textInstances.deinit(self.allocator); self.allocator.destroy(self); diff --git a/extras/bsp/src/maploader.zig b/extras/bsp/src/maploader.zig index 15ef8f7..3c96352 100644 --- a/extras/bsp/src/maploader.zig +++ b/extras/bsp/src/maploader.zig @@ -139,8 +139,6 @@ pub const TBMap = struct { } self.colliderSpecs.deinit(self.allocator); - physics.context().system.update(0.001, .{}) catch {}; - self.shapes.deinit(self.allocator); self.root.destroy(); diff --git a/projects/build.zig b/projects/build.zig index 7d97265..8060841 100644 --- a/projects/build.zig +++ b/projects/build.zig @@ -21,6 +21,7 @@ pub fn build(b: *std.Build) void { sampleGame.setModuleEnabled("audio", true); sampleGame.setModuleEnabled("physics", true); sampleGame.setModuleEnabled("ui", true); + sampleGame.setModuleEnabled("sys", true); sampleGame.addExtraModule("gameExtras"); sampleGame.addExtraModule("videoplayer"); sampleGame.addExtraModule("doomplayer"); diff --git a/projects/content/_shaders/dxil/lit_mesh.frag.dxil b/projects/content/_shaders/dxil/lit_mesh.frag.dxil index 581026e448eeacdb7c82921c0a8f848838e9a9f1..e86567e67550c9dc239856aac7f229cef8910eaf 100644 GIT binary patch delta 57 zcmV-90LK5^LEJ$UL|8&Ytr_qArfru@p!T5N*F!BOE%iDr*6K3^Ho8 PYqM+*E9R_ delta 57 zcmV-90LK5^LEJ$UL|8&Y?L+O|B-X;>HjocUtpwP$u@p!T5PB|;MtC4AsrL;XbnA)O PnzL*V 1.0) { - float4 _288 = float4(0.0, 0.0, 0.0, 1.0); + float4 _288 = float4(0.0); _288.x = _272.x; _289 = _288; } else { - _289 = float4(0.0, 0.0, 0.0, 1.0); + _289 = float4(0.0); } float4 _294; if (_272.y > 1.0) diff --git a/projects/content/_shaders/spv/lit_mesh.frag.spv b/projects/content/_shaders/spv/lit_mesh.frag.spv index 59dfd2a3a089bf03b70c0b0dae4836c75bcd0611..4b7c0490ab0f4a6ac5ae778bcc07abf0086f22c5 100644 GIT binary patch delta 2578 zcmYk6ZERFk5QgtUKiIamU2b=`+ikm)U0j!?)KY3iC~f%=i4v%oASxlK#8g8N65|g) z+J=y53`BE?Mh#j_{DA>2F+@QDF=9+?qo{~zh<_wOlO_-~!jC3C@45Fh-Ryg3=AAin zXXc!9M|wtjM*k=uoauR9(JS$qk#oVdX?7O979_lxUJf}2C|3GB;CVx*oPDdcy)#Mt zd341n_X4lX+P9%=jpBrG-Jn;%_-FD!k4rQkTR&$P(aVOf^teO|u(d{U^0~NH^dpTA zop$y@?9tt`&bW1L*jlGJ`GUAX&$}ICMzOrt1-4@=P`q9er=vy4IY2)xl-*&iz}EB@ zgBidT&}sccQ;pq$Jw8^|s|j_XYeFRt@L1rLTjEZ11x<%bwgkT7Vs@Fc@4_A*yKgG_ zQfz*~l+5vHKBn}`!T8u%w{6W#M3aMJdqLaDtIJ)(eIX}aaP_P}*8rx&y?-UV=RMu$ z>{ZtGdY!%6+Cx+J-PXRguut8u!B8QZmMh{ObT#2%6PaTbek5nkRot7>#HPdL$eBWA zx<#H6(99?skn4cB3BO{?-_C|D_*e-LqG8#k2=zci4S-3+7F*KkVjh^kqPN5P5cXF|Nz|4p4r{J&HCF-|tknBS00c z0Pljm;S>&`kA!$B}!t300oRjs?Hs@g5=6c+>E6z^yeu3`l z_!3<;$RE_vo(Sp)taXWWLD|m%b@vr;yZCj;uX3DuE#cdFd;=q|rWVw3B9V>c&E-Uz z=gmYWr4O_2UKes4jDeuX_GE@V>QDN8n)~-aU2Op00ZpineR>di9@K*t;Bx&C^5MLa z8C%a!us;H23p|&S#gtp8_gn-&1A7lmQ+={qU0(thz%Rgc{cFfCMY`Mh8@hOXF#B}| z&8~W%PWRS##FhPbpcr*BNY^`b8Z ztr@GcoEb;RlLoEULLNNFF3<3jlpS%!hB1_ETpQ+o3)J@x*BNg zVMd1=i%pt!E#3++fnI~G2Ei<^H~KqN#cY^uNJQX4`XM(1J^Z$Lb#O7Dc=^?n&4i3& zZ%69qxJ1Yy!Z+?}@|$!r>!Gwl5lJwW$sB6(3#zFBR+aOg%9jqgshZ5?raWKU(q?^O d+ne>Z-ORJo3|r=?WiD7|(lUjNV)`@d{|BkOHpTz| delta 2578 zcmYjRYiL|W6rP*+CNbH~&D}?KH=Fd@tm`I?>*ir>(_~F+En1Qop;iqgYLFQHiF7{;0H?B1KzGW5tSKf>y1yO7M??Dg;_oY<>j%zPU3Y%YOHq^PMy2 zo^xjAPW4RnO#e}uzb=GGiy~1Exeo9HK~X4N$OeEu>bC+yjL#T*y|Tq@2>vGMj41?~ zMTxSL(7A?jgjshR^nX^4^k_RTQXu#<0k=ahnON*GiPEsSh;j6pxMt`lV~?CSb_?w3 z{bjRe-3HiP$2j^-Tr2c~bZM^_mlxs=5DcV)FLBUO2C@O*j|*wvsVvXtw6Z_}U=p_} z|G4Q)w8NgCtL){3I-qkxML@GCRdy%z_J{ab114kgy8w>UB=3S=e#PBn?7Lyl&pojE zvW>9u^QI=x_>uv>ZZj}HH`lFtl}o-*o@_7BdhXh0GpU^B$P=c(d!Tb525iv0zYn?) z&*qH1McJa)*jtr7zG~mA?CTqHoW?d7EQHfDMcfCSO&F*|@^ravx$84uE^cQBt~cw4&4MkdqaOMxNFNL_Y{=X+P~D=!HOsT&QrZjI=7< z0Q1tf3zF5kAGcTTw$`(F3&C_h2AHmgp$jqIMPHLVdrN1IFB<_^TsNMy9|wxH%?wWf zCE8}OPXeXdZjza*G>RFnN;{3+^p|qfIeQ~BjDIA?up`g8x1$EIo>qGO=ymnYQQ__ za>yUB+T^JJ0BZZwpTsi|NaNWZc&df{zYbUcH|{ln7h@UYJ`8zN%YT_mUJ69f*;3#c zwJ~qO|0d8c$}sJ*nylKFcfh<29M;{u3w;wn-iy3YlXiHS-vgMR@&KcyW!vrSb_!rc zyaDe62lW(=LZ8xjMRUhsx5@2xA1XU!yLg_qhwv<}rJky7-O7v~0;d4prIWxptmZy` z1klI3bprds*lB<~Ir=Ke%gNe)hr4qI7y;Oq>QP#b+d|JL0ITNRW7TF)K7~#n&s`q$DM@AdL9hlHv_N|zG)UPZ=zqF9C^dB)rt#iyk9^! zb$kh(HPG+XkqLTrc-D?!G{x)}0e1HlV0Q6q&2KTBd?RS9d3*zgUQW%c<808in&d(- zisy1L5#fiLcaLXn9+(5X9y6f?_GmC<=Q#K80d_S2dep>B446}Sxi0+_CU)%-?Cb31>7PM#mk zL7qXmFKnaJgW;^h?7styVJCTX?aKLZ)@NqmN?#=5W85N;l9|X(D=S}(Jc>CiM*5(q z>RQzu_z(WS0dw|mLMO*>++OB|Tn7FERE#`Sw->j1r7ooEuvh?rA8!}#LNpoSsv@w3 z0M9pP%+6dn7R`6jTMW-NNOQkRV6#^8Di8Ehy_!Dn3^&HS)8GU1Eh5SwSyhwV9!sFB zu~-jgbRw3HbJl)%%Yh~6)sR(yH_IC_dk?Fq0W$&#;dvl!%@sh`-!@STE&wo|e)gm? zK{~KUA^9_0P;(Iajr-zuoF_93iYpiq0#-B0qj5XMn(Dx^a{O2GMK!ltlU#@=@wF|k f=NC3p&#&z+Jlo`iVooXMvSL;glS(jVFwy@%B;Ph5 diff --git a/projects/sampleGame/externGame/externGame.zig b/projects/sampleGame/externGame/externGame.zig index 853f0b0..32670cd 100644 --- a/projects/sampleGame/externGame/externGame.zig +++ b/projects/sampleGame/externGame/externGame.zig @@ -3,6 +3,7 @@ pub export fn startup(p_allocator: *anyopaque, p_a: ?*anyopaque) bool { _ = allocator; imgui.setupFromModule(); platform.setupFromModule(); + sys.setupFromModule(); rend.setupFromModule(); backlog.physics.setupFromModule(); // TODO backlog.setupFromModule @@ -70,7 +71,6 @@ pub const ExternGameObject = struct { core.engine_log("map loaded", .{}); } - pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try Slack.create(allocator); self.* = .{ @@ -254,6 +254,7 @@ const imgui = backlog.imgui; const physics = backlog.physics; const rend = backlog.rend; const ig = imgui.api; +const sys = backlog.sys; const ui = backlog.ui; const platform = backlog.platform; const extras = @import("gameExtras");