diff --git a/engine/rend/shaders/lit_mesh.frag.hlsl b/engine/rend/shaders/lit_mesh.frag.hlsl index 9e9d451..2bfe7a6 100644 --- a/engine/rend/shaders/lit_mesh.frag.hlsl +++ b/engine/rend/shaders/lit_mesh.frag.hlsl @@ -21,16 +21,7 @@ cbuffer Uniforms : register(b0, space3) float time; }; -struct Scene -{ - float4x4 Model; - - uint textureMode; // 0 = regular triple, - // 0x10 = video yuv, - uint pad0; // 0 = regular triple, - uint pad1; // 0 = regular triple, - uint pad2; // 0 = regular triple, -}; +#include "sceneShared.hlsli" StructuredBuffer scene: register(t4, space2); @@ -247,7 +238,7 @@ PixelOutput main( if((texMode & 0x2) > 0) // full bright no lighting bit { - c2 = col * 2.0; + c2 = pow(col, 1.0/2.2); } // float4 rv = float4(pow(c2, 1.0 / 2.2), alpha); diff --git a/engine/rend/shaders/lit_mesh.frag.json b/engine/rend/shaders/lit_mesh.frag.json index c88358d..3706c00 100644 --- a/engine/rend/shaders/lit_mesh.frag.json +++ b/engine/rend/shaders/lit_mesh.frag.json @@ -62,18 +62,18 @@ "offset" : 64 }, { - "name" : "pad0", - "type" : "uint", + "name" : "animation", + "type" : "int", "offset" : 68 }, { - "name" : "pad1", + "name" : "flags", "type" : "uint", "offset" : 72 }, { - "name" : "pad2", - "type" : "uint", + "name" : "float0", + "type" : "float", "offset" : 76 } ] diff --git a/engine/rend/shaders/meshes.vert.hlsl b/engine/rend/shaders/meshes.vert.hlsl index 09cfea8..9a14135 100644 --- a/engine/rend/shaders/meshes.vert.hlsl +++ b/engine/rend/shaders/meshes.vert.hlsl @@ -5,42 +5,8 @@ uint getCharFromUintArray(uint color, uint index) return uint((color >> 8 * index) & 0xFF); } -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 TexCoord : TEXCOORD0; - float3 WorldPos : TEXCOORD1; - float3 Normal: TEXCOORD2; - float4 DirectionalShadowFragPos: TEXCOORD3; - uint Instance: TEXCOORD4; - float3 ScreenNormal: TEXCOORD5; - - float4 Position : SV_Position; -}; - -struct Scene -{ - float4x4 Model; - - uint textureMode; // 0 = regular triple, - // 0x10 = video yuv, - - int animation; // -1 means no animation, any non-zero value means an index into the animationBuffer - uint flags; // 0 -> 0: always in front - // 1 -> 1: useAltCamera - uint pad2; -}; +#include "vertexShared.hlsli" +#include "sceneShared.hlsli" StructuredBuffer scene: register(t0, space0); @@ -55,7 +21,9 @@ cbuffer Uniforms : register(b0, space1) { float4x4 ViewProjection; float4x4 NoTranslateView; + float4x4 ViewTransform; float4x4 ShadowMapProjection; + float4 cameraPosition; float time; }; @@ -110,23 +78,56 @@ Output main(Input input) // pos.x += 0.2 * sin(time * 0.5 ) * pos.y * 0.5; // pos.y += 0.2 * cos(time * 0.5 ) * pos.z * 0.5; + int billboard = scene[input.Instance].flags & 0x4; + + float4 WorldPos; + + if(billboard > 0) + { + float3 billboardPosition = mul(scene[input.Instance].Model, float4(0,0,0,1)).xyz; + float3 toCamera = normalize(billboardPosition - cameraPosition.xyz); + + float3 up = float3(0,1,0); + float3 right = normalize(cross(up, toCamera)); + up = cross(toCamera, right); + + float d = length(cameraPosition.xyz - billboardPosition); + float perspectiveScale = d * 0.1f; // 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); + + WorldPos = float4(wp, 1.0); + + output.Position = mul(ViewProjection, WorldPos); + output.WorldPos = WorldPos.xyz; + + output.Normal = toCamera; + output.ScreenNormal = float3(0, 0, 1); + } + else + { + // todo. maybe all world position values should be + // transformed into screen space + WorldPos = mul(scene[input.Instance].Model, pos); + output.Position = mul(ViewProjection, mul(scene[input.Instance].Model, pos)); + output.WorldPos = WorldPos.xyz; + + float4x4 noTranslate = ExtractRotation(scene[input.Instance].Model); + output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz; + + float4x4 noTranslateScreen = mul(NoTranslateView, noTranslate); + 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; + } + - // todo. maybe all world position values should be - // transformed into screen space - float4 WorldPos = mul(scene[input.Instance].Model, pos); - output.Position = mul(ViewProjection, mul(scene[input.Instance].Model, pos)); - output.WorldPos = WorldPos.xyz; - - float4x4 noTranslate = ExtractRotation(scene[input.Instance].Model); - output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz; - - float4x4 noTranslateScreen = mul(NoTranslateView, noTranslate); - 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; output.DirectionalShadowFragPos = mul(ShadowMapProjection, WorldPos); output.Instance = input.Instance; diff --git a/engine/rend/shaders/meshes.vert.json b/engine/rend/shaders/meshes.vert.json index 1d2b116..a855b2f 100644 --- a/engine/rend/shaders/meshes.vert.json +++ b/engine/rend/shaders/meshes.vert.json @@ -32,8 +32,8 @@ "offset" : 72 }, { - "name" : "pad2", - "type" : "uint", + "name" : "float0", + "type" : "float", "offset" : 76 } ] @@ -102,16 +102,28 @@ "row_major" : true }, { - "name" : "ShadowMapProjection", + "name" : "ViewTransform", "type" : "mat4", "offset" : 128, "matrix_stride" : 16, "row_major" : true }, + { + "name" : "ShadowMapProjection", + "type" : "mat4", + "offset" : 192, + "matrix_stride" : 16, + "row_major" : true + }, + { + "name" : "cameraPosition", + "type" : "vec4", + "offset" : 256 + }, { "name" : "time", "type" : "float", - "offset" : 192 + "offset" : 272 } ] } @@ -197,7 +209,7 @@ { "type" : "_22", "name" : "type.Uniforms", - "block_size" : 196, + "block_size" : 276, "set" : 1, "binding" : 0 } diff --git a/engine/rend/shaders/sceneShared.hlsli b/engine/rend/shaders/sceneShared.hlsli new file mode 100644 index 0000000..eaf113d --- /dev/null +++ b/engine/rend/shaders/sceneShared.hlsli @@ -0,0 +1,26 @@ +struct Scene +{ + float4x4 Model; + + uint textureMode; // 0 = regular triple, + // 0x10 = video yuv, + // bit 0 == srgb correction + // bit 1 == fullbright + // bit 2 = reserved + // bit 3 = reserved + // bit 4 - 7 = color space: + // 0 -> regular rgb + // 1 -> regular video yuv // used for decoding video files + + int animation; // -1 means no animation, any non-zero value means an index into the animationBuffer + uint flags; // 0 -> 0: always in front + // 1 -> 1: useAltCamera + // 2 -> 2: billboard (& 0x4) + float float0; // uses: + // in billboard mode: this represents the size +}; + +uint isBillboard(Scene s) +{ + return s.flags & 0x4; +} diff --git a/engine/rend/shaders/vertexShared.hlsli b/engine/rend/shaders/vertexShared.hlsli new file mode 100644 index 0000000..9c9ce33 --- /dev/null +++ b/engine/rend/shaders/vertexShared.hlsli @@ -0,0 +1,23 @@ +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 TexCoord : TEXCOORD0; + float3 WorldPos : TEXCOORD1; + float3 Normal: TEXCOORD2; + float4 DirectionalShadowFragPos: TEXCOORD3; + uint Instance: TEXCOORD4; + float3 ScreenNormal: TEXCOORD5; + + float4 Position : SV_Position; +}; diff --git a/engine/rend/src/particles/particles.zig b/engine/rend/src/particles/particles.zig index db01462..c66e43f 100644 --- a/engine/rend/src/particles/particles.zig +++ b/engine/rend/src/particles/particles.zig @@ -74,6 +74,31 @@ pub const Rotationals = struct { pub const RenderInfo = struct { meshIndex: u32 = 0, textureIndex: u32 = 0, + + var quad_mesh: ?rend.IndexedMesh = null; + var default_texture: ?*rend.Texture = null; + + pub fn getMesh(self: @This(), emitter: *const ParticleEmitter) rend.IndexedMesh { + if (emitter.mesh.items.len == 0) { + if (quad_mesh == null) { + quad_mesh = rend.getMesh("m_screenPlane").?; + } + return quad_mesh.?; + } + + return emitter.mesh.items[self.meshIndex]; + } + + pub fn getTexture(self: @This(), emitter: *const ParticleEmitter) *rend.Texture { + if (emitter.texture.items.len == 0) { + if (default_texture == null) { + default_texture = rend.getTexture("t_white").?; + } + return default_texture.?; + } + + return emitter.texture.items[self.textureIndex]; + } }; pub const ParticleEmitter = struct { @@ -85,11 +110,12 @@ pub const ParticleEmitter = struct { life: std.ArrayListUnmanaged(Life) = .{}, particlesPVA: std.ArrayListUnmanaged(ParticlePVA) = .{}, finals: std.ArrayListUnmanaged(core.Mat) = .{}, - renderInfo: std.ArrayListUnmanaged(RenderInfo) = .{}, + size: std.ArrayListUnmanaged(f32) = .{}, particleAcceleration: ParticleRandRangef = .{ .min = 0.0, .max = 0.0 }, particleVelocity: ParticleRandRangef = .{ .min = 8, .max = 10 }, particleLife: ParticleRandRangef = .{ .min = 2, .max = 2 }, + particleSizeSpawn: ParticleRandRangef = .{ .min = 0.8, .max = 1.0 }, spawnRate: ParticleRandRangef = .{ .min = 10, .max = 10 }, nextSpawn: f64 = 0.0, @@ -106,10 +132,10 @@ pub const ParticleEmitter = struct { // and only position and scale will be used to render the particle. // an empty list means that this will use quad_mesh - mesh: std.ArrayListUnmanaged(rend.IndexedMesh) = .{}, + mesh: rend.IndexedMesh = undefined, // empty list means will use t_white - texture: std.ArrayListUnmanaged(*rend.Texture) = .{}, + texture: *rend.Texture = undefined, emitterLife: f64 = 0.0, // 0.0 means this emitter lives forever. emitterMaxLife: f64 = 0.0, @@ -173,7 +199,7 @@ pub const ParticleEmitter = struct { _ = self.life.swapRemove(i); _ = self.particlesPVA.swapRemove(i); _ = self.finals.swapRemove(i); - _ = self.renderInfo.swapRemove(i); + _ = self.size.swapRemove(i); } pub fn updateSpawn(self: *@This(), dt: f64) void { @@ -235,12 +261,9 @@ pub const ParticleEmitter = struct { const life = self.particleLife.getRange(); try self.life.append(gParticleAllocator, .{ .current = life, .max = life }); - try self.particlesPVA.append(gParticleAllocator, pva); - - // renderinfo not used rn - try self.renderInfo.append(gParticleAllocator, .{}); try self.finals.append(gParticleAllocator, std.mem.zeroes(core.Mat)); + try self.size.append(gParticleAllocator, self.particleSizeSpawn.getRange()); } fn updateLife(self: *@This(), dt: f64) void { @@ -264,12 +287,30 @@ pub const ParticleEmitter = struct { self.updatePVA(dt); self.updateParticleLife(dt); self.updateLife(dt); + self.updateFinals(); } + pub fn updateFinals(self: *@This()) void { + const scene = self.entity.fetch(core.Scene).?; + const transform = scene.getPosRot().toTransform(); + + for (self.particlesPVA.items, 0..) |pva, i| { + const p = core.zm.translationV(pva.position); + + self.finals.items[i] = core.zm.mul(p, transform); + } + } + + 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 { // get the mesh component self.entity = core.Entity{ .handle = handle }; + self.texture = rend.getTexture(&t_whiteName).?; + self.mesh = rend.getMeshByName(&m_quad).?; + if (self.entity.fetch(core.Scene)) |scene| { _ = scene; } else { diff --git a/engine/rend/src/sgpu/ParticleRenderer.zig b/engine/rend/src/sgpu/ParticleRenderer.zig new file mode 100644 index 0000000..051a5ea --- /dev/null +++ b/engine/rend/src/sgpu/ParticleRenderer.zig @@ -0,0 +1,137 @@ +allocator: std.mem.Allocator, + +ssboScene: *gpu.GPUBuffer = undefined, +ssboSceneUpload: *gpu.GPUTransferBuffer = undefined, +spans: std.ArrayListUnmanaged(core.Span) = .{}, + +renderInfo: std.ArrayListUnmanaged(SgpuParticleRenderInfo) = .{}, + +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.ParticleRenderer"); + +const SgpuParticleRenderInfo = struct { + mesh: rend.IndexedMesh, + texture: *rend.Texture, +}; + +pub fn create(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + self.* = .{ + .allocator = allocator, + }; + + const device = rend.context().device; + + self.ssboScene = device.createGPUBuffer(&.{ + .usage = .{ + .bufferusageGraphicsStorageRead = true, + .bufferusageVertex = true, + }, + .size = MaxParticleCount * @sizeOf(meshes_vert.Scene), + .props = 0, + }); + + self.ssboSceneUpload = device.createGPUTransferBuffer(&.{ + .usage = .transferbufferusageUpload, + .size = MaxParticleCount * @sizeOf(meshes_vert.Scene), + .props = 0, + }); + + return self; +} + +pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void { + self.spans.clearRetainingCapacity(); + self.renderInfo.clearRetainingCapacity(); + + var offset: usize = 0; + + const device = rend.context().device; + + const uploadMapped: [*]meshes_vert.Scene = @ptrCast(@alignCast(device.mapGPUTransferBuffer(self.ssboSceneUpload, true))); + defer device.unmapGPUTransferBuffer(self.ssboSceneUpload); + + for (rend.ParticleEmitter.BaseContainer.dense.items) |*c| { + const emitter = &c.value; + + for (emitter.finals.items, 0..) |final, i| { + const size = emitter.size.items[i]; + + uploadMapped[i + offset] = .{ + .Model = final, + .textureMode = 0x2, //0x2, // default 0x2 is fullbright + .animation = -1, + .float0 = size, + .flags = 0, //0x4, + }; + } + + try self.renderInfo.append(self.allocator, .{ .texture = emitter.texture, .mesh = emitter.mesh }); + try self.spans.append(self.allocator, .{ .start = @intCast(offset), .size = @intCast(emitter.finals.items.len) }); + offset += emitter.finals.items.len; + } + + if (self.renderInfo.items.len == 0) + return; + + copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.ssboSceneUpload, .offset = 0 }, &.{ + .buffer = self.ssboScene, + .offset = 0, + .size = @intCast(offset * @sizeOf(meshes_vert.Scene)), + }, true); +} + +pub fn postMesh(p: *anyopaque, cmd: *gpu.GPUCommandBuffer, renderpass: *gpu.GPURenderPass) void { + const self: *@This() = @ptrCast(@alignCast(p)); + _ = cmd; + + renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 1); + renderpass.bindGPUFragmentStorageBuffers(0, &self.ssboScene, 1); + + const ctx = rend.context(); + + for (self.spans.items, 0..) |span, i| { + const ri = self.renderInfo.items[i]; + const mesh = ri.mesh; + const _t = ri.texture; + + var sampler: *gpu.GPUSampler = undefined; + switch (_t.samplerMode) { + .blocky => { + sampler = ctx.blockySampler; + }, + .linear => { + sampler = ctx.linearSampler; + }, + } + + renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 0); + renderpass.bindGPUFragmentSamplers(0, &.{ .texture = _t.texture, .sampler = sampler }, 1); + renderpass.drawGPUIndexedPrimitives(mesh.index.size, span.size, mesh.index.start, @intCast(mesh.vertex.start), @intCast(span.start)); + } +} + +pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void { + _ = self; + _ = device; +} + +pub fn destroy(self: *@This()) void { + self.spans.deinit(self.allocator); + self.renderInfo.deinit(self.allocator); + self.allocator.destroy(self); +} + +const MaxParticleCount = 1_000_000; + +const assets = @import("assets"); +const core = @import("core"); +const std = @import("std"); + +const rend = @import("../rend.zig"); +const renderer = rend.renderer; + +const particles = rend.particles; +const sdl3 = @import("sdl3"); +const gpu = sdl3.gpu; + +const meshes_vert = @import("meshes.vert"); diff --git a/engine/rend/src/sgpu/embedded/texture_white.png b/engine/rend/src/sgpu/embedded/texture_white.png new file mode 100644 index 0000000..41a4854 Binary files /dev/null and b/engine/rend/src/sgpu/embedded/texture_white.png differ diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 37bd171..7a9080b 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -86,6 +86,7 @@ pub const Renderer = struct { lightPower: f32 = 4.0, + particleRenderer: *ParticleRenderer = undefined, ssaoSystem: *SsaoSystem = undefined, positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, normalTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, @@ -174,6 +175,7 @@ pub const Renderer = struct { try self.createSamplers(); _ = try core.fs().installFileBytesMount("embedded:texture_sample.png", @constCast(&texture_sample_png), true); + _ = try core.fs().installFileBytesMount("embedded:texture_white.png", @constCast(&texture_white_png), true); _ = try core.fs().installFileBytesMount("embedded:primitive_box.obj", @constCast(&primitive_box_obj), true); // todo... make these embedded @@ -185,6 +187,14 @@ pub const Renderer = struct { ), ); + try assets.load( + assets.MakeImportRefOptions( + "Texture", + "t_white", + .{ .path = "embedded:texture_white.png" }, + ), + ); + try assets.load( assets.MakeImportRefOptions( "Mesh", @@ -194,11 +204,13 @@ pub const Renderer = struct { ); var defaultTextureName = core.MakeName("t_default"); self.defaultTexture = getTexture(&defaultTextureName).?; - self.debugDrawSys = try self.createRendererEngineObject(DebugDrawSystem); try self.createDirectionalShadowsPipeline(); self.skyboxSystem = try self.createRendererEngineObject(SkyboxSystem); + self.particleRenderer = try self.createRendererEngineObject(ParticleRenderer); + self.debugDrawSys = try self.createRendererEngineObject(DebugDrawSystem); + _ = try core.fs().installFileBytesMount("embedded:plane.obj", @constCast(&plane_obj), true); _ = try core.fs().installFileBytesMount("embedded:screenPlane.obj", @constCast(&screenPlane_obj), true); @@ -352,9 +364,7 @@ pub const Renderer = struct { pub fn createRendererObject(self: *@This(), T: type) !*T { const object = try T.create(self.device, self.allocator, .{}); - try self.registerRendererObject(T, object); - try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy }); return object; @@ -501,7 +511,16 @@ pub const Renderer = struct { pci.target_info.color_target_descriptions = &[4]gpu.GPUColorTargetDescription{ .{ .format = self.hdrTextureFormat, - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + //.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, @@ -559,7 +578,7 @@ pub const Renderer = struct { }); } - pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) !void { + pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) void { const container = rend.MeshComponent.BaseContainer; const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount); { @@ -604,6 +623,8 @@ pub const Renderer = struct { } } + self.particleRenderer.uploadSsbos(copyPass) catch unreachable; + if (uploadCount == 0) return; @@ -672,6 +693,7 @@ pub const Renderer = struct { var data = std.mem.zeroes([@sizeOf(meshes_vert.Uniforms) / 8 + 1]usize); const ptr: *meshes_vert.Uniforms = @ptrCast(@alignCast(&data)); if (self.activeCamera) |camera| { + ptr.ViewTransform = @bitCast(camera.transform); ptr.ViewProjection = @bitCast(camera.final); ptr.NoTranslateView = @bitCast(camera.noTranslate); } @@ -727,7 +749,7 @@ pub const Renderer = struct { // .size = 4 * 12, // }, true); - try self.uploadSSBOs(copyPass); + self.uploadSSBOs(copyPass); for (self.uploads.items) |upload| { upload.func(upload.ptr, copyPass); @@ -936,6 +958,7 @@ pub const Renderer = struct { for (self.postMesh.items) |interface| { interface.func(interface.ptr, cmd, renderpass); } + renderpass.endGPURenderPass(); self.state.pass = null; } @@ -1127,6 +1150,7 @@ pub const GPUTextureType = gpu.GPUTexture; const plane_obj align(8) = @embedFile("embedded/plane.obj").*; const screenPlane_obj align(8) = @embedFile("embedded/screenPlane.obj").*; const texture_sample_png align(8) = @embedFile("embedded/texture_sample.png").*; +const texture_white_png align(8) = @embedFile("embedded/texture_white.png").*; const primitive_box_obj align(8) = @embedFile("embedded/primitive_box.obj").*; const tracy = core.tracy; @@ -1134,3 +1158,4 @@ const animationSystem = rend.animationSystem; const builtin = @import("builtin"); pub const SsaoSystem = @import("ssao.zig"); +pub const ParticleRenderer = @import("ParticleRenderer.zig"); diff --git a/engine/rend/src/sgpu/ssao.zig b/engine/rend/src/sgpu/ssao.zig index 6dd86c0..fba73f4 100644 --- a/engine/rend/src/sgpu/ssao.zig +++ b/engine/rend/src/sgpu/ssao.zig @@ -196,7 +196,16 @@ pub fn createPipeline(self: *@This()) !void { pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ .format = self.ssaoOutputFormat, - .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + //.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, + }), }, }; diff --git a/projects/content/_shaders/dxil/lit_mesh.frag.dxil b/projects/content/_shaders/dxil/lit_mesh.frag.dxil index 4d326c1..581026e 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/meshes.vert.dxil b/projects/content/_shaders/dxil/meshes.vert.dxil index 60fe6bf..dd3a943 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/lit_mesh.frag.msl b/projects/content/_shaders/msl/lit_mesh.frag.msl index b72c673..e8da403 100644 --- a/projects/content/_shaders/msl/lit_mesh.frag.msl +++ b/projects/content/_shaders/msl/lit_mesh.frag.msl @@ -18,9 +18,9 @@ struct Scene { float4x4 Model; uint textureMode; - uint pad0; - uint pad1; - uint pad2; + int animation; + uint flags; + float float0; }; struct type_StructuredBuffer_Scene @@ -28,8 +28,8 @@ struct type_StructuredBuffer_Scene Scene _m0[1]; }; -constant float4 _90 = {}; -constant float3 _92 = {}; +constant float4 _92 = {}; +constant float3 _94 = {}; struct main0_out { @@ -52,145 +52,145 @@ 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 _102 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); - int _103 = _102 & 240; - float4 _137; - if (_103 == 16) + int _104 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); + int _105 = _104 & 240; + float4 _139; + if (_105 == 16) { - float3 _124 = 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); - _137 = float4(dot(_124, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_124, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_124, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); + float3 _126 = 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); + _139 = float4(dot(_126, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_126, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_126, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); } else { - float4 _136; - if (_103 == 0) + float4 _138; + if (_105 == 0) { - _136 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); + _138 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); } else { - _136 = _90; + _138 = _92; } - _137 = _136; + _139 = _138; } - float4 _143; - if ((_102 & 1) == 1) + float4 _145; + if ((_104 & 1) == 1) { - _143 = powr(_137, float4(2.2000000476837158203125)); + _145 = powr(_139, float4(2.2000000476837158203125)); } else { - _143 = _137; + _145 = _139; } - if (_143.w < 0.00999999977648258209228515625) + if (_145.w < 0.00999999977648258209228515625) { discard_fragment(); } - float3 _153 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower; - float3 _200; + float3 _155 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower; + float3 _202; do { - float3 _157 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; - float _158 = length(_157); - float _159 = _158 * _158; - float _165; - if (_158 > 2.0) + float3 _159 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; + float _160 = length(_159); + float _161 = _160 * _160; + float _167; + if (_160 > 2.0) { - _165 = 0.5 / _159; + _167 = 0.5 / _161; } else { - _165 = 1.0 / _159; + _167 = 1.0 / _161; } - float _170; - if (_158 > 4.0) + float _172; + if (_160 > 4.0) { - _170 = _165 * 0.5; + _172 = _167 * 0.5; } else { - _170 = _165; + _172 = _167; } - float _172 = (_158 > 15.0) ? 0.0 : _170; - float _174 = (_172 > 1.0) ? 1.0 : _172; + float _174 = (_160 > 15.0) ? 0.0 : _172; + float _176 = (_174 > 1.0) ? 1.0 : _174; if (length(in.in_var_TEXCOORD2) < 0.100000001490116119384765625) { - _200 = (in.in_var_TEXCOORD1 * _153) * _174; + _202 = (in.in_var_TEXCOORD1 * _155) * _176; break; } - float3 _181 = fast::normalize(_157); - _200 = ((_153 * precise::max(dot(_181, in.in_var_TEXCOORD2), 0.0)) * _174) + (((_153 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_181 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _174); + float3 _183 = fast::normalize(_159); + _202 = ((_155 * precise::max(dot(_183, in.in_var_TEXCOORD2), 0.0)) * _176) + (((_155 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_183 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _176); break; } while(false); - float3 _217 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); - float3 _219; - _219.x = _217.x; - float2 _220 = _219.xy; - _220.y = -_217.y; - float _227; - int _230; + float3 _219 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); + float3 _221; + _221.x = _219.x; + float2 _222 = _221.xy; + _222.y = -_219.y; + float _229; int _232; - _227 = 0.0; - _230 = 0; - _232 = -2; - float _228; - int _231; - for (; _232 <= 2; _227 = _228, _230 = _231, _232++) + int _234; + _229 = 0.0; + _232 = 0; + _234 = -2; + float _230; + int _233; + for (; _234 <= 2; _229 = _230, _232 = _233, _234++) { - _231 = _230; - _228 = _227; - for (int _241 = -2; _241 <= 2; ) + _233 = _232; + _230 = _229; + for (int _243 = -2; _243 <= 2; ) { - _231++; - _228 += float((in.in_var_TEXCOORD3.z - 0.0030000000260770320892333984375) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_220 + float2(float(_241) * 0.000244140625, float(_232) * 0.000244140625))).x); - _241++; + _233++; + _230 += float((in.in_var_TEXCOORD3.z - 0.0030000000260770320892333984375) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_222 + float2(float(_243) * 0.000244140625, float(_234) * 0.000244140625))).x); + _243++; continue; } } - float3 _270; - if ((_102 & 2) > 0) + float3 _272; + if ((_104 & 2) > 0) { - _270 = _143.xyz * 2.0; + _272 = powr(_145.xyz, float3(0.4545454680919647216796875)); } else { - _270 = _143.xyz * ((float3(0.100000001490116119384765625) + _200) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_227 / float(_230))))); + _272 = _145.xyz * ((float3(0.100000001490116119384765625) + _202) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_229 / float(_232))))); } - float4 _287; - if (_270.x > 1.0) + float4 _289; + if (_272.x > 1.0) { - float4 _286 = float4(0.0, 0.0, 0.0, 1.0); - _286.x = _270.x; - _287 = _286; + float4 _288 = float4(0.0, 0.0, 0.0, 1.0); + _288.x = _272.x; + _289 = _288; } else { - _287 = float4(0.0, 0.0, 0.0, 1.0); + _289 = float4(0.0, 0.0, 0.0, 1.0); } - float4 _292; - if (_270.y > 1.0) + float4 _294; + if (_272.y > 1.0) { - float4 _291 = _287; - _291.y = _270.y; - _292 = _291; + float4 _293 = _289; + _293.y = _272.y; + _294 = _293; } else { - _292 = _287; + _294 = _289; } - float4 _297; - if (_270.z > 1.0) + float4 _299; + if (_272.z > 1.0) { - float4 _296 = _292; - _296.z = _270.z; - _297 = _296; + float4 _298 = _294; + _298.z = _272.z; + _299 = _298; } else { - _297 = _292; + _299 = _294; } - out.out_var_SV_Target0 = float4(_270, _143.w); - out.out_var_SV_Target1 = _297; + out.out_var_SV_Target0 = float4(_272, _145.w); + out.out_var_SV_Target1 = _299; out.out_var_SV_Target2 = float4(in.in_var_TEXCOORD1, 1.0); out.out_var_SV_Target3 = float4(in.in_var_TEXCOORD5, 1.0); return out; diff --git a/projects/content/_shaders/msl/meshes.vert.msl b/projects/content/_shaders/msl/meshes.vert.msl index 5cb0413..4cff0f8 100644 --- a/projects/content/_shaders/msl/meshes.vert.msl +++ b/projects/content/_shaders/msl/meshes.vert.msl @@ -9,7 +9,7 @@ struct Scene uint textureMode; int animation; uint flags; - uint pad2; + float float0; }; struct type_StructuredBuffer_Scene @@ -31,7 +31,9 @@ struct type_Uniforms { float4x4 ViewProjection; float4x4 NoTranslateView; + float4x4 ViewTransform; float4x4 ShadowMapProjection; + float4 cameraPosition; float time; }; @@ -58,35 +60,61 @@ 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 _103; + float3 _112; if (scene._m0[gl_InstanceIndex].animation != (-1)) { - float3 _75; - _75 = float3(0.0); - for (int _78 = 0; _78 < 4; ) + float3 _84; + _84 = float3(0.0); + for (int _87 = 0; _87 < 4; ) { - uint _84 = (8u * uint(_78)) & 31u; - _75 += ((animationBuffer._m0[uint(scene._m0[gl_InstanceIndex].animation) + ((in.in_var_TEXCOORD4 >> _84) & 255u)].final * float4(in.in_var_TEXCOORD0, 1.0)).xyz * (float((in.in_var_TEXCOORD5 >> _84) & 255u) * 0.0039215688593685626983642578125)); - _78++; + 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++; continue; } - _103 = _75; + _112 = _84; } else { - _103 = in.in_var_TEXCOORD0; + _112 = in.in_var_TEXCOORD0; + } + float4 _116 = float4(_112, 1.0); + float3 _210; + float3 _211; + float3 _212; + float4 _213; + float4 _214; + 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; + } + 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 _107 = float4(_103, 1.0); - float4 _110 = scene._m0[gl_InstanceIndex].Model * _107; - float4x4 _145 = 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 _149 = float4(in.in_var_TEXCOORD1, 1.0); out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3; - out.out_var_TEXCOORD1 = _110.xyz; - out.out_var_TEXCOORD2 = fast::normalize(_149 * _145).xyz; - out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _110; + out.out_var_TEXCOORD1 = _210; + out.out_var_TEXCOORD2 = _211; + out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _214; out.out_var_TEXCOORD4 = gl_InstanceIndex; - out.out_var_TEXCOORD5 = (_149 * (_145 * transpose(Uniforms.NoTranslateView))).xyz; - out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _107); + out.out_var_TEXCOORD5 = _212; + out.gl_Position = _213; return out; } diff --git a/projects/content/_shaders/spv/lit_mesh.frag.spv b/projects/content/_shaders/spv/lit_mesh.frag.spv index c6e2acf..59dfd2a 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/meshes.vert.spv b/projects/content/_shaders/spv/meshes.vert.spv index bead258..ac4afe7 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/content/textures/PixelSmoke.aseprite b/projects/content/textures/PixelSmoke.aseprite new file mode 100644 index 0000000..b6ec231 Binary files /dev/null and b/projects/content/textures/PixelSmoke.aseprite differ diff --git a/projects/content/textures/PixelSmoke.png b/projects/content/textures/PixelSmoke.png new file mode 100644 index 0000000..d6cb0ca Binary files /dev/null and b/projects/content/textures/PixelSmoke.png differ diff --git a/projects/content/textures/texture_white.png b/projects/content/textures/texture_white.png new file mode 100644 index 0000000..41a4854 Binary files /dev/null and b/projects/content/textures/texture_white.png differ diff --git a/projects/sampleGame/externGame/externGame.zig b/projects/sampleGame/externGame/externGame.zig index c05f6e5..0d8e72c 100644 --- a/projects/sampleGame/externGame/externGame.zig +++ b/projects/sampleGame/externGame/externGame.zig @@ -116,6 +116,7 @@ pub const ExternGameObject = struct { displayRandRangeImgui("Acceleration", &emitter.particleAcceleration); displayRandRangeImgui("Velocity", &emitter.particleVelocity); displayRandRangeImgui("Life", &emitter.particleLife); + displayRandRangeImgui("Size", &emitter.particleSizeSpawn); displayRandRangeImgui("spawnRate", &emitter.spawnRate); if (emitter.gravity != null) { @@ -139,7 +140,8 @@ pub const ExternGameObject = struct { editVector("gravity", &emitter.gravity.?); } - _ = ig.inputInt("maaxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{}); + _ = ig.inputInt("maxParticles##particleEd", @ptrCast(&emitter.maxParticles), 1, 5, .{}); + _ = ig.checkbox("showDebug", &emitter._showDebug); } ig.end(); } diff --git a/projects/sampleGame/main.zig b/projects/sampleGame/main.zig index 42d0e52..ec1edf7 100644 --- a/projects/sampleGame/main.zig +++ b/projects/sampleGame/main.zig @@ -68,6 +68,11 @@ const assetReferences = [_]assets.AssetImportReference{ "t_fox", .{ .path = "gltf-samples/Fox/glTF/Texture.png" }, ), + assets.MakeImportRefOptions( + "Texture", + "t_pixelSmoke", + .{ .path = "textures/PixelSmoke.png" }, + ), assets.MakeImportRefOptions("Texture", "t_crate", .{ .path = "textures/Crate.png", }), @@ -126,6 +131,8 @@ pub const ParticleObject = struct { particle._showDebug = true; particle.start(); particle.gravity = .{ .y = -9.8 }; + var name = core.MakeName("t_pixelSmoke"); + particle.texture = rend.getTexture(&name).?; self.entity = e;