diff --git a/engine/backlog.zig b/engine/backlog.zig index 6544ca1..8842d7b 100644 --- a/engine/backlog.zig +++ b/engine/backlog.zig @@ -15,7 +15,7 @@ const modulelist = @import("modulelist.zig").list; const std = @import("std"); pub const NwArgs = struct { - useGPA: bool = true, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations + useGPA: bool = false, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations vulkanValidation: bool = true, fastTest: bool = false, dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations diff --git a/engine/core/src/math.zig b/engine/core/src/math.zig index 1ec005c..f0ba558 100644 --- a/engine/core/src/math.zig +++ b/engine/core/src/math.zig @@ -557,6 +557,14 @@ pub const Rotation = struct { return .{}; } + pub fn add(self: @This(), other: @This()) Rotation { + const m1 = zm.quatToMat(self.quat); + const m2 = zm.quatToMat(other.quat); + + const r = zm.mul(m1, m2); + return .{ .quat = zm.matToQuat(r) }; + } + pub fn eulerX(o: f32) @This() { return .{ .quat = zm.matToQuat(zm.rotationX((o))), diff --git a/engine/imgui/src/sgpu/backend_impl.zig b/engine/imgui/src/sgpu/backend_impl.zig index f0098d1..41e6913 100644 --- a/engine/imgui/src/sgpu/backend_impl.zig +++ b/engine/imgui/src/sgpu/backend_impl.zig @@ -57,7 +57,7 @@ pub const Impl = struct { //const renderpass = cmd.beginGPURenderPass(color_target_infos: [*c]const GPUColorTargetInfo, num_color_targets: u32, depth_stencil_target_info: [*c]const GPUDepthStencilTargetInfo); var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo); - targetInfo.texture = rend.context().state.swapchainTexture.?; + targetInfo.texture = rend.context().state.swapchainTargetTexture.?; targetInfo.clear_color = .{ .r = 0.0, .g = 0.0, .b = 0.0, .a = 0.0 }; targetInfo.load_op = .loadopLoad; targetInfo.store_op = .storeopStore; diff --git a/engine/rend/build.zig b/engine/rend/build.zig index 40a4efc..832ab05 100644 --- a/engine/rend/build.zig +++ b/engine/rend/build.zig @@ -44,6 +44,9 @@ pub fn build(b: *std.Build) void { sdl3.shaderDefintion(b, mod, "../../lib/sdl3", optimize, "skybox.frag", b.path("shaders/skybox.frag.json")); sdl3.shaderDefintion(b, mod, "../../lib/sdl3", optimize, "skybox.vert", b.path("shaders/skybox.vert.json")); + sdl3.shaderDefintion(b, mod, "../../lib/sdl3", optimize, "postProc.frag", b.path("shaders/postProc.frag.json")); + sdl3.shaderDefintion(b, mod, "../../lib/sdl3", optimize, "postProc.vert", b.path("shaders/postProc.vert.json")); + // ========== tests ========== const tests = b.addTest(.{ .target = target, diff --git a/engine/rend/shaders/lit_mesh.frag.hlsl b/engine/rend/shaders/lit_mesh.frag.hlsl index b711fe6..4ba7820 100644 --- a/engine/rend/shaders/lit_mesh.frag.hlsl +++ b/engine/rend/shaders/lit_mesh.frag.hlsl @@ -154,7 +154,6 @@ float shadowCalculationPCF(float3 fragPos, float4 DirectionalShadowFragPos) float3 DirectionalLight(float3 normal, float3 fragPos, float4 DirectionalShadowFragPos) { - float3 lightDir = directionalLight.xyz; float diff = max(dot(lightDir, normal), 0.0); float3 diffuse = diff * directionalLightColor.xyz; @@ -174,6 +173,14 @@ float3 DirectionalLight(float3 normal, float3 fragPos, float4 DirectionalShadow return diffuse; } +float3 reinhard2(float3 x) { + const float L_white = 4.0; + + const float3 a = 1.0 + x / (L_white * L_white); + const float3 x2 = x * a; + const float3 x3 = 1.0 + x; + return x2 / x3; +} float4 main( @@ -242,7 +249,7 @@ float4 main( if((texMode & 0x2) > 0) // full bright no lighting bit { - c2 = col; + c2 = col * 4; } diff --git a/engine/rend/shaders/postProc.frag.hlsl b/engine/rend/shaders/postProc.frag.hlsl new file mode 100644 index 0000000..0d2452a --- /dev/null +++ b/engine/rend/shaders/postProc.frag.hlsl @@ -0,0 +1,12 @@ +Texture2D Texture0 : register(t0, space2); +SamplerState Sampler0 : register(s0, space2); + +float4 main(float2 UV : TEXCOORD0) : SV_Target0 +{ + float2 uv = UV; + uv.y *= -1; + + float4 color = Texture0.Sample(Sampler0, uv); + + return color; +} diff --git a/engine/rend/shaders/postProc.frag.json b/engine/rend/shaders/postProc.frag.json new file mode 100644 index 0000000..e0a47ec --- /dev/null +++ b/engine/rend/shaders/postProc.frag.json @@ -0,0 +1,38 @@ +{ + "entryPoints" : [ + { + "name" : "main", + "mode" : "frag" + } + ], + "inputs" : [ + { + "type" : "vec2", + "name" : "in.var.TEXCOORD0", + "location" : 0 + } + ], + "outputs" : [ + { + "type" : "vec4", + "name" : "out.var.SV_Target0", + "location" : 0 + } + ], + "separate_images" : [ + { + "type" : "texture2D", + "name" : "Texture0", + "set" : 2, + "binding" : 0 + } + ], + "separate_samplers" : [ + { + "type" : "sampler", + "name" : "Sampler0", + "set" : 2, + "binding" : 0 + } + ] +} \ No newline at end of file diff --git a/engine/rend/shaders/postProc.vert.hlsl b/engine/rend/shaders/postProc.vert.hlsl new file mode 100644 index 0000000..16650ab --- /dev/null +++ b/engine/rend/shaders/postProc.vert.hlsl @@ -0,0 +1,26 @@ +struct Input +{ + float3 Position : TEXCOORD0; + float3 Normal : TEXCOORD1; + float4 Color : TEXCOORD2; + float2 UV : TEXCOORD3; + uint Bones : TEXCOORD4; + uint weights : TEXCOORD5; + + uint Instance : SV_InstanceID; +}; + +struct Output +{ + float2 UV : TEXCOORD0; + float4 Position : SV_Position; +}; + +Output main(Input input) +{ + Output output; + output.Position = float4(input.Position, 1.0); + output.UV = input.UV; + + return output; +} diff --git a/engine/rend/shaders/postProc.vert.json b/engine/rend/shaders/postProc.vert.json new file mode 100644 index 0000000..9d09f1a --- /dev/null +++ b/engine/rend/shaders/postProc.vert.json @@ -0,0 +1,27 @@ +{ + "entryPoints" : [ + { + "name" : "main", + "mode" : "vert" + } + ], + "inputs" : [ + { + "type" : "vec3", + "name" : "in.var.TEXCOORD0", + "location" : 0 + }, + { + "type" : "vec2", + "name" : "in.var.TEXCOORD3", + "location" : 3 + } + ], + "outputs" : [ + { + "type" : "vec2", + "name" : "out.var.TEXCOORD0", + "location" : 0 + } + ] +} \ No newline at end of file diff --git a/engine/rend/src/sgpu/DebugDrawSystem.zig b/engine/rend/src/sgpu/DebugDrawSystem.zig index e0a2bda..a93de37 100644 --- a/engine/rend/src/sgpu/DebugDrawSystem.zig +++ b/engine/rend/src/sgpu/DebugDrawSystem.zig @@ -197,7 +197,7 @@ pub fn createPipeline(self: *@This()) !*gpu.GPUGraphicsPipeline { pci.target_info.num_color_targets = 1; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ - .format = self.device.getGPUSwapchainTextureFormat(rend.context().window), + .format = rend.context().hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), }, }; diff --git a/engine/rend/src/sgpu/SkyboxSystem.zig b/engine/rend/src/sgpu/SkyboxSystem.zig index 255afcf..8ff755b 100644 --- a/engine/rend/src/sgpu/SkyboxSystem.zig +++ b/engine/rend/src/sgpu/SkyboxSystem.zig @@ -61,7 +61,7 @@ fn createPipeline(self: *@This()) !void { pci.target_info.num_color_targets = 1; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ - .format = self.device.getGPUSwapchainTextureFormat(ctx.window), + .format = ctx.hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), }, }; @@ -85,7 +85,7 @@ pub fn destroy(self: *@This()) void { pub fn render(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = rend.context().state.swapchainTexture.?, + .texture = rend.context().state.targetTexture, .clear_color = self.skyboxColor, .load_op = .loadopClear, .store_op = .storeopStore, @@ -102,6 +102,7 @@ pub fn render(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { } const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); + if (self.skyboxTexture) |skyboxTexture| { if (self.skyboxMesh) |skyboxMesh| { const ctx = rend.context(); diff --git a/engine/rend/src/sgpu/embedded/screenPlane.obj b/engine/rend/src/sgpu/embedded/screenPlane.obj new file mode 100644 index 0000000..7467525 --- /dev/null +++ b/engine/rend/src/sgpu/embedded/screenPlane.obj @@ -0,0 +1,15 @@ +# Blender 4.4.3 +# www.blender.org +o Plane +v -1.000000 1.000000 0.000000 +v 1.000000 1.000000 0.000000 +v -1.000000 -1.000000 -0.000000 +v 1.000000 -1.000000 -0.000000 +vn -0.0000 1.0000 -0.0000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +s 0 +f 1/1/1 2/2/1 4/3/1 3/4/1 + diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 15ab3e8..c781c51 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -72,6 +72,12 @@ pub const Renderer = struct { state: RendererState = .{}, // swapchainTexture: ?*gpu.GPUTexture = undefined, + swapchainTargetFormat: gpu.GPUTextureFormat = undefined, + hdrTextureFormat: gpu.GPUTextureFormat = undefined, + postProcessingPipeline: *gpu.GPUGraphicsPipeline = undefined, + + screenPlane: ?rend.IndexedMesh = null, + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); pub const MaxObjectCount = 50000; @@ -86,9 +92,28 @@ pub const Renderer = struct { try core.defineComponent(rend.MeshComponent, allocator); try core.defineComponent(rend.CameraComponent, allocator); + self.hdrTextureFormat = .textureformatR16g16b16a16Float; return self; } + pub fn createHDRTexture(self: *@This()) !void { + var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); + + gci.type = .texturetype2d; + gci.format = self.hdrTextureFormat; + gci.width = @intCast(platform.getInstance().windowExtent.x); + gci.height = @intCast(platform.getInstance().windowExtent.y); + gci.layer_count_or_depth = 1; + gci.num_levels = 1; + gci.sample_count = .samplecount1; + gci.usage = .{ + .textureusageSampler = true, + .textureusageColorTarget = true, + }; + + self.state.targetTexture = self.device.createGPUTexture(&gci); + } + pub fn startRenderer(self: *@This()) !void { self.device = gpu.createGPUDevice(.{ .shaderformatSpirv = true, @@ -110,6 +135,8 @@ pub const Renderer = struct { try self.createMeshPipeline(); try self.createBuffers(); try self.createDepthTexture(); + try self.createHDRTexture(); + try self.createPostProcessingPipeline(); self.meshPool = try self.createRendererObject(MeshPool); self.textureList = try self.createRendererEngineObject(TextureList); @@ -141,6 +168,8 @@ pub const Renderer = struct { _ = try core.fs().installFileBytesMount("embedded:plane.obj", @constCast(&plane_obj), true); + _ = try core.fs().installFileBytesMount("embedded:screenPlane.obj", @constCast(&screenPlane_obj), true); + try assets.load( assets.MakeImportRefOptions( "Mesh", @@ -148,6 +177,49 @@ pub const Renderer = struct { .{ .path = "embedded:plane.obj" }, ), ); + + try assets.load( + assets.MakeImportRefOptions( + "Mesh", + "m_screenPlane", + .{ .path = "embedded:screenPlane.obj" }, + ), + ); + } + + pub fn createPostProcessingPipeline(self: *@This()) !void { + const vertex = try self.loadShader("postProc.vert", postProcVert.LoadArgs); + const fragment = try self.loadShader("postProc.frag", postProcFrag.LoadArgs); + + var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); + pci.vertex_shader = vertex; + pci.fragment_shader = fragment; + + 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), + }; + + core.graphics_log("hdr texture format format: {any}", .{self.hdrTextureFormat}); + pci.target_info.num_color_targets = 1; + pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ + .{ + .format = self.swapchainTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + }; + + pci.rasterizer_state.cull_mode = .cullmodeNone; + pci.rasterizer_state.fill_mode = .fillmodeFill; + + self.postProcessingPipeline = self.device.createGPUGraphicsPipeline(&pci); } pub fn createDirectionalShadowsPipeline(self: *@This()) !void { @@ -340,12 +412,14 @@ pub const Renderer = struct { pci.depth_stencil_state.enable_depth_write = true; pci.depth_stencil_state.write_mask = 0xff; + 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 = 1; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ - .format = self.device.getGPUSwapchainTextureFormat(self.window), + .format = self.hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), }, }; @@ -606,8 +680,8 @@ pub const Renderer = struct { pub fn draw(self: *@This()) void { const cmd = self.state.cmd.?; - if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, @ptrCast(&self.state.swapchainTexture), null, null)) { - if (self.state.swapchainTexture == null) { + if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, @ptrCast(&self.state.swapchainTargetTexture), null, null)) { + if (self.state.swapchainTargetTexture == null) { _ = cmd.submitGPUCommandBuffer(); return; } @@ -623,7 +697,7 @@ pub const Renderer = struct { // can cache this const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ - .texture = self.state.swapchainTexture.?, + .texture = self.state.targetTexture, .load_op = .loadopLoad, .store_op = .storeopStore, }); @@ -640,6 +714,8 @@ pub const Renderer = struct { self.state.pass = cmd.beginGPURenderPass(&targetInfo, 1, &depthTarget); const renderpass = self.state.pass.?; + renderpass.setGPUScissor(&self.scissor); + //renderpass.bindGPUGraphicsPipeline(self.testPipeline); renderpass.bindGPUFragmentSamplers(1, &.{ .sampler = self.blockySampler, .texture = self.defaultTexture.texture }, 1); renderpass.bindGPUFragmentSamplers(2, &.{ .sampler = self.blockySampler, .texture = self.defaultTexture.texture }, 1); @@ -654,8 +730,6 @@ pub const Renderer = struct { renderpass.bindGPUFragmentSamplers(self.shadowDepthTextureSlot, &.{ .texture = self.shadowDepthTexture, .sampler = self.blockySampler }, 1); // todo move into materials system - renderpass.setGPUScissor(&self.scissor); - try self.uploadUniforms(cmd); //rendering each mesh { @@ -686,15 +760,35 @@ pub const Renderer = struct { for (self.postMesh.items) |interface| { interface.func(interface.ptr, cmd, renderpass); } - renderpass.endGPURenderPass(); + { + const postProcTargetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.state.swapchainTargetTexture.?, + .load_op = .loadopDontCare, + .store_op = .storeopStore, + }); + + const postProcPass = cmd.beginGPURenderPass(&postProcTargetInfo, 1, null); + + postProcPass.bindGPUGraphicsPipeline(self.postProcessingPipeline); + postProcPass.bindGPUFragmentSamplers(0, &.{ .sampler = self.blockySampler, .texture = self.state.targetTexture }, 1); + + // post processing + hdr etc... + if (self.screenPlane == null) { + self.screenPlane = getMesh("m_screenPlane"); + } + + if (self.screenPlane) |mesh| { + postProcPass.drawGPUIndexedPrimitives(mesh.index.size, 1, mesh.index.start, @intCast(mesh.vertex.start), 0); + } + + postProcPass.endGPURenderPass(); + } + for (self.postRenders.items) |interface| { interface.func(interface.ptr, cmd); } - - // renderpass.drawGPUPrimitives(3, 1, 0, 0); - } _ = cmd.submitGPUCommandBuffer(); @@ -734,6 +828,9 @@ const lit_mesh_frag = @import("lit_mesh.frag"); const depthOnly = @import("depthOnly.frag"); const sample_vert = @import("sample.vert"); +const postProcVert = @import("postProc.vert"); +const postProcFrag = @import("postProc.frag"); + const MeshVertices = meshes_vert.Scene; const MeshUniforms = meshes_vert.Uniforms; @@ -801,10 +898,12 @@ pub const RendererState = struct { copyPass: ?*gpu.GPURenderPass = null, pass: ?*gpu.GPURenderPass = null, cmd: ?*gpu.GPUCommandBuffer = null, - swapchainTexture: ?*gpu.GPUTexture = null, + swapchainTargetTexture: ?*gpu.GPUTexture = null, + targetTexture: *gpu.GPUTexture = undefined, }; pub const CustomMeshRenderFunc = *const fn (?*anyopaque) void; pub const GPUTextureType = gpu.GPUTexture; const plane_obj align(8) = @embedFile("embedded/plane.obj").*; +const screenPlane_obj align(8) = @embedFile("embedded/screenPlane.obj").*; diff --git a/extras/doomplayer/src/doom.zig b/extras/doomplayer/src/doom.zig index 8140b3e..fad5491 100644 --- a/extras/doomplayer/src/doom.zig +++ b/extras/doomplayer/src/doom.zig @@ -7,18 +7,75 @@ texture: *gpu.GPUTexture = undefined, width: u32, height: u32, - inputEnabled: bool = false, sensitivity: f32 = 1.0, -entity: core.Entity, - fn log(comptime fmt: []const u8, args: anytype) void { core.engine_log("[Doomplayer] " ++ fmt, args); } -pub fn create(allocator: std.mem.Allocator) !*@This() { +pub const DoomCanvas = struct { + data: core.GameObjectData = undefined, + entity: core.Entity, + first: bool = false, + + pub fn create(alloc: std.mem.Allocator) !*@This() { + var first: bool = false; + if (gDoom == null) { + first = true; + gDoom = try createDoom(alloc); + } + + if (gDoom) |doomCtx| { + const self = try alloc.create(@This()); + self.first = first; + + const entity = try core.createEntity(); + const scene = entity.addComponent(core.Scene).?; + const size = 5.0; + const h: f32 = @floatFromInt(doomCtx.height); + const w: f32 = @floatFromInt(doomCtx.width); + + scene.setScale(size, size, size * (h / w)); + scene.setRotation(core.Rotation.eulerX(core.radians(90.0))); + scene.setPosition(.{ .z = 30 }); + + if (entity.addComponent(rend.MeshComponent)) |mesh| { + mesh.cmrf = bindVideoTextures; + mesh.cmrf_ctx = doomCtx; + mesh.textureMode.fullbright = true; + mesh.textureMode.noSrgb = true; + mesh.setMesh("m_plane"); + } + self.entity = entity; + + return self; + } + + return error.ContextNotReady; + } + + pub fn tick(self: *@This(), dt: f64) void { + if (self.first) { + gDoom.?.tick(dt); + } + } + + pub fn getEntity(self: *@This()) core.Entity { + return self.entity; + } + + pub fn destroy(self: *@This()) void { + self.entity.destroy(); + if (self.first) { + gDoom.?.destroy(); + } + self.data.release(self); + } +}; + +pub fn createDoom(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); self.* = .{ .allocator = allocator, @@ -28,8 +85,6 @@ pub fn create(allocator: std.mem.Allocator) !*@This() { log("initialized", .{}); - try self.setup(); - self.sensitivity = core.configVar(f32, "doomplayer.sensitivity", 1.0); gDoom = self; @@ -44,11 +99,13 @@ pub fn create(allocator: std.mem.Allocator) !*@This() { c.doom_set_default_int("mouse_move", 0); // Mouse will not move forward c.doom_init(1, @constCast(@ptrCast(@alignCast(&.{"doom"}))), 8); - - self.entity = try self.createEntity(); return self; } +pub fn getEntity(self: *@This()) core.Entity { + return self.entity; +} + fn sdlToDoomButton(button: c_uint) c_uint { switch (button) { sdl3_c.SDL_BUTTON_LEFT => { @@ -290,34 +347,36 @@ fn sdlToDoomScancode(sdlScancode: c_uint) c_int { return c.DOOM_KEY_UNKNOWN; } -var gDoom: *@This() = undefined; +pub var gDoom: ?*@This() = null; pub fn processFunc(e: *sdl3.Event) void { - if (!gDoom.inputEnabled) { - return; - } + if (gDoom) |ctx| { + if (!ctx.inputEnabled) { + return; + } - switch (e.type) { - else => {}, - sdl3_c.SDL_EVENT_MOUSE_MOTION => { - c.doom_mouse_move(@intFromFloat(e.motion.xrel * 4 * gDoom.sensitivity), @intFromFloat(e.motion.yrel * 4 * gDoom.sensitivity)); - }, - sdl3_c.SDL_EVENT_MOUSE_BUTTON_DOWN => { - c.doom_button_down(sdlToDoomButton(e.button.button)); - }, - sdl3_c.SDL_EVENT_MOUSE_BUTTON_UP => { - c.doom_button_up(sdlToDoomButton(e.button.button)); - }, - sdl3_c.SDL_EVENT_KEY_DOWN => { - if (!e.key.repeat) { - c.doom_key_down(sdlToDoomScancode(e.key.scancode)); - } - }, - sdl3_c.SDL_EVENT_KEY_UP => { - if (!e.key.repeat) { - c.doom_key_up(sdlToDoomScancode(e.key.scancode)); - } - }, + switch (e.type) { + else => {}, + sdl3_c.SDL_EVENT_MOUSE_MOTION => { + c.doom_mouse_move(@intFromFloat(e.motion.xrel * 4 * ctx.sensitivity), @intFromFloat(e.motion.yrel * 4 * ctx.sensitivity)); + }, + sdl3_c.SDL_EVENT_MOUSE_BUTTON_DOWN => { + c.doom_button_down(sdlToDoomButton(e.button.button)); + }, + sdl3_c.SDL_EVENT_MOUSE_BUTTON_UP => { + c.doom_button_up(sdlToDoomButton(e.button.button)); + }, + sdl3_c.SDL_EVENT_KEY_DOWN => { + if (!e.key.repeat) { + c.doom_key_down(sdlToDoomScancode(e.key.scancode)); + } + }, + sdl3_c.SDL_EVENT_KEY_UP => { + if (!e.key.repeat) { + c.doom_key_up(sdlToDoomScancode(e.key.scancode)); + } + }, + } } } @@ -418,26 +477,6 @@ fn bindVideoTextures(p: ?*anyopaque) void { } // creates a video player entity -pub fn createEntity(self: *@This()) !core.Entity { - const entity = try core.createEntity(); - const scene = entity.addComponent(core.Scene).?; - const size = 5.0; - const h: f32 = @floatFromInt(self.height); - const w: f32 = @floatFromInt(self.width); - - scene.setScale(size, size, size * (h / w)); - scene.setRotation(core.Rotation.eulerX(core.radians(90.0))); - scene.setPosition(.{ .z = 30 }); - - if (entity.addComponent(rend.MeshComponent)) |mesh| { - mesh.cmrf = bindVideoTextures; - mesh.cmrf_ctx = self; - mesh.textureMode.fullbright = true; - mesh.textureMode.noSrgb = true; - mesh.setMesh("m_plane"); - } - return entity; -} pub fn destroy(self: *@This()) void { core.engine_logs("[Videoplayer] destroying player"); diff --git a/extras/gameExtras/src/objectSpawner.zig b/extras/gameExtras/src/objectSpawner.zig index c7e1533..da4f059 100644 --- a/extras/gameExtras/src/objectSpawner.zig +++ b/extras/gameExtras/src/objectSpawner.zig @@ -3,6 +3,7 @@ objectList: *core.GameObjectList, windowOpen: bool = true, spawnFuncs: std.ArrayListUnmanaged(SpawnEntry) = .{}, spawnPosition: core.Vectorf = .{}, +spawnRotation: core.Rotation = .{}, pub const SpawnEntry = struct { typeName: []const u8, @@ -44,6 +45,9 @@ pub fn addSpawnFunction(self: *@This(), comptime name: []const u8, comptime T: t pub fn prepareEntity(self: *@This(), entity: core.Entity) void { if (entity.fetch(core.Scene)) |scene| { scene.setPosition(self.spawnPosition); + scene.setRotation(scene.getRotation().add(self.spawnRotation)); + + _ = scene.getAndResolveTransform(); } } diff --git a/projects/content/_shaders/dxil/lit_mesh.frag.dxil b/projects/content/_shaders/dxil/lit_mesh.frag.dxil index 177d655..1a192f4 100644 Binary files a/projects/content/_shaders/dxil/lit_mesh.frag.dxil and b/projects/content/_shaders/dxil/lit_mesh.frag.dxil differ diff --git a/projects/content/_shaders/dxil/postProc.frag.dxil b/projects/content/_shaders/dxil/postProc.frag.dxil new file mode 100644 index 0000000..2948cb9 Binary files /dev/null and b/projects/content/_shaders/dxil/postProc.frag.dxil differ diff --git a/projects/content/_shaders/dxil/postProc.vert.dxil b/projects/content/_shaders/dxil/postProc.vert.dxil new file mode 100644 index 0000000..ce70167 Binary files /dev/null and b/projects/content/_shaders/dxil/postProc.vert.dxil differ diff --git a/projects/content/_shaders/msl/lit_mesh.frag.msl b/projects/content/_shaders/msl/lit_mesh.frag.msl index cec1381..53707a1 100644 --- a/projects/content/_shaders/msl/lit_mesh.frag.msl +++ b/projects/content/_shaders/msl/lit_mesh.frag.msl @@ -47,101 +47,110 @@ struct main0_in fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], const device type_StructuredBuffer_Scene& scene [[buffer(1)]], texture2d Texture0 [[texture(0)]], texture2d Texture1 [[texture(1)]], texture2d Texture2 [[texture(2)]], texture2d DirectionalShadowDepthMap [[texture(3)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]], sampler Sampler2 [[sampler(2)]], sampler DirectionalShadowSampler [[sampler(3)]]) { main0_out out = {}; - int _98 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); - int _99 = _98 & 240; - float4 _133; - if (_99 == 16) + int _97 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); + int _98 = _97 & 240; + float4 _132; + if (_98 == 16) { - float3 _120 = float3(Texture0.sample(Sampler0, in.in_var_TEXCOORD0).x, Texture1.sample(Sampler1, in.in_var_TEXCOORD0).x, Texture2.sample(Sampler2, in.in_var_TEXCOORD0).x) + float3(-0.0625, -0.5, -0.5); - _133 = float4(dot(_120, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_120, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_120, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); + float3 _119 = float3(Texture0.sample(Sampler0, in.in_var_TEXCOORD0).x, Texture1.sample(Sampler1, in.in_var_TEXCOORD0).x, Texture2.sample(Sampler2, in.in_var_TEXCOORD0).x) + float3(-0.0625, -0.5, -0.5); + _132 = float4(dot(_119, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_119, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_119, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); } else { - float4 _132; - if (_99 == 0) + float4 _131; + if (_98 == 0) { - _132 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); + _131 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); } else { - _132 = _86; + _131 = _86; } - _133 = _132; + _132 = _131; } - float4 _139; - if ((_98 & 1) == 1) + float4 _138; + if ((_97 & 1) == 1) { - _139 = powr(_133, float4(2.2000000476837158203125)); + _138 = powr(_132, float4(2.2000000476837158203125)); } else { - _139 = _133; + _138 = _132; } - if (_139.w < 0.00999999977648258209228515625) + if (_138.w < 0.00999999977648258209228515625) { discard_fragment(); } - float3 _193; + float3 _192; do { - float3 _150 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; - float _151 = length(_150); - float _152 = _151 * _151; - float _158; - if (_151 > 2.0) + float3 _149 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; + float _150 = length(_149); + float _151 = _150 * _150; + float _157; + if (_150 > 2.0) { - _158 = 0.5 / _152; + _157 = 0.5 / _151; } else { - _158 = 1.0 / _152; + _157 = 1.0 / _151; } - float _163; - if (_151 > 4.0) + float _162; + if (_150 > 4.0) { - _163 = _158 * 0.5; + _162 = _157 * 0.5; } else { - _163 = _158; + _162 = _157; } - float _165 = (_151 > 15.0) ? 0.0 : _163; - float _167 = (_165 > 1.0) ? 1.0 : _165; + float _164 = (_150 > 15.0) ? 0.0 : _162; + float _166 = (_164 > 1.0) ? 1.0 : _164; if (length(in.in_var_TEXCOORD2) < 0.100000001490116119384765625) { - _193 = (in.in_var_TEXCOORD1 * float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5)) * _167; + _192 = (in.in_var_TEXCOORD1 * float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5)) * _166; break; } - float3 _174 = fast::normalize(_150); - _193 = ((float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * precise::max(dot(_174, in.in_var_TEXCOORD2), 0.0)) * _167) + (((float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_174 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _167); + float3 _173 = fast::normalize(_149); + _192 = ((float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * precise::max(dot(_173, in.in_var_TEXCOORD2), 0.0)) * _166) + (((float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_173 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _166); break; } while(false); - float3 _210 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); - float3 _212; - _212.x = _210.x; - float2 _213 = _212.xy; - _213.y = -_210.y; + float3 _209 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); + float3 _211; + _211.x = _209.x; + float2 _212 = _211.xy; + _212.y = -_209.y; + float _219; + int _222; + int _224; + _219 = 0.0; + _222 = 0; + _224 = -4; float _220; int _223; - int _225; - _220 = 0.0; - _223 = 0; - _225 = -4; - float _221; - int _224; - for (; _225 <= 4; _220 = _221, _223 = _224, _225++) + for (; _224 <= 4; _219 = _220, _222 = _223, _224++) { - _224 = _223; - _221 = _220; - for (int _234 = -4; _234 <= 4; ) + _223 = _222; + _220 = _219; + for (int _233 = -4; _233 <= 4; ) { - _224++; - _221 += float((in.in_var_TEXCOORD3.z - 0.004999999888241291046142578125) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_213 + float2(float(_234) * 0.000244140625, float(_225) * 0.000244140625))).x); - _234++; + _223++; + _220 += float((in.in_var_TEXCOORD3.z - 0.004999999888241291046142578125) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_212 + float2(float(_233) * 0.000244140625, float(_224) * 0.000244140625))).x); + _233++; continue; } } - out.out_var_SV_Target0 = float4(powr(select(_139.xyz * ((float3(0.100000001490116119384765625) + _193) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_220 / float(_223))))), _139.xyz, bool3((_98 & 2) > 0)), float3(0.4545454680919647216796875)), _139.w); + float3 _262; + if ((_97 & 2) > 0) + { + _262 = _138.xyz * 4.0; + } + else + { + _262 = _138.xyz * ((float3(0.100000001490116119384765625) + _192) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_219 / float(_222))))); + } + out.out_var_SV_Target0 = float4(powr(_262, float3(0.4545454680919647216796875)), _138.w); return out; } diff --git a/projects/content/_shaders/msl/postProc.frag.msl b/projects/content/_shaders/msl/postProc.frag.msl new file mode 100644 index 0000000..6d2534e --- /dev/null +++ b/projects/content/_shaders/msl/postProc.frag.msl @@ -0,0 +1,24 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 out_var_SV_Target0 [[color(0)]]; +}; + +struct main0_in +{ + float2 in_var_TEXCOORD0 [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture0 [[texture(0)]], sampler Sampler0 [[sampler(0)]]) +{ + main0_out out = {}; + float2 _19 = in.in_var_TEXCOORD0; + _19.y = -_19.y; + out.out_var_SV_Target0 = Texture0.sample(Sampler0, _19); + return out; +} + diff --git a/projects/content/_shaders/msl/postProc.vert.msl b/projects/content/_shaders/msl/postProc.vert.msl new file mode 100644 index 0000000..ecdc597 --- /dev/null +++ b/projects/content/_shaders/msl/postProc.vert.msl @@ -0,0 +1,25 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float2 out_var_TEXCOORD0 [[user(locn0)]]; + float4 gl_Position [[position]]; +}; + +struct main0_in +{ + float3 in_var_TEXCOORD0 [[attribute(0)]]; + float2 in_var_TEXCOORD3 [[attribute(3)]]; +}; + +vertex main0_out main0(main0_in in [[stage_in]]) +{ + main0_out out = {}; + out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3; + out.gl_Position = float4(in.in_var_TEXCOORD0, 1.0); + return out; +} + diff --git a/projects/content/_shaders/spv/lit_mesh.frag.spv b/projects/content/_shaders/spv/lit_mesh.frag.spv index fe17a6a..e72f745 100644 Binary files a/projects/content/_shaders/spv/lit_mesh.frag.spv and b/projects/content/_shaders/spv/lit_mesh.frag.spv differ diff --git a/projects/content/_shaders/spv/postProc.frag.spv b/projects/content/_shaders/spv/postProc.frag.spv new file mode 100644 index 0000000..d030ccb Binary files /dev/null and b/projects/content/_shaders/spv/postProc.frag.spv differ diff --git a/projects/content/_shaders/spv/postProc.vert.spv b/projects/content/_shaders/spv/postProc.vert.spv new file mode 100644 index 0000000..30bf6db Binary files /dev/null and b/projects/content/_shaders/spv/postProc.vert.spv differ diff --git a/projects/sampleGame/main.zig b/projects/sampleGame/main.zig index fa087c2..4bbe649 100644 --- a/projects/sampleGame/main.zig +++ b/projects/sampleGame/main.zig @@ -16,9 +16,7 @@ showWindow: bool = true, fpcamera: *FpCamera = undefined, videoplayer: *VideoPlayer = undefined, -doomplayer: *DoomPlayer = undefined, videoplayerObject: core.Entity = undefined, -doomplayerObject: core.Entity = undefined, objectSpawner: *extras.ObjectSpawner = undefined, @@ -119,15 +117,13 @@ pub fn prepare(self: *@This()) !void { self.objectSpawner = try extras.ObjectSpawner.create(self.allocator); try self.objectSpawner.addSpawnFunction("fox", FoxObject); + try self.objectSpawner.addSpawnFunction("doomplayer", DoomPlayer.DoomCanvas); try assets.loadList(assetReferences); self.videoplayer = try VideoPlayer.create(self.allocator); try self.videoplayer.startPlayback("LAPWING2.ogv"); self.videoplayerObject = try self.videoplayer.createVideoPlayerEntity(); - self.doomplayer = try DoomPlayer.create(self.allocator); - self.doomplayerObject = try self.doomplayer.createEntity(); - rend.setSkyboxTexture("t_skybox"); const exitInput = try core.ActionBinding.create(core.MakeName("exit")); @@ -158,26 +154,6 @@ pub fn prepare(self: *@This()) !void { empireMesh.setTexture("t_empire"); } - { - // const fox = try core.createEntity(); - // const scene = fox.addComponent(core.Scene).?; - // _ = scene; - // // scene.setScale(); - // const mesh = fox.addComponent(rend.MeshComponent).?; - // mesh.setMesh("m_fox"); - // mesh.setTexture("t_fox"); - } - - { - // const lightbox = try core.createEntity(); - // const scene = lightbox.addComponent(core.Scene).?; - // scene.setPosition(.{ .z = 20 }); - // scene.setScale(0.1, 0.1, 0.1); - // const mesh = lightbox.addComponent(rend.MeshComponent).?; - // mesh.setMesh("m_default_cube"); - // mesh.setTexture("t_default"); - } - const moveInput = try core.Axis2dBinding.create(core.MakeName("movement")); moveInput.addKey(.w, 1.0, .y); @@ -248,8 +224,11 @@ fn toggleDoom(ctx: ?*anyopaque, action: core.ActionEvent) void { const self: *@This() = @ptrCast(@alignCast(ctx)); _ = action; - self.doomplayer.inputEnabled = !self.doomplayer.inputEnabled; - self.inputEnabled = !self.doomplayer.inputEnabled; + self.inputEnabled = !self.inputEnabled; + + if (DoomPlayer.gDoom) |c| { + c.inputEnabled = !self.inputEnabled; + } } fn toggleMouseLook(ctx: ?*anyopaque, action: core.ActionEvent) void { @@ -328,7 +307,6 @@ pub fn tick(self: *@This(), dt: f64) void { extras.inputDebugger.tick(); self.objectSpawner.tick(dt); self.videoplayer.tick(dt); - self.doomplayer.tick(dt); self.fpcamera.tick(dt); var movement = self.fpcamera.getForwardXZ().fmul(self.moveVector.z * fdt * self.cameraSpeed); @@ -347,6 +325,7 @@ pub fn tick(self: *@This(), dt: f64) void { const forward = self.fpcamera.getForward(); const debugCenter = self.fpcamera.getPosition().add(forward.fmul(self.centerDist)); self.objectSpawner.spawnPosition = debugCenter; + self.objectSpawner.spawnRotation = core.Rotation.eulerY(core.radians(self.fpcamera.yaw)); if (self.moveLight) { core.debugSphere(debugCenter, 0.3, .{}); @@ -376,7 +355,7 @@ pub fn tick(self: *@This(), dt: f64) void { } pub fn deinit(self: *@This()) void { - self.doomplayer.destroy(); + // self.doomplayer.destroy(); self.fpcamera.destroy(); self.objectSpawner.destroy();