diff --git a/engine/core/src/math.zig b/engine/core/src/math.zig index 9144439..0f74acb 100644 --- a/engine/core/src/math.zig +++ b/engine/core/src/math.zig @@ -10,9 +10,9 @@ const pod = lua.pod; // LUA END // vector versions. -pub const f32x4 = @Vector(4, f32); -pub const f32x8 = @Vector(8, f32); -pub const f32x16 = @Vector(16, f32); +pub const f32x4 = @Vector(4, f32); // __m128_int +pub const f32x8 = @Vector(8, f32); // __m256_int +pub const f32x16 = @Vector(16, f32); // __m512_int pub const f32x4_zero = std.mem.zeroes(@Vector(4, f32)); pub const f32x8_zero = std.mem.zeroes(@Vector(8, f32)); diff --git a/engine/rend/shaders/meshes.vert.hlsl b/engine/rend/shaders/meshes.vert.hlsl index 9a14135..43d77ed 100644 --- a/engine/rend/shaders/meshes.vert.hlsl +++ b/engine/rend/shaders/meshes.vert.hlsl @@ -85,20 +85,21 @@ Output main(Input input) if(billboard > 0) { float3 billboardPosition = mul(scene[input.Instance].Model, float4(0,0,0,1)).xyz; - float3 toCamera = normalize(billboardPosition - cameraPosition.xyz); + float3 toCamera = normalize(cameraPosition.xyz - billboardPosition); float3 up = float3(0,1,0); float3 right = normalize(cross(up, toCamera)); up = cross(toCamera, right); + //toCamera = float3(0, 0, -1); float d = length(cameraPosition.xyz - billboardPosition); - float perspectiveScale = d * 0.1f; // adjust multiplier as needed + float perspectiveScale = 1.0f; // adjust multiplier as needed float finalSize = scene[input.Instance].float0 * perspectiveScale; float3 wp = billboardPosition + - mul(mul(right, input.Position.x), finalSize) + - mul(mul(right, input.Position.y), finalSize); + mul(mul(right, -input.Position.x), finalSize) + + mul(mul(up, input.Position.y), finalSize); WorldPos = float4(wp, 1.0); diff --git a/engine/rend/src/particles/particles.zig b/engine/rend/src/particles/particles.zig index 36e0f4a..cf2bd2f 100644 --- a/engine/rend/src/particles/particles.zig +++ b/engine/rend/src/particles/particles.zig @@ -287,6 +287,10 @@ pub const ParticleEmitter = struct { } pub fn update(self: *@This(), dt: f64) void { + if (self.state == .paused) { + return; + } + if (self.state != .dead) { self.updateSpawn(dt); } diff --git a/engine/rend/src/sgpu/ParticleRenderer.zig b/engine/rend/src/sgpu/ParticleRenderer.zig index 051a5ea..1c3e48c 100644 --- a/engine/rend/src/sgpu/ParticleRenderer.zig +++ b/engine/rend/src/sgpu/ParticleRenderer.zig @@ -6,6 +6,8 @@ spans: std.ArrayListUnmanaged(core.Span) = .{}, renderInfo: std.ArrayListUnmanaged(SgpuParticleRenderInfo) = .{}, +lastParticleCount: u32 = 0, + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.ParticleRenderer"); const SgpuParticleRenderInfo = struct { @@ -58,10 +60,10 @@ pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void { uploadMapped[i + offset] = .{ .Model = final, - .textureMode = 0x2, //0x2, // default 0x2 is fullbright + .textureMode = if (emitter.billboard) 0x2 else 0x0, //0x2, // default 0x2 is fullbright .animation = -1, .float0 = size, - .flags = 0, //0x4, + .flags = if (emitter.billboard) 0x4 else 0, //0x4 for billboard mode }; } @@ -70,6 +72,8 @@ pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void { offset += emitter.finals.items.len; } + self.lastParticleCount = @intCast(offset); + if (self.renderInfo.items.len == 0) return; @@ -121,7 +125,7 @@ pub fn destroy(self: *@This()) void { self.allocator.destroy(self); } -const MaxParticleCount = 1_000_000; +const MaxParticleCount = 10_000_000; const assets = @import("assets"); const core = @import("core"); diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 7a9080b..42f1ed3 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -44,6 +44,8 @@ pub const Renderer = struct { depthTexture: *gpu.GPUTexture = undefined, depthFormat: gpu.GPUTextureFormat = .textureformatD32Float, + transparentDepthTexture: *gpu.GPUTexture = undefined, + textureList: *TextureList = undefined, shadowMapProjection: core.Transform = core.zm.identity(), @@ -398,6 +400,7 @@ pub const Renderer = struct { gci.usage = .{ .textureusageDepthStencilTarget = true }; self.depthTexture = self.device.createGPUTexture(&gci); + self.transparentDepthTexture = self.device.createGPUTexture(&gci); } pub fn discoverFormats(self: *@This()) !void { @@ -696,6 +699,7 @@ pub const Renderer = struct { ptr.ViewTransform = @bitCast(camera.transform); ptr.ViewProjection = @bitCast(camera.final); ptr.NoTranslateView = @bitCast(camera.noTranslate); + ptr.cameraPosition = @bitCast(camera.finalPos.toZm()); } ptr.ShadowMapProjection = @bitCast(self.shadowMapProjection); // ptr.ViewProjection = @bitCast(self.shadowMapProjection); @@ -963,6 +967,45 @@ pub const Renderer = struct { self.state.pass = null; } + pub fn renderTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + 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, + }), + }; + + const depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{ + .texture = self.transparentDepthTexture, + .load_op = .loadopDontCare, + .store_op = .storeopDontCare, + .stencil_load_op = .loadopDontCare, + .stencil_store_op = .storeopDontCare, + .clear_depth = 1.0, + .clear_stencil = 0, + }); + + const renderpass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget); + + renderpass.endGPURenderPass(); + } + pub fn drawPostProcess(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { const postProcTargetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ .texture = self.state.swapchainTargetTexture.?, diff --git a/projects/content/_shaders/dxil/meshes.vert.dxil b/projects/content/_shaders/dxil/meshes.vert.dxil index dd3a943..562754a 100644 Binary files a/projects/content/_shaders/dxil/meshes.vert.dxil and b/projects/content/_shaders/dxil/meshes.vert.dxil differ diff --git a/projects/content/_shaders/msl/meshes.vert.msl b/projects/content/_shaders/msl/meshes.vert.msl index 4cff0f8..1cf9fc6 100644 --- a/projects/content/_shaders/msl/meshes.vert.msl +++ b/projects/content/_shaders/msl/meshes.vert.msl @@ -60,61 +60,60 @@ struct main0_in vertex main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], const device type_StructuredBuffer_Scene& scene [[buffer(1)]], const device type_StructuredBuffer_BoneTransform& animationBuffer [[buffer(2)]], uint gl_InstanceIndex [[instance_id]]) { main0_out out = {}; - float3 _112; + float3 _111; if (scene._m0[gl_InstanceIndex].animation != (-1)) { - float3 _84; - _84 = float3(0.0); - for (int _87 = 0; _87 < 4; ) + float3 _83; + _83 = float3(0.0); + for (int _86 = 0; _86 < 4; ) { - uint _93 = (8u * uint(_87)) & 31u; - _84 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _93) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _93) & 255u) * 0.0039215688593685626983642578125)); - _87++; + uint _92 = (8u * uint(_86)) & 31u; + _83 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _92) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _92) & 255u) * 0.0039215688593685626983642578125)); + _86++; continue; } - _112 = _84; + _111 = _83; } else { - _112 = in.in_var_TEXCOORD0; + _111 = in.in_var_TEXCOORD0; } - float4 _116 = float4(_112, 1.0); - float3 _210; - float3 _211; - float3 _212; - float4 _213; - float4 _214; + float4 _115 = float4(_111, 1.0); + float3 _207; + float3 _208; + float3 _209; + float4 _210; + float4 _211; if (int(scene._m0[gl_InstanceIndex].flags & 4u) > 0) { - float3 _128 = (scene._m0[gl_InstanceIndex].Model * float4(0.0, 0.0, 0.0, 1.0)).xyz; - float3 _133 = fast::normalize(_128 - Uniforms.cameraPosition.xyz); - float3 _135 = fast::normalize(cross(float3(0.0, 1.0, 0.0), _133)); - float _141 = scene._m0[gl_InstanceIndex].float0 * (length(Uniforms.cameraPosition.xyz - _128) * 0.100000001490116119384765625); - float4 _155 = float4((_128 + ((_135 * in.in_var_TEXCOORD0.x) * _141)) + ((_135 * in.in_var_TEXCOORD0.y) * _141), 1.0); - _210 = _155.xyz; - _211 = _133; - _212 = float3(0.0, 0.0, 1.0); - _213 = Uniforms.ViewProjection * _155; - _214 = _155; + float3 _127 = (scene._m0[gl_InstanceIndex].Model * float4(0.0, 0.0, 0.0, 1.0)).xyz; + float3 _132 = fast::normalize(Uniforms.cameraPosition.xyz - _127); + float3 _134 = fast::normalize(cross(float3(0.0, 1.0, 0.0), _132)); + float4 _152 = float4((_127 + ((_134 * (-in.in_var_TEXCOORD0.x)) * scene._m0[gl_InstanceIndex].float0)) + ((cross(_132, _134) * in.in_var_TEXCOORD0.y) * scene._m0[gl_InstanceIndex].float0), 1.0); + _207 = _152.xyz; + _208 = _132; + _209 = float3(0.0, 0.0, 1.0); + _210 = Uniforms.ViewProjection * _152; + _211 = _152; } else { - float4 _162 = scene._m0[gl_InstanceIndex].Model * _116; - float4x4 _197 = float4x4(float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][0], scene._m0[gl_InstanceIndex].Model[1][0], scene._m0[gl_InstanceIndex].Model[2][0])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][1], scene._m0[gl_InstanceIndex].Model[1][1], scene._m0[gl_InstanceIndex].Model[2][1])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][2], scene._m0[gl_InstanceIndex].Model[1][2], scene._m0[gl_InstanceIndex].Model[2][2])), 0.0), float4(0.0, 0.0, 0.0, 1.0)); - float4 _201 = float4(in.in_var_TEXCOORD1, 1.0); - _210 = _162.xyz; - _211 = fast::normalize(_201 * _197).xyz; - _212 = (_201 * (_197 * transpose(Uniforms.NoTranslateView))).xyz; - _213 = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _116); - _214 = _162; + float4 _159 = scene._m0[gl_InstanceIndex].Model * _115; + float4x4 _194 = float4x4(float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][0], scene._m0[gl_InstanceIndex].Model[1][0], scene._m0[gl_InstanceIndex].Model[2][0])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][1], scene._m0[gl_InstanceIndex].Model[1][1], scene._m0[gl_InstanceIndex].Model[2][1])), 0.0), float4(fast::normalize(float3(scene._m0[gl_InstanceIndex].Model[0][2], scene._m0[gl_InstanceIndex].Model[1][2], scene._m0[gl_InstanceIndex].Model[2][2])), 0.0), float4(0.0, 0.0, 0.0, 1.0)); + float4 _198 = float4(in.in_var_TEXCOORD1, 1.0); + _207 = _159.xyz; + _208 = fast::normalize(_198 * _194).xyz; + _209 = (_198 * (_194 * transpose(Uniforms.NoTranslateView))).xyz; + _210 = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _115); + _211 = _159; } out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3; - out.out_var_TEXCOORD1 = _210; - out.out_var_TEXCOORD2 = _211; - out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _214; + out.out_var_TEXCOORD1 = _207; + out.out_var_TEXCOORD2 = _208; + out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _211; out.out_var_TEXCOORD4 = gl_InstanceIndex; - out.out_var_TEXCOORD5 = _212; - out.gl_Position = _213; + out.out_var_TEXCOORD5 = _209; + out.gl_Position = _210; return out; } diff --git a/projects/content/_shaders/spv/meshes.vert.spv b/projects/content/_shaders/spv/meshes.vert.spv index ac4afe7..7c3da46 100644 Binary files a/projects/content/_shaders/spv/meshes.vert.spv and b/projects/content/_shaders/spv/meshes.vert.spv differ diff --git a/projects/sampleGame/externGame/externGame.zig b/projects/sampleGame/externGame/externGame.zig index 3e51c77..5f113e5 100644 --- a/projects/sampleGame/externGame/externGame.zig +++ b/projects/sampleGame/externGame/externGame.zig @@ -99,8 +99,10 @@ pub const ExternGameObject = struct { pub fn particleDebug(self: *@This()) void { if (ig.begin("particleDebugger", null, .{})) { var buffer: [256]u8 = undefined; + ig.textFmt("active particles: {d}", .{rend.context().particleRenderer.lastParticleCount}) catch unreachable; for (rend.ParticleEmitter.BaseContainer.dense.items, 0..) |*emitter, i| { ig.textFmt("emitter {d}", .{emitter.sparseIndex.index}) catch {}; + ig.sameLine(0, 10); if (ig.smallButton(std.fmt.bufPrintZ(&buffer, "edit##{d}", .{i}) catch unreachable)) { self.editParticle = emitter.value.entity; } @@ -142,6 +144,20 @@ pub const ExternGameObject = struct { _ = ig.inputInt("maxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{}); _ = ig.checkbox("showDebug", &emitter._showDebug); + _ = ig.checkbox("useLocalScene", &emitter.useLocalScene); + _ = ig.checkbox("billboard", &emitter.billboard); + + if (ig.smallButton("alive")) { + emitter.state = .alive; + } + ig.sameLine(0, 10); + if (ig.smallButton("kill")) { + emitter.state = .dead; + } + ig.sameLine(0, 10); + if (ig.smallButton("pause")) { + emitter.state = .paused; + } } ig.end(); }