From f7b3d03b40092f21bcd3fb4ef19525f028710c97 Mon Sep 17 00:00:00 2001 From: peterino2 Date: Sun, 1 Jun 2025 22:10:41 -0700 Subject: [PATCH] crates! --- engine/core/src/scene.zig | 3 +- engine/rend/shaders/meshes.vert.hlsl | 5 +- engine/rend/shaders/ssao.frag.hlsl | 4 +- engine/rend/src/meshes/gltfLoader.zig | 1 + engine/rend/src/sgpu/renderer.zig | 5 +- extras/bsp/src/maploader.zig | 8 +- extras/gameExtras/src/ecsObject.zig | 0 .../content/_shaders/dxil/meshes.vert.dxil | Bin 7312 -> 7596 bytes projects/content/_shaders/msl/meshes.vert.msl | 5 +- projects/content/_shaders/spv/meshes.vert.spv | Bin 3500 -> 3520 bytes projects/content/meshes/Crate.obj | 673 ++++++++++++++++++ projects/content/textures/Crate.png | Bin 0 -> 11607 bytes projects/sampleGame/externGame/externGame.zig | 30 +- projects/sampleGame/main.zig | 8 + 14 files changed, 729 insertions(+), 13 deletions(-) create mode 100644 extras/gameExtras/src/ecsObject.zig create mode 100644 projects/content/meshes/Crate.obj create mode 100644 projects/content/textures/Crate.png diff --git a/engine/core/src/scene.zig b/engine/core/src/scene.zig index c42588b..5115476 100644 --- a/engine/core/src/scene.zig +++ b/engine/core/src/scene.zig @@ -240,7 +240,8 @@ pub const Scene = struct { const settings = Scene.SceneObjectContainer.get(self.handle, .settings).?; if (settings.sceneMode == .static) { if (mobility == .moveable) { - core.gScene.dynamicObjects.append(core.gScene.allocator, self.handle) catch unreachable; + const gScene = getSceneSystem(); + gScene.dynamicObjects.append(gScene.allocator, self.handle) catch unreachable; } } diff --git a/engine/rend/shaders/meshes.vert.hlsl b/engine/rend/shaders/meshes.vert.hlsl index e01f73c..45c9b79 100644 --- a/engine/rend/shaders/meshes.vert.hlsl +++ b/engine/rend/shaders/meshes.vert.hlsl @@ -86,7 +86,10 @@ Output main(Input input) output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz; float4x4 noTranslateScreen = mul(NoTranslateView, noTranslate); - output.ScreenNormal = mul(NoTranslateView, float4(input.Normal, 1.0)).xyz; + output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz; + + + // output.ScreenNormal = mul(noTranslateScreen, float4(input.Normal, 1.0)).xyz; // output.ScreenNormal = input.Normal; // output.ScreenNormal = float4(input.Normal, 1.0).xyz; diff --git a/engine/rend/shaders/ssao.frag.hlsl b/engine/rend/shaders/ssao.frag.hlsl index 58a8e5e..2f5c2e4 100644 --- a/engine/rend/shaders/ssao.frag.hlsl +++ b/engine/rend/shaders/ssao.frag.hlsl @@ -52,7 +52,7 @@ float4 main(float2 UV: TEXCOORD0) : SV_Target0 x = (normal + 1.0) * 0.5; // -1 -> 0 . 1.0 -> 1.0 0 -> 0.5 - x = tangent; + // x = tangent; //for(int i = 0; i < numSamples; i += 1) for(int i = 0; i < numSamples; i += 1) { @@ -100,7 +100,7 @@ float4 main(float2 UV: TEXCOORD0) : SV_Target0 c = occlusion; //float j = x.z; - // c = float4(x, 1.0); + //c = float4(x, 1.0); return c + occlusion * 0.00001; } diff --git a/engine/rend/src/meshes/gltfLoader.zig b/engine/rend/src/meshes/gltfLoader.zig index 3b6ff91..5a678c5 100644 --- a/engine/rend/src/meshes/gltfLoader.zig +++ b/engine/rend/src/meshes/gltfLoader.zig @@ -86,6 +86,7 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor } } else if (accessor.component_type == .unsigned_integer) { parser.getDataFromBufferView(u32, &indexList, accessor, @alignCast(binaryBytes)); + // ... do we need to rotate winding orders? } } diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 37db816..f0ef7f4 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -37,7 +37,7 @@ pub const Renderer = struct { preDraws: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer) void }) = .{}, depthTexture: *gpu.GPUTexture = undefined, - depthFormat: gpu.GPUTextureFormat = .textureformatD16Unorm, + depthFormat: gpu.GPUTextureFormat = .textureformatD32Float, textureList: *TextureList = undefined, @@ -59,7 +59,7 @@ pub const Renderer = struct { directionalLightColor: core.colors.Color = .{ .r = 0.8, .g = 0.8, .b = 0.9 }, directionalLightDir: core.Vectorf = core.Vectorf.new(0.5, -0.5, 0.0).normalize(), - shadowDepthFormat: gpu.GPUTextureFormat = .textureformatD16Unorm, + shadowDepthFormat: gpu.GPUTextureFormat = .textureformatD32Float, shadowDepthTexture: *gpu.GPUTexture = undefined, shadowDepthDebugOutput: *gpu.GPUTexture = undefined, shadowCastingPipeline: *gpu.GPUGraphicsPipeline = undefined, @@ -485,6 +485,7 @@ pub const Renderer = struct { pci.rasterizer_state.fill_mode = .fillmodeFill; pci.rasterizer_state.cull_mode = .cullmodeBack; + pci.rasterizer_state.front_face = .frontfaceClockwise; self.meshPipe = self.device.createGPUGraphicsPipeline(&pci); } diff --git a/extras/bsp/src/maploader.zig b/extras/bsp/src/maploader.zig index 34e5ed6..a27f9ed 100644 --- a/extras/bsp/src/maploader.zig +++ b/extras/bsp/src/maploader.zig @@ -226,15 +226,15 @@ pub const MeshBuilder = struct { } // generate ngons - try self.indexList.append(self.meshAlloc, indexStart); - try self.indexList.append(self.meshAlloc, indexStart + 1); try self.indexList.append(self.meshAlloc, indexStart + 2); + try self.indexList.append(self.meshAlloc, indexStart + 1); + try self.indexList.append(self.meshAlloc, indexStart); for (3..count) |j| { const i: u32 = @intCast(j); - try self.indexList.append(self.meshAlloc, indexStart); - try self.indexList.append(self.meshAlloc, indexStart + i - 1); try self.indexList.append(self.meshAlloc, indexStart + i); + try self.indexList.append(self.meshAlloc, indexStart + i - 1); + try self.indexList.append(self.meshAlloc, indexStart); } } }; diff --git a/extras/gameExtras/src/ecsObject.zig b/extras/gameExtras/src/ecsObject.zig new file mode 100644 index 0000000..e69de29 diff --git a/projects/content/_shaders/dxil/meshes.vert.dxil b/projects/content/_shaders/dxil/meshes.vert.dxil index ba9b61e43a1cb112022f6e3f73a5111712da6a9d..147b51a227f5228efe28bd6d4fabace1c5d4f75c 100644 GIT binary patch delta 1847 zcmZvd4NMbf7{}kX$8og>Tq)MG8`yH}Kt(J_7_y4JQY$Rr2P{i*nw0v*rcRcbjm<9Q z+5)Y%P*Y=C#v%e+7G(*@Hkp}8TVMj)nD{l_5>r1WBr}^~8e}ZX-a@Zs*^*0h?e%^B z|KI<4-uK+=dtQ=h^_r4F(afgc_XnD0uan!BZn=@d0|4}-_Q?hWytn$V3DS7U7JNvF z4=UYNO)QD68dKwg{mT+*o@XUGjvV_;DfG;t4FB?6e{pd4o~s80BABEfDsX>DBv3xn;W$77;G*MwESnU}dX?yOUk(0Xov|0lF*I>&$V%FH zq@5uf0(O?yASczTGf8aR9{CE%h`PAI&6;{v#?LxQIlwGt=And|I9Z}JHiQ@7-s;v? zC9-R#RJl$1-3d-PWny?auj*!=&OS9fdACkE_1K9t$B_e}C= z5kjE}kVAeZuIzcOIw@X!WiaC64K|sLbC}8tAM7qsoEBRJuzvBtti-DCyUFo7t@3eq-#7|Gm17>D)SoHx@mN{ya6*;4bRkkI2j zK4Al71!0-6F=T}t{qQe!F@<8#h?~__tBw*2xQtY`uP?+zXnnQq!`tK8>dq)_DYd41 zBS*VB;fuOwaxzyP7W^*%re@UY&#Q9(5TX5aLV6<$(wgU0K5lwV+rg=PB0D_sgfXq^{*sIzQ8qkg$wPDb!Vvvjcl1;zpIB zS6m1@)o_z)3h7RXSVy4H99{nB71!_4<&Sp1IIs)r!N;QFcQ+rlGliV@Uz!h_E)jZK z##ukO(SJYL#aaIwYkfJNFA9Ppov(?@W-e*kT~0-^!L?(8JeQwu&TDAda25{q!iLcy z8)P@Q=29n~=wG3FLwLtJV_kTI{pjduK4>4Q)c_}r1!{wGCru361L0k|Gy7`V1vb4) z$Wyk-kuITC*`~%RG#<`y-LT#CSm$ukh`-iCIB7gs%g=R^&%+HI*lVU{#A(@iZ3O5N zYLsnCtV=j#sM-=uC6#yLGR=irpP@bFyYBM>NG3_Q0Q0nyxTN(x<1700Mqt13=xwpFjYKo8kXD{n&ju4}hQ80crBD z|Ie;qQG{y28TNk&j|B)ZiX@Kg7q76K7Uj<=#Gl9ErNA)YCcqS`MkQWXa|MUJ)`{l> zj@xArtpKb)0qfswCxDED`K>qggcc7^dX@egz96ebhFgkl{O4enP)!U5-|X`==M#%X z_7>`R`fFaaC?)7a;6W$uD3Pa57o!u{L)jKC4k=}jQj1A)gME5sBMmehYU#agf&;flc+)S zl6WP(pcn{HPsfhB1*de{u95?j$V;ef0+YyR3(bQv0q^ptKk+@#KI;XzRp6fWYH_Qq zRp?;@t#b6y!d9I-$0TAADlNw(!fYxRZsMf?G&p~c`mvyf=eXmnO~Q3b(WssFiQ3F}1iiUQP+l1&uTwRrTlWwlfIvN0=PJ2ve7BH| zLIvT9`W-!LPJYoQINJp3hv08lm1|#`!eV|VUW?T&u9NJ`&du(m4^>R z`cf!q=ReA!`%-7nlT{d1|fhA)*2TeMMv3jxeNPS2~6|E;DkxZ*4pN(}1 zJyh2!8*&Ua4&&eBxh7sJtWVhmQeY#~?(#o~B0vDIv3j7i!X5(>Z-G#V55(AWwL#6OBb6_8JAU*!^KR!jt63p zoIe8xgCdYl2V#(T+T@Kq;*1%S6?ugvGlBdJAcpD70F36MTJ S24)6cAZ-i8e}S&B0Ac_RjuY4b delta 145 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