diff --git a/engine/core/src/math.zig b/engine/core/src/math.zig index f0ba558..0df548a 100644 --- a/engine/core/src/math.zig +++ b/engine/core/src/math.zig @@ -605,6 +605,10 @@ pub const Rotation = struct { } }; +pub fn lerp(a: f32, b: f32, t: f32) f32 { + return a + t * (b - a); +} + pub fn simdVec4ToVec(vec: zm.Vec) Vector4f { return .{ .x = vec[0], diff --git a/engine/core/tests/tests.zig b/engine/core/tests/tests.zig index 9be35ec..f4b4f7b 100644 --- a/engine/core/tests/tests.zig +++ b/engine/core/tests/tests.zig @@ -25,9 +25,41 @@ test "simple systems setup for core" { try test_consoleCommands(); try test_gameObjects(std.testing.allocator); + try generateRandomSamples(); + try memory.dumpTimeline("test-core-timeline.txt"); } +fn generateRandomSamples() !void { + var prng = std.Random.DefaultPrng.init(blk: { + var seed: u64 = undefined; + try std.posix.getrandom(std.mem.asBytes(&seed)); + break :blk seed; + }); + const rand = prng.random(); + + std.debug.print("const float3[] = {{", .{}); + for (0..64) |i| { + var vec = core.Vectorf{ + .x = rand.float(f32) * 2.0 - 1.0, + .y = rand.float(f32) * 2.0 - 1.0, + .z = rand.float(f32), + }; + + vec = vec.normalize(); + vec = vec.fmul(rand.float(f32)); + + var scale: f32 = @as(f32, @floatFromInt(i)) / 64.0; + scale = scale * core.lerp(0.1, 1.0, scale * scale); + vec = vec.fmul(scale); + + // std.debug.print("( {d}, {d}, {d} )\n", .{ vec.x, vec.y, vec.z }); + std.debug.print(" float3( {d}, {d}, {d} ),\n", .{ vec.x, vec.y, vec.z }); + } + + std.debug.print("}};\n", .{}); +} + fn test_loadingConfigs() !void { if (core.getConfigVar(u32, "platform.extent.width")) |width| { core.engine_log("config: {d}", .{width}); diff --git a/engine/imgui/src/sgpu/backend_impl.zig b/engine/imgui/src/sgpu/backend_impl.zig index cd1c2cf..5027319 100644 --- a/engine/imgui/src/sgpu/backend_impl.zig +++ b/engine/imgui/src/sgpu/backend_impl.zig @@ -88,6 +88,15 @@ pub const Impl = struct { if (self.dtAverage > 0.000001) { ig.textFmt("frameTime: {d:.2}ms ({d:.2}fps)", .{ self.dtAverage * 1000, @as(u32, @intFromFloat(1 / self.dtAverage)) }) catch return error.UnknownStatePanic; } + + ig.textFmt("SSAO settings: ", .{}) catch unreachable; + + const ssao = rend.context().ssaoSystem; + _ = ig.sliderFloat("radius", &ssao.radius, 0.1, 1.0, null, .{}); + _ = ig.sliderFloat("bias", &ssao.bias, 0.0025, 1.0, null, .{}); + + _ = ig.checkbox("enable SSAO", &ssao.enable); + ig.end(); } } diff --git a/engine/rend/build.zig b/engine/rend/build.zig index 832ab05..2cf2924 100644 --- a/engine/rend/build.zig +++ b/engine/rend/build.zig @@ -47,6 +47,8 @@ pub fn build(b: *std.Build) void { 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")); + sdl3.shaderDefintion(b, mod, "../../lib/sdl3", optimize, "ssao.frag", b.path("shaders/ssao.frag.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 c2a7ff7..2a6f215 100644 --- a/engine/rend/shaders/lit_mesh.frag.hlsl +++ b/engine/rend/shaders/lit_mesh.frag.hlsl @@ -177,6 +177,8 @@ float3 DirectionalLight(float3 normal, float3 fragPos, float4 DirectionalShadow struct PixelOutput { float4 Color : SV_Target0; // First render target float4 Emissive : SV_Target1; // Second render target + float4 Position : SV_Target2; // Used for SSAO + float4 Normal : SV_Target3; // Used for SSAO }; PixelOutput main( @@ -251,6 +253,9 @@ PixelOutput main( PixelOutput o; + o.Position = float4(WorldPos, 1.0); + o.Normal = float4(Normal, 1.0); + o.Color = float4(c2, alpha); o.Emissive = float4(0.0, 0.0, 0.0, 1.0); if(c2.x > 1.0) o.Emissive.x = c2.x; diff --git a/engine/rend/shaders/lit_mesh.frag.json b/engine/rend/shaders/lit_mesh.frag.json index d5c016a..a619351 100644 --- a/engine/rend/shaders/lit_mesh.frag.json +++ b/engine/rend/shaders/lit_mesh.frag.json @@ -6,7 +6,7 @@ } ], "types" : { - "_20" : { + "_22" : { "name" : "type.Uniforms", "members" : [ { @@ -46,7 +46,7 @@ } ] }, - "_23" : { + "_25" : { "name" : "Scene", "members" : [ { @@ -78,12 +78,12 @@ } ] }, - "_22" : { + "_24" : { "name" : "type.StructuredBuffer.Scene", "members" : [ { "name" : "_m0", - "type" : "_23", + "type" : "_25", "array" : [ 0 ], @@ -133,6 +133,16 @@ "type" : "vec4", "name" : "out.var.SV_Target1", "location" : 1 + }, + { + "type" : "vec4", + "name" : "out.var.SV_Target2", + "location" : 2 + }, + { + "type" : "vec4", + "name" : "out.var.SV_Target3", + "location" : 3 } ], "separate_images" : [ @@ -189,7 +199,7 @@ ], "ssbos" : [ { - "type" : "_22", + "type" : "_24", "name" : "scene", "readonly" : true, "block_size" : 0, @@ -199,7 +209,7 @@ ], "ubos" : [ { - "type" : "_20", + "type" : "_22", "name" : "type.Uniforms", "block_size" : 80, "set" : 3, diff --git a/engine/rend/shaders/meshes.vert.hlsl b/engine/rend/shaders/meshes.vert.hlsl index 1aff330..970779d 100644 --- a/engine/rend/shaders/meshes.vert.hlsl +++ b/engine/rend/shaders/meshes.vert.hlsl @@ -81,8 +81,7 @@ Output main(Input input) output.WorldPos = WorldPos.xyz; float4x4 noTranslate = ExtractRotation(scene[input.Instance].Model); - // output.Normal = mul(scene[input.Instance].Model, float4(input.Normal, 1.0)).xyz; - output.Normal = mul(noTranslate, input.Normal); + output.Normal = normalize(mul(noTranslate, float4(input.Normal, 1.0))).xyz; output.DirectionalShadowFragPos = mul(ShadowMapProjection, WorldPos); output.Instance = input.Instance; diff --git a/engine/rend/shaders/postProc.frag.hlsl b/engine/rend/shaders/postProc.frag.hlsl index ddc5c71..5eda966 100644 --- a/engine/rend/shaders/postProc.frag.hlsl +++ b/engine/rend/shaders/postProc.frag.hlsl @@ -4,6 +4,9 @@ SamplerState Sampler0 : register(s0, space2); Texture2D EmissiveTexture : register(t1, space2); SamplerState Sampler1 : register(s1, space2); +Texture2D SsaoTexture : register(t2, space2); +SamplerState Sampler2 : register(s2, space2); + float3 reinhard2(float3 x) { const float L_white = 10.0; @@ -88,16 +91,25 @@ float4 main(float2 UV : TEXCOORD0) : SV_Target0 c = c + blur(uv) * 0.05; float exposure = 1.0; - c *= exposure;//= exposure(c, 1.0, 0.3); + c *= exposure; //= exposure(c, 1.0, 0.3); + // c = blur(uv) * 0.01; + + // c = float3(1.0, 1.0, 1.0) - (step(0.91, length(float3(1.0, 1.0, 1.0) - (e - c)))); // c = c * c ; - // c = e; // c = float3(uv.x, uv.y, 0.0); + // c = SsaoTexture.Sample(Sampler2, uv).x; + + float ssao = SsaoTexture.Sample(Sampler2, uv).x; + c = ssao * c; + c.x *= 1.0 + 0.000001 * EmissiveTexture.Sample(Sampler1, uv).x; c.x *= 1.0 + 0.000001 * ColorTexture.Sample(Sampler0, uv).x; + c.x *= 1.0 + 0.000001 * SsaoTexture.Sample(Sampler2, uv).x; + return float4(c, 1.0); } diff --git a/engine/rend/shaders/postProc.frag.json b/engine/rend/shaders/postProc.frag.json index 537472b..b2e2b5d 100644 --- a/engine/rend/shaders/postProc.frag.json +++ b/engine/rend/shaders/postProc.frag.json @@ -31,6 +31,12 @@ "name" : "EmissiveTexture", "set" : 2, "binding" : 1 + }, + { + "type" : "texture2D", + "name" : "SsaoTexture", + "set" : 2, + "binding" : 2 } ], "separate_samplers" : [ @@ -45,6 +51,12 @@ "name" : "Sampler1", "set" : 2, "binding" : 1 + }, + { + "type" : "sampler", + "name" : "Sampler2", + "set" : 2, + "binding" : 2 } ] } \ No newline at end of file diff --git a/engine/rend/shaders/randomSamplesFloat3.hlsli b/engine/rend/shaders/randomSamplesFloat3.hlsli new file mode 100644 index 0000000..6610d82 --- /dev/null +++ b/engine/rend/shaders/randomSamplesFloat3.hlsli @@ -0,0 +1,65 @@ +static const float3 SamplingKernel[64] = { float3( -0, 0, 0 ), + float3( 0.00039307403, 0.00020744701, 0.00023402007 ), + float3( -0.0013183617, -0.001457856, 0.001546739 ), + float3( 0.00034961867, 0.000084181214, 0.000058608897 ), + float3( -0.0005043492, -0.0038330406, 0.0029292488 ), + float3( -0.0024177164, 0.005713524, 0.0017336456 ), + float3( -0.0007101023, 0.00041329022, 0.00037520085 ), + float3( 0.000015587833, -0.00011572848, 0.00007356792 ), + float3( 0.0033403218, -0.0051653436, 0.0050431825 ), + float3( -0.006396646, 0.012900719, 0.0014770345 ), + float3( 0.007907788, -0.0049759555, 0.001991992 ), + float3( -0.0003332807, -0.0010008786, 0.0010310012 ), + float3( 0.00011193146, 0.0003611636, 0.0010905899 ), + float3( -0.003853666, -0.0046293857, 0.0027080767 ), + float3( -0.005521812, 0.01639079, 0.003326437 ), + float3( -0.002978282, -0.0034022515, 0.0009606515 ), + float3( 0.00056433195, -0.0012372117, 0.0011423329 ), + float3( 0.004264683, 0.0016907869, 0.003383593 ), + float3( 0.028113492, -0.018816402, 0.014087889 ), + float3( -0.030224549, -0.0008946165, 0.008499113 ), + float3( -0.019619143, -0.035032418, 0.014081306 ), + float3( 0.015496987, -0.0109031275, 0.0018075232 ), + float3( 0.01965354, 0.017109247, 0.014284793 ), + float3( -0.028926125, 0.0032248388, 0.06573774 ), + float3( -0.0016983883, 0.00040745927, 0.0037293378 ), + float3( -0.03353675, 0.059106316, 0.0014771292 ), + float3( 0.01729743, 0.0209541, 0.061427496 ), + float3( -0.036244053, -0.010973344, 0.052580632 ), + float3( -0.010873114, 0.07166689, 0.07090236 ), + float3( 0.04043038, -0.07589081, 0.066407025 ), + float3( 0.0064247856, -0.008888489, 0.0057132393 ), + float3( -0.04249787, 0.122786455, 0.030131085 ), + float3( -0.012614764, -0.011735871, 0.016145077 ), + float3( 0.022467306, -0.023659669, 0.01735905 ), + float3( 0.028099436, -0.028635133, 0.0076164785 ), + float3( 0.070179075, -0.15321687, 0.08871499 ), + float3( 0.0073889424, 0.15228039, 0.006640831 ), + float3( 0.07831906, -0.07210498, 0.094614334 ), + float3( 0.032895967, -0.04089934, 0.040609412 ), + float3( -0.14140445, 0.17826557, 0.06704617 ), + float3( 0.108955644, 0.11149475, 0.21018304 ), + float3( 0.027592616, 0.013900582, 0.03667716 ), + float3( 0.05564411, -0.09973075, 0.11314424 ), + float3( -0.03156544, -0.2242651, 0.23739193 ), + float3( -0.047421616, 0.0056678373, 0.17368564 ), + float3( 0.088452466, 0.09633193, 0.08357883 ), + float3( -0.0036428333, 0.010955554, 0.0033084971 ), + float3( -0.19118926, -0.18971312, 0.15644875 ), + float3( 0.034361146, 0.06554529, 0.030825432 ), + float3( 0.3718893, 0.02290428, 0.29824117 ), + float3( -0.014679887, 0.013492301, 0.007404959 ), + float3( -0.0065382663, -0.005886981, 0.0057258857 ), + float3( -0.23331204, -0.35499394, 0.03432809 ), + float3( 0.041135747, -0.023320116, 0.018914448 ), + float3( -0.0945929, 0.025291005, 0.09295652 ), + float3( -0.03173818, 0.22602636, 0.23679778 ), + float3( -0.38012174, 0.24812445, 0.47917068 ), + float3( 0.13565014, 0.13791494, 0.40774575 ), + float3( 0.52387995, -0.38875812, 0.2438776 ), + float3( -0.052082617, -0.11840963, 0.09570911 ), + float3( 0.12260949, -0.4220635, 0.17810947 ), + float3( -0.28019544, -0.52029127, 0.26809025 ), + float3( -0.3271856, 0.23393591, 0.09812375 ), + float3( 0.3826407, 0.08367093, 0.2575612 ), +}; diff --git a/engine/rend/shaders/ssao.frag.hlsl b/engine/rend/shaders/ssao.frag.hlsl new file mode 100644 index 0000000..adea668 --- /dev/null +++ b/engine/rend/shaders/ssao.frag.hlsl @@ -0,0 +1,79 @@ +Texture2D PositionTexture : register(t0, space2); +SamplerState Sampler0 : register(s0, space2); + +Texture2D NormalTexture : register(t1, space2); +SamplerState Sampler1 : register(s1, space2); + +Texture2D NoiseTexture : register(t2, space2); +SamplerState Sampler2 : register(s2, space2); + +#include "randomSamplesFloat3.hlsli" + +cbuffer Uniforms : register(b0, space3) +{ + float4x4 View; + float4x4 ViewProjection; + float4x4 Projection; + float2 extents; + float radius; // = 0.5; + float bias; // = 0.025; + int numSamples; // up to 64 +}; + +float4 main(float2 UV: TEXCOORD0) : SV_Target0 +{ + float2 uv = UV; + uv.y *= -1; + uv.y += 1.0; + + float2 scale = float2(1280 / 4.0, 720 / 4.0); + + float4 c = PositionTexture.Sample(Sampler0, uv); + float3 position = mul(View, PositionTexture.Sample(Sampler0, uv)).xyz; + if (position.z < 0.01) + { + return 1.0; + } + float3 normal = normalize(mul(View, NormalTexture.Sample(Sampler1, uv)).xyz); + float3 randomVec = normalize(NoiseTexture.Sample(Sampler2, uv * scale).xyz); + + float3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + float3 bitangent = cross(normal, tangent); + float3x3 TBN = float3x3(tangent, bitangent, normal); + + float occlusion = 0.0; + + for(int i = 0; i < numSamples; i += 1) + { + float3 samplePos = mul(TBN, SamplingKernel[i]); // from tangent to view-space + samplePos = position + samplePos * radius; + + // project sample position (to sample texture) (to get position on screen/texture) + float4 offset = float4(samplePos, 1.0); + offset = mul(Projection, offset); // from view to clip-space + offset.xyz /= offset.w; // perspective divide + offset.xyz = offset.xyz * 0.5 + 0.5; // transform to range 0.0 - 1.0 + + offset.y *= -1; + // get sample depth + float sampleDepth = mul(View, PositionTexture.Sample(Sampler0, offset.xy)).z; // texture(gPosition, offset.xy).z; // get depth value of kernel sample + // c = float4(sampleDepth, sampleDepth, sampleDepth, 1.0) / 100; + // c = float4(offset) * 2.0 - 0.6 ; + + // range check & accumulate + float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth)); + occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck; + } + occlusion = 1.0 - (occlusion / numSamples); + + // c += PositionTexture.Sample(Sampler0, uv).x * 0.00001; + // c += NormalTexture.Sample(Sampler1, uv).x * 0.00001; + // c += NoiseTexture.Sample(Sampler2, uv).x * 0.00001; + // float x = length(c); + // c = float4(x, x, x, 1.0); + + + + c = occlusion; + return c + occlusion * 0.00001; +} diff --git a/engine/rend/shaders/ssao.frag.json b/engine/rend/shaders/ssao.frag.json new file mode 100644 index 0000000..f519949 --- /dev/null +++ b/engine/rend/shaders/ssao.frag.json @@ -0,0 +1,119 @@ +{ + "entryPoints" : [ + { + "name" : "main", + "mode" : "frag" + } + ], + "types" : { + "_14" : { + "name" : "type.Uniforms", + "members" : [ + { + "name" : "View", + "type" : "mat4", + "offset" : 0, + "matrix_stride" : 16, + "row_major" : true + }, + { + "name" : "ViewProjection", + "type" : "mat4", + "offset" : 64, + "matrix_stride" : 16, + "row_major" : true + }, + { + "name" : "Projection", + "type" : "mat4", + "offset" : 128, + "matrix_stride" : 16, + "row_major" : true + }, + { + "name" : "extents", + "type" : "vec2", + "offset" : 192 + }, + { + "name" : "radius", + "type" : "float", + "offset" : 200 + }, + { + "name" : "bias", + "type" : "float", + "offset" : 204 + }, + { + "name" : "numSamples", + "type" : "int", + "offset" : 208 + } + ] + } + }, + "inputs" : [ + { + "type" : "vec2", + "name" : "in.var.TEXCOORD0", + "location" : 0 + } + ], + "outputs" : [ + { + "type" : "vec4", + "name" : "out.var.SV_Target0", + "location" : 0 + } + ], + "separate_images" : [ + { + "type" : "texture2D", + "name" : "PositionTexture", + "set" : 2, + "binding" : 0 + }, + { + "type" : "texture2D", + "name" : "NormalTexture", + "set" : 2, + "binding" : 1 + }, + { + "type" : "texture2D", + "name" : "NoiseTexture", + "set" : 2, + "binding" : 2 + } + ], + "separate_samplers" : [ + { + "type" : "sampler", + "name" : "Sampler0", + "set" : 2, + "binding" : 0 + }, + { + "type" : "sampler", + "name" : "Sampler1", + "set" : 2, + "binding" : 1 + }, + { + "type" : "sampler", + "name" : "Sampler2", + "set" : 2, + "binding" : 2 + } + ], + "ubos" : [ + { + "type" : "_14", + "name" : "type.Uniforms", + "block_size" : 212, + "set" : 3, + "binding" : 0 + } + ] +} \ No newline at end of file diff --git a/engine/rend/src/sgpu/DebugDrawSystem.zig b/engine/rend/src/sgpu/DebugDrawSystem.zig index 8a82ba7..07288b9 100644 --- a/engine/rend/src/sgpu/DebugDrawSystem.zig +++ b/engine/rend/src/sgpu/DebugDrawSystem.zig @@ -194,7 +194,7 @@ pub fn createPipeline(self: *@This()) !*gpu.GPUGraphicsPipeline { pci.target_info.has_depth_stencil_target = true; pci.target_info.depth_stencil_format = rend.context().depthFormat; - pci.target_info.num_color_targets = 2; + pci.target_info.num_color_targets = 4; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ .format = rend.context().hdrTextureFormat, @@ -204,6 +204,14 @@ pub fn createPipeline(self: *@This()) !*gpu.GPUGraphicsPipeline { .format = rend.context().hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), }, + .{ + .format = rend.context().positionTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + .{ + .format = rend.context().normalTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, }; pci.rasterizer_state.fill_mode = .fillmodeLine; diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index c6843fe..c1f29c7 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -81,6 +81,10 @@ pub const Renderer = struct { lightPower: f32 = 4.0, + ssaoSystem: *SsaoSystem = undefined, + positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, + normalTargetFormat: gpu.GPUTextureFormat = .textureformatB8g8r8a8Unorm, + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); pub const MaxObjectCount = 50000; @@ -99,7 +103,7 @@ pub const Renderer = struct { return self; } - pub fn createHDRTexture(self: *@This()) !void { + pub fn createRenderTargets(self: *@This()) !void { var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); gci.type = .texturetype2d; @@ -116,6 +120,12 @@ pub const Renderer = struct { self.state.targetTexture = self.device.createGPUTexture(&gci); self.state.emissiveTarget = self.device.createGPUTexture(&gci); + + gci.format = self.positionTargetFormat; + self.state.positionTarget = self.device.createGPUTexture(&gci); + + gci.format = self.normalTargetFormat; + self.state.normalTarget = self.device.createGPUTexture(&gci); } pub fn startRenderer(self: *@This()) !void { @@ -139,7 +149,7 @@ pub const Renderer = struct { try self.createMeshPipeline(); try self.createBuffers(); try self.createDepthTexture(); - try self.createHDRTexture(); + try self.createRenderTargets(); try self.createPostProcessingPipeline(); self.meshPool = try self.createRendererObject(MeshPool); @@ -188,6 +198,23 @@ pub const Renderer = struct { .{ .path = "embedded:screenPlane.obj" }, ), ); + + self.ssaoSystem = try self.createRendererEngineObject(SsaoSystem); + } + + pub fn addVertexAttributes(self: *@This(), pci: *gpu.GPUGraphicsPipelineCreateInfo) !std.ArrayList(gpu.GPUVertexAttribute) { + const attributes = try self.generateVertexAttributeList(); + + 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), + }; + + return attributes; } pub fn createPostProcessingPipeline(self: *@This()) !void { @@ -434,8 +461,8 @@ pub const Renderer = struct { 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 = 2; - pci.target_info.color_target_descriptions = &[2]gpu.GPUColorTargetDescription{ + pci.target_info.num_color_targets = 4; + pci.target_info.color_target_descriptions = &[4]gpu.GPUColorTargetDescription{ .{ .format = self.hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), @@ -444,6 +471,14 @@ pub const Renderer = struct { .format = self.hdrTextureFormat, .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), }, + .{ + .format = self.positionTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + .{ + .format = self.normalTargetFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, }; pci.rasterizer_state.fill_mode = .fillmodeFill; @@ -713,7 +748,7 @@ pub const Renderer = struct { pub fn drawMeshes(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { // can cache this - const targetInfo: [2]gpu.GPUColorTargetInfo = .{ + const targetInfo: [4]gpu.GPUColorTargetInfo = .{ std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ .texture = self.state.targetTexture, .load_op = .loadopLoad, @@ -724,6 +759,16 @@ pub const Renderer = struct { .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, .{ @@ -736,7 +781,7 @@ pub const Renderer = struct { .clear_stencil = 0, }); - self.state.pass = cmd.beginGPURenderPass(&targetInfo, 2, &depthTarget); + self.state.pass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget); const renderpass = self.state.pass.?; renderpass.setGPUScissor(&self.scissor); @@ -783,6 +828,7 @@ pub const Renderer = struct { interface.func(interface.ptr, cmd, renderpass); } renderpass.endGPURenderPass(); + self.state.pass = null; } pub fn drawPostProcess(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { @@ -795,10 +841,11 @@ pub const Renderer = struct { const postProcPass = cmd.beginGPURenderPass(&postProcTargetInfo, 1, null); postProcPass.bindGPUGraphicsPipeline(self.postProcessingPipeline); - postProcPass.bindGPUFragmentSamplers(0, &[2]gpu.GPUTextureSamplerBinding{ + postProcPass.bindGPUFragmentSamplers(0, &[3]gpu.GPUTextureSamplerBinding{ .{ .sampler = self.blockySampler, .texture = self.state.targetTexture }, .{ .sampler = self.linearSampler, .texture = self.state.emissiveTarget }, - }, 2); + .{ .sampler = self.linearSampler, .texture = self.ssaoSystem.ssaoTexture }, + }, 3); postProcPass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1); postProcPass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); @@ -835,6 +882,7 @@ pub const Renderer = struct { self.drawDirectionalShadowMap(cmd); self.skyboxSystem.render(cmd); self.drawMeshes(cmd); + self.ssaoSystem.render(cmd); self.drawPostProcess(cmd); for (self.postRenders.items) |interface| { @@ -904,6 +952,7 @@ pub fn reloadShaders() !void { }; try gRenderer.createMeshPipeline(); try gRenderer.createPostProcessingPipeline(); + try gRenderer.ssaoSystem.createPipeline(); } // ====== renderer API ======= @@ -953,6 +1002,8 @@ pub const RendererState = struct { swapchainTargetTexture: ?*gpu.GPUTexture = null, targetTexture: *gpu.GPUTexture = undefined, emissiveTarget: *gpu.GPUTexture = undefined, + positionTarget: *gpu.GPUTexture = undefined, + normalTarget: *gpu.GPUTexture = undefined, }; pub const CustomMeshRenderFunc = *const fn (?*anyopaque) void; @@ -961,3 +1012,5 @@ pub const GPUTextureType = gpu.GPUTexture; const plane_obj align(8) = @embedFile("embedded/plane.obj").*; const screenPlane_obj align(8) = @embedFile("embedded/screenPlane.obj").*; const tracy = core.tracy; + +pub const SsaoSystem = @import("ssao.zig"); diff --git a/engine/rend/src/sgpu/ssao.zig b/engine/rend/src/sgpu/ssao.zig new file mode 100644 index 0000000..0930584 --- /dev/null +++ b/engine/rend/src/sgpu/ssao.zig @@ -0,0 +1,222 @@ +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + +allocator: std.mem.Allocator, + +ssaoOutputFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, +noiseTextureFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, + +// outputs an SSAO texture at half the resolution +ssaoPipeline: *gpu.GPUGraphicsPipeline = undefined, +ssaoTexture: *gpu.GPUTexture = undefined, + +noiseTexture: *gpu.GPUTexture = undefined, +noiseSampler: *gpu.GPUSampler = undefined, + +radius: f32 = 0.5, +bias: f32 = 0.05, +numSamples: i32 = 64, +enable: bool = true, + +// float radius; // = 0.5; +// float bias; // = 0.025; +// int numSamples; // up to 64 + +pub fn create(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + + self.* = .{ + .allocator = allocator, + }; + + return self; +} + +pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void { + _ = device; + core.engine_log("creating ssao pipeline", .{}); + try self.createBuffersAndTextures(); + try self.createPipeline(); + try self.createNoiseTexture(); +} + +pub fn createNoiseTexture(self: *@This()) !void { + const ctx = rend.context(); + + self.noiseSampler = ctx.device.createGPUSampler(&std.mem.zeroInit(gpu.GPUSamplerCreateInfo, .{ + .min_filter = .filterLinear, + .mag_filter = .filterLinear, + .mipmap_mode = .samplermipmapmodeNearest, + .address_mode_u = .sampleraddressmodeRepeat, + .address_mode_v = .sampleraddressmodeRepeat, + .address_mode_w = .sampleraddressmodeRepeat, + })); + + var prng = std.Random.DefaultPrng.init(blk: { + var seed: u64 = undefined; + try std.posix.getrandom(std.mem.asBytes(&seed)); + break :blk seed; + }); + const rand = prng.random(); + + const textureSize = 4; + var tci: gpu.GPUTextureCreateInfo = std.mem.zeroInit(gpu.GPUTextureCreateInfo, .{ + .type = .texturetype2d, + .format = self.noiseTextureFormat, + .usage = .{ .textureusageSampler = true }, + .width = textureSize, + .height = textureSize, + .layer_count_or_depth = 1, + .num_levels = 1, + }); + self.noiseTexture = ctx.device.createGPUTexture(&tci); + + const transferBuffer = ctx.device.createGPUTransferBuffer(&.{ + .usage = .transferbufferusageUpload, + .size = textureSize * textureSize * @sizeOf(f32) * 4, + .props = 0, + }); + defer ctx.device.releaseGPUTransferBuffer(transferBuffer); + + const gtti: gpu.GPUTextureTransferInfo = .{ + .transfer_buffer = transferBuffer, + .offset = 0, + .pixels_per_row = textureSize, + .rows_per_layer = textureSize, + }; + + const data: [*][4]f16 = @ptrCast(@alignCast(ctx.device.mapGPUTransferBuffer(transferBuffer, false))); + for (0..16) |i| { + data[i][0] = @as(f16, @floatCast(rand.float(f32))) * 2.0 - 1.0; + data[i][1] = @as(f16, @floatCast(rand.float(f32))) * 2.0 - 1.0; + data[i][2] = 0.0; + data[i][3] = 0.0; + } + + const cmd = ctx.device.acquireGPUCommandBuffer(); + + const copyPass = cmd.beginGPUCopyPass(); + + const textureRegion = std.mem.zeroInit(gpu.GPUTextureRegion, .{ + .texture = self.noiseTexture, + .w = textureSize, + .h = textureSize, + .d = 1, + }); + + copyPass.uploadToGPUTexture(>ti, &textureRegion, false); + + copyPass.endGPUCopyPass(); + + _ = cmd.submitGPUCommandBuffer(); +} + +pub fn createBuffersAndTextures(self: *@This()) !void { + var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); + + gci.type = .texturetype2d; + gci.format = self.ssaoOutputFormat; + gci.width = @divFloor(@as(u32, @intCast(platform.getInstance().windowExtent.x)), 2); + gci.height = @divFloor(@as(u32, @intCast(platform.getInstance().windowExtent.y)), 2); + gci.layer_count_or_depth = 1; + gci.num_levels = 1; + gci.sample_count = .samplecount1; + gci.usage = .{ + .textureusageSampler = true, + .textureusageColorTarget = true, + }; + + self.ssaoTexture = rend.context().device.createGPUTexture(&gci); +} + +pub fn uploadUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + const ctx = rend.context(); + + var data = std.mem.zeroes([@sizeOf(ssao_frag.Uniforms) / 8 + 1]usize); + const ptr: *ssao_frag.Uniforms = @ptrCast(@alignCast(&data)); + ptr.numSamples = self.numSamples; + ptr.radius = self.radius; + ptr.bias = self.bias; + ptr.extents.x = @floatFromInt(platform.getInstance().windowExtent.x); + ptr.extents.y = @floatFromInt(platform.getInstance().windowExtent.y); + + if (ctx.activeCamera) |camera| { + ptr.ViewProjection = @bitCast(camera.final); + ptr.Projection = @bitCast(camera.projection); + ptr.View = @bitCast(camera.transform); + } + + cmd.pushGPUFragmentUniformData(0, &data, @sizeOf(ssao_frag.Uniforms)); +} + +pub fn render(self: *@This(), cmd: *gpu.GPUCommandBuffer) void { + const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = self.ssaoTexture, + .clear_color = .{ .r = 1.0, .g = 1.0, .b = 1.0, .a = 1.0 }, + .load_op = .loadopClear, + .store_op = .storeopStore, + }); + + const ctx = rend.context(); + const pass = cmd.beginGPURenderPass(&targetInfo, 1, null); + + if (self.enable) { + pass.bindGPUGraphicsPipeline(self.ssaoPipeline); + pass.bindGPUVertexBuffers(0, &.{ .buffer = ctx.meshPool.vertexBuffer, .offset = 0 }, 1); + pass.bindGPUIndexBuffer(&.{ .buffer = ctx.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); + + pass.bindGPUFragmentSamplers(0, &[3]gpu.GPUTextureSamplerBinding{ + .{ .sampler = ctx.blockySampler, .texture = ctx.state.positionTarget }, + .{ .sampler = ctx.linearSampler, .texture = ctx.state.normalTarget }, + .{ .sampler = self.noiseSampler, .texture = self.noiseTexture }, + }, 3); + + self.uploadUniforms(cmd); + + if (rend.context().screenPlane) |mesh| { + pass.drawGPUIndexedPrimitives(mesh.index.size, 1, mesh.index.start, @intCast(mesh.vertex.start), 0); + } + } + + pass.endGPURenderPass(); +} + +pub fn createPipeline(self: *@This()) !void { + const ctx = rend.context(); + const vertex = try ctx.loadShader("postProc.vert", postProc_vert.LoadArgs); + const fragment = try ctx.loadShader("ssao.frag", ssao_frag.LoadArgs); + + var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo); + pci.vertex_shader = vertex; + pci.fragment_shader = fragment; + + var vertexList = try ctx.addVertexAttributes(&pci); + defer vertexList.deinit(); + + pci.target_info.num_color_targets = 1; + pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ + .{ + .format = self.ssaoOutputFormat, + .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState), + }, + }; + + pci.rasterizer_state.cull_mode = .cullmodeNone; + pci.rasterizer_state.fill_mode = .fillmodeFill; + + self.ssaoPipeline = ctx.device.createGPUGraphicsPipeline(&pci); +} + +pub fn destroy(self: *@This()) void { + self.allocator.destroy(self); +} + +const core = @import("core"); +const rend = @import("../rend.zig"); +const std = @import("std"); +const sdl3 = @import("sdl3"); +const platform = @import("platform"); + +const postProc_vert = @import("postProc.vert"); +const ssao_frag = @import("ssao.frag"); + +pub const gpu = sdl3.gpu; diff --git a/engine/ui/src/sgpu/papyrusSgpu.zig b/engine/ui/src/sgpu/papyrusSgpu.zig index 837f52f..e9f18f2 100644 --- a/engine/ui/src/sgpu/papyrusSgpu.zig +++ b/engine/ui/src/sgpu/papyrusSgpu.zig @@ -98,8 +98,6 @@ pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void { } pub fn drawToTarget(self: *@This(), ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void { - _ = targetTexture; - ctx.makeDrawList(&self.drawList, &self.stringArena) catch return; if (self.first) { @@ -109,6 +107,26 @@ pub fn drawToTarget(self: *@This(), ctx: *papyrus.Context, targetTexture: *gpu.G core.engine_log("{any}", .{item}); } } + + const cmd = rend.context().state.cmd.?; + + const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{ + .texture = targetTexture, + .load_op = .loadopLoad, + .store_op = .storeopStore, + }); + + const pass = cmd.beginGPURenderPass(&targetInfo, 1, null); + pass.bindGPUVertexBuffers(1, &.{ .buffer = rend.context().meshPool.vertexBuffer, .offset = 0 }, 1); + pass.bindGPUIndexBuffer(&.{ .buffer = rend.context().meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); + for (self.drawList.items) |item| { + switch (item.primitive) { + .Rect => {}, + .Text => {}, + } + } + + pass.endGPURenderPass(); } pub const rect_frag = @import("rect.frag"); diff --git a/projects/content/_shaders/dxil/lit_mesh.frag.dxil b/projects/content/_shaders/dxil/lit_mesh.frag.dxil index 1918753..ab723e7 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 5b76d0b..817386d 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/dxil/postProc.frag.dxil b/projects/content/_shaders/dxil/postProc.frag.dxil index 04ff011..750c0a3 100644 Binary files a/projects/content/_shaders/dxil/postProc.frag.dxil and b/projects/content/_shaders/dxil/postProc.frag.dxil differ diff --git a/projects/content/_shaders/dxil/ssao.frag.dxil b/projects/content/_shaders/dxil/ssao.frag.dxil new file mode 100644 index 0000000..12b73f9 Binary files /dev/null and b/projects/content/_shaders/dxil/ssao.frag.dxil differ diff --git a/projects/content/_shaders/msl/lit_mesh.frag.msl b/projects/content/_shaders/msl/lit_mesh.frag.msl index 59e33df..5a036d0 100644 --- a/projects/content/_shaders/msl/lit_mesh.frag.msl +++ b/projects/content/_shaders/msl/lit_mesh.frag.msl @@ -28,13 +28,15 @@ struct type_StructuredBuffer_Scene Scene _m0[1]; }; -constant float4 _88 = {}; -constant float3 _90 = {}; +constant float4 _90 = {}; +constant float3 _92 = {}; struct main0_out { float4 out_var_SV_Target0 [[color(0)]]; float4 out_var_SV_Target1 [[color(1)]]; + float4 out_var_SV_Target2 [[color(2)]]; + float4 out_var_SV_Target3 [[color(3)]]; }; struct main0_in @@ -49,145 +51,147 @@ 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 _99 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); - int _100 = _99 & 240; - float4 _134; - if (_100 == 16) + int _101 = int(scene._m0[in.in_var_TEXCOORD4].textureMode); + int _102 = _101 & 240; + float4 _136; + if (_102 == 16) { - float3 _121 = 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); - _134 = float4(dot(_121, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_121, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_121, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); + float3 _123 = 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); + _136 = float4(dot(_123, float3(1.164000034332275390625, 0.0, 1.7929999828338623046875)), dot(_123, float3(1.164000034332275390625, -0.212999999523162841796875, -0.53299999237060546875)), dot(_123, float3(1.164000034332275390625, 2.111999988555908203125, 0.0)), 1.0); } else { - float4 _133; - if (_100 == 0) + float4 _135; + if (_102 == 0) { - _133 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); + _135 = Texture0.sample(Sampler0, in.in_var_TEXCOORD0); } else { - _133 = _88; + _135 = _90; } - _134 = _133; + _136 = _135; } - float4 _140; - if ((_99 & 1) == 1) + float4 _142; + if ((_101 & 1) == 1) { - _140 = powr(_134, float4(2.2000000476837158203125)); + _142 = powr(_136, float4(2.2000000476837158203125)); } else { - _140 = _134; + _142 = _136; } - if (_140.w < 0.00999999977648258209228515625) + if (_142.w < 0.00999999977648258209228515625) { discard_fragment(); } - float3 _150 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower; - float3 _197; + float3 _152 = float3(0.800000011920928955078125, 0.800000011920928955078125, 0.5) * Uniforms.lightPower; + float3 _199; do { - float3 _154 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; - float _155 = length(_154); - float _156 = _155 * _155; - float _162; - if (_155 > 2.0) + float3 _156 = Uniforms.lightPosition.xyz - in.in_var_TEXCOORD1; + float _157 = length(_156); + float _158 = _157 * _157; + float _164; + if (_157 > 2.0) { - _162 = 0.5 / _156; + _164 = 0.5 / _158; } else { - _162 = 1.0 / _156; + _164 = 1.0 / _158; } - float _167; - if (_155 > 4.0) + float _169; + if (_157 > 4.0) { - _167 = _162 * 0.5; + _169 = _164 * 0.5; } else { - _167 = _162; + _169 = _164; } - float _169 = (_155 > 15.0) ? 0.0 : _167; - float _171 = (_169 > 1.0) ? 1.0 : _169; + float _171 = (_157 > 15.0) ? 0.0 : _169; + float _173 = (_171 > 1.0) ? 1.0 : _171; if (length(in.in_var_TEXCOORD2) < 0.100000001490116119384765625) { - _197 = (in.in_var_TEXCOORD1 * _150) * _171; + _199 = (in.in_var_TEXCOORD1 * _152) * _173; break; } - float3 _178 = fast::normalize(_154); - _197 = ((_150 * precise::max(dot(_178, in.in_var_TEXCOORD2), 0.0)) * _171) + (((_150 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_178 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _171); + float3 _180 = fast::normalize(_156); + _199 = ((_152 * precise::max(dot(_180, in.in_var_TEXCOORD2), 0.0)) * _173) + (((_152 * powr(precise::max(dot(in.in_var_TEXCOORD2, fast::normalize(_180 + fast::normalize(in.in_var_TEXCOORD1 - Uniforms.viewPos.xyz))), 0.0), 30.0)) * 2.0) * _173); break; } while(false); - float3 _214 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); - float3 _216; - _216.x = _214.x; - float2 _217 = _216.xy; - _217.y = -_214.y; - float _224; - int _227; + float3 _216 = ((in.in_var_TEXCOORD3.xyz / float3(in.in_var_TEXCOORD3.w)) * 0.5) + float3(0.5); + float3 _218; + _218.x = _216.x; + float2 _219 = _218.xy; + _219.y = -_216.y; + float _226; int _229; - _224 = 0.0; - _227 = 0; - _229 = -4; - float _225; - int _228; - for (; _229 <= 4; _224 = _225, _227 = _228, _229++) + int _231; + _226 = 0.0; + _229 = 0; + _231 = -4; + float _227; + int _230; + for (; _231 <= 4; _226 = _227, _229 = _230, _231++) { - _228 = _227; - _225 = _224; - for (int _238 = -4; _238 <= 4; ) + _230 = _229; + _227 = _226; + for (int _240 = -4; _240 <= 4; ) { - _228++; - _225 += float((in.in_var_TEXCOORD3.z - 0.004999999888241291046142578125) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_217 + float2(float(_238) * 0.000244140625, float(_229) * 0.000244140625))).x); - _238++; + _230++; + _227 += float((in.in_var_TEXCOORD3.z - 0.004999999888241291046142578125) > DirectionalShadowDepthMap.sample(DirectionalShadowSampler, (_219 + float2(float(_240) * 0.000244140625, float(_231) * 0.000244140625))).x); + _240++; continue; } } - float3 _267; - if ((_99 & 2) > 0) + float3 _269; + if ((_101 & 2) > 0) { - _267 = _140.xyz * 2.0; + _269 = _142.xyz * 2.0; } else { - _267 = _140.xyz * ((float3(0.100000001490116119384765625) + _197) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_224 / float(_227))))); - } - float4 _276; - if (_267.x > 1.0) - { - float4 _275 = float4(0.0, 0.0, 0.0, 1.0); - _275.x = _267.x; - _276 = _275; - } - else - { - _276 = float4(0.0, 0.0, 0.0, 1.0); - } - float4 _281; - if (_267.y > 1.0) - { - float4 _280 = _276; - _280.y = _267.y; - _281 = _280; - } - else - { - _281 = _276; + _269 = _142.xyz * ((float3(0.100000001490116119384765625) + _199) + ((Uniforms.directionalLightColor.xyz * precise::max(dot(Uniforms.directionalLight.xyz, in.in_var_TEXCOORD2), 0.0)) * (1.0 - (_226 / float(_229))))); } float4 _286; - if (_267.z > 1.0) + if (_269.x > 1.0) { - float4 _285 = _281; - _285.z = _267.z; + float4 _285 = float4(0.0, 0.0, 0.0, 1.0); + _285.x = _269.x; _286 = _285; } else { - _286 = _281; + _286 = float4(0.0, 0.0, 0.0, 1.0); } - out.out_var_SV_Target0 = float4(_267, _140.w); - out.out_var_SV_Target1 = _286; + float4 _291; + if (_269.y > 1.0) + { + float4 _290 = _286; + _290.y = _269.y; + _291 = _290; + } + else + { + _291 = _286; + } + float4 _296; + if (_269.z > 1.0) + { + float4 _295 = _291; + _295.z = _269.z; + _296 = _295; + } + else + { + _296 = _291; + } + out.out_var_SV_Target0 = float4(_269, _142.w); + out.out_var_SV_Target1 = _296; + out.out_var_SV_Target2 = float4(in.in_var_TEXCOORD1, 1.0); + out.out_var_SV_Target3 = float4(in.in_var_TEXCOORD2, 1.0); return out; } diff --git a/projects/content/_shaders/msl/meshes.vert.msl b/projects/content/_shaders/msl/meshes.vert.msl index 55d2e3c..4e8f7a3 100644 --- a/projects/content/_shaders/msl/meshes.vert.msl +++ b/projects/content/_shaders/msl/meshes.vert.msl @@ -44,14 +44,14 @@ 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)]], uint gl_InstanceIndex [[instance_id]]) { main0_out out = {}; - float4 _52 = float4(in.in_var_TEXCOORD0, 1.0); - float4 _55 = scene._m0[gl_InstanceIndex].Model * _52; + float4 _51 = float4(in.in_var_TEXCOORD0, 1.0); + float4 _54 = scene._m0[gl_InstanceIndex].Model * _51; out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3; - out.out_var_TEXCOORD1 = _55.xyz; - out.out_var_TEXCOORD2 = float3((in.in_var_TEXCOORD1 * float4x3(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).xyz, 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).xyz, 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).xyz, float3(0.0))).xyz); - out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _55; + out.out_var_TEXCOORD1 = _54.xyz; + out.out_var_TEXCOORD2 = fast::normalize(float4(in.in_var_TEXCOORD1, 1.0) * 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))).xyz; + out.out_var_TEXCOORD3 = Uniforms.ShadowMapProjection * _54; out.out_var_TEXCOORD4 = gl_InstanceIndex; - out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _52); + out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _51); return out; } diff --git a/projects/content/_shaders/msl/postProc.frag.msl b/projects/content/_shaders/msl/postProc.frag.msl index e2a7c04..49e57cd 100644 --- a/projects/content/_shaders/msl/postProc.frag.msl +++ b/projects/content/_shaders/msl/postProc.frag.msl @@ -13,31 +13,31 @@ struct main0_in float2 in_var_TEXCOORD0 [[user(locn0)]]; }; -fragment main0_out main0(main0_in in [[stage_in]], texture2d ColorTexture [[texture(0)]], texture2d EmissiveTexture [[texture(1)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]]) +fragment main0_out main0(main0_in in [[stage_in]], texture2d ColorTexture [[texture(0)]], texture2d EmissiveTexture [[texture(1)]], texture2d SsaoTexture [[texture(2)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]], sampler Sampler2 [[sampler(2)]]) { main0_out out = {}; - float2 _43 = in.in_var_TEXCOORD0; - _43.y = (_43.y * (-1.0)) + 1.0; - float4 _51 = ColorTexture.sample(Sampler0, _43); - float3 _52 = _51.xyz; - float3 _66; - int _69; - _66 = EmissiveTexture.sample(Sampler1, _43).xyz * 0.2270270287990570068359375; - _69 = 0; - float3 _67; - for (; _69 < 5; _66 = _67, _69++) + float2 _45 = in.in_var_TEXCOORD0; + _45.y = (_45.y * (-1.0)) + 1.0; + float4 _53 = ColorTexture.sample(Sampler0, _45); + float3 _54 = _53.xyz; + float3 _68; + int _71; + _68 = EmissiveTexture.sample(Sampler1, _45).xyz * 0.2270270287990570068359375; + _71 = 0; + float3 _69; + for (; _71 < 5; _68 = _69, _71++) { - _67 = _66; - for (int _77 = 0; _77 < 5; ) + _69 = _68; + for (int _79 = 0; _79 < 5; ) { - float2 _85 = float2(float(_69) - 2.5, float(_77)) * float2(0.001953125); - _67 = (_67 + (EmissiveTexture.sample(Sampler1, (_43 + _85)).xyz * float3(0.039999999105930328369140625))) + (EmissiveTexture.sample(Sampler1, (_43 - _85)).xyz * float3(0.039999999105930328369140625)); - _77++; + float2 _87 = float2(float(_71) - 2.5, float(_79)) * float2(0.001953125); + _69 = (_69 + (EmissiveTexture.sample(Sampler1, (_45 + _87)).xyz * float3(0.039999999105930328369140625))) + (EmissiveTexture.sample(Sampler1, (_45 - _87)).xyz * float3(0.039999999105930328369140625)); + _79++; continue; } } - float3 _99 = (powr((_52 * (float3(1.0) + (_52 * float3(0.00999999977648258209228515625)))) / (float3(1.0) + _52), float3(0.4545454680919647216796875)) + (_66 * 0.0500000007450580596923828125)) * 1.0; - out.out_var_SV_Target0 = float4((_99.x * (1.0 + (9.9999999747524270787835121154785e-07 * EmissiveTexture.sample(Sampler1, _43).x))) * (1.0 + (9.9999999747524270787835121154785e-07 * ColorTexture.sample(Sampler0, _43).x)), _99.yz, 1.0); + float3 _107 = ((powr((_54 * (float3(1.0) + (_54 * float3(0.00999999977648258209228515625)))) / (float3(1.0) + _54), float3(0.4545454680919647216796875)) + (_68 * 0.0500000007450580596923828125)) * 1.0) * SsaoTexture.sample(Sampler2, _45).x; + out.out_var_SV_Target0 = float4(((_107.x * (1.0 + (9.9999999747524270787835121154785e-07 * EmissiveTexture.sample(Sampler1, _45).x))) * (1.0 + (9.9999999747524270787835121154785e-07 * ColorTexture.sample(Sampler0, _45).x))) * (1.0 + (9.9999999747524270787835121154785e-07 * SsaoTexture.sample(Sampler2, _45).x)), _107.yz, 1.0); return out; } diff --git a/projects/content/_shaders/msl/ssao.frag.msl b/projects/content/_shaders/msl/ssao.frag.msl new file mode 100644 index 0000000..31f85f1 --- /dev/null +++ b/projects/content/_shaders/msl/ssao.frag.msl @@ -0,0 +1,115 @@ +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wmissing-braces" + +#include +#include + +using namespace metal; + +template +struct spvUnsafeArray +{ + T elements[Num ? Num : 1]; + + thread T& operator [] (size_t pos) thread + { + return elements[pos]; + } + constexpr const thread T& operator [] (size_t pos) const thread + { + return elements[pos]; + } + + device T& operator [] (size_t pos) device + { + return elements[pos]; + } + constexpr const device T& operator [] (size_t pos) const device + { + return elements[pos]; + } + + constexpr const constant T& operator [] (size_t pos) const constant + { + return elements[pos]; + } + + threadgroup T& operator [] (size_t pos) threadgroup + { + return elements[pos]; + } + constexpr const threadgroup T& operator [] (size_t pos) const threadgroup + { + return elements[pos]; + } +}; + +struct type_Uniforms +{ + float4x4 View; + float4x4 ViewProjection; + float4x4 Projection; + float2 extents; + float radius; + float bias0; + int numSamples; +}; + +constant spvUnsafeArray _311 = spvUnsafeArray({ float3(0.0), float3(0.00039307403494603931903839111328125, 0.00020744701032526791095733642578125, 0.00023402007354889065027236938476562), float3(-0.001318361726589500904083251953125, -0.001457856036722660064697265625, 0.001546739018522202968597412109375), float3(0.0003496186691336333751678466796875, 8.4181214333511888980865478515625e-05, 5.8608897234080359339714050292969e-05), float3(-0.0005043491837568581104278564453125, -0.00383304059505462646484375, 0.002929248847067356109619140625), float3(-0.00241771643050014972686767578125, 0.0057135238312184810638427734375, 0.00173364556394517421722412109375), float3(-0.0007101023220457136631011962890625, 0.000413290224969387054443359375, 0.00037520084879361093044281005859375), float3(1.5587833331665024161338806152344e-05, -0.00011572847870411351323127746582031, 7.3567920480854809284210205078125e-05), float3(0.00334032182581722736358642578125, -0.0051653436385095119476318359375, 0.0050431825220584869384765625), float3(-0.0063966461457312107086181640625, 0.01290071941912174224853515625, 0.00147703452967107295989990234375), float3(0.007907788269221782684326171875, -0.0049759554676711559295654296875, 0.001991991885006427764892578125), float3(-0.0003332807100377976894378662109375, -0.00100087863393127918243408203125, 0.001031001214869320392608642578125), float3(0.00011193146201549097895622253417969, 0.00036116360570304095745086669921875, 0.0010905899107456207275390625), float3(-0.00385366589762270450592041015625, -0.004629385657608509063720703125, 0.00270807673223316669464111328125), float3(-0.0055218120105564594268798828125, 0.0163907893002033233642578125, 0.0033264369703829288482666015625), float3(-0.00297828204929828643798828125, -0.00340225151740014553070068359375, 0.0009606514940969645977020263671875), float3(0.0005643319454975426197052001953125, -0.00123721174895763397216796875, 0.001142332912422716617584228515625), float3(0.0042646829970180988311767578125, 0.001690786913968622684478759765625, 0.00338359293527901172637939453125), float3(0.028113491833209991455078125, -0.01881640218198299407958984375, 0.0140878893435001373291015625), float3(-0.03022454865276813507080078125, -0.000894616474397480487823486328125, 0.008499112911522388458251953125), float3(-0.01961914263665676116943359375, -0.0350324176251888275146484375, 0.014081305824220180511474609375), float3(0.015496986918151378631591796875, -0.010903127491474151611328125, 0.00180752319283783435821533203125), float3(0.0196535401046276092529296875, 0.01710924692451953887939453125, 0.0142847932875156402587890625), float3(-0.02892612479627132415771484375, 0.00322483875788748264312744140625, 0.06573773920536041259765625), float3(-0.0016983882524073123931884765625, 0.0004074592725373804569244384765625, 0.00372933782637119293212890625), float3(-0.0335367508232593536376953125, 0.0591063164174556732177734375, 0.001477129175327718257904052734375), float3(0.01729742996394634246826171875, 0.02095410041511058807373046875, 0.061427496373653411865234375), float3(-0.0362440533936023712158203125, -0.01097334362566471099853515625, 0.052580632269382476806640625), float3(-0.010873113758862018585205078125, 0.071666888892650604248046875, 0.07090236246585845947265625), float3(0.0404303781688213348388671875, -0.0758908092975616455078125, 0.066407024860382080078125), float3(0.006424785591661930084228515625, -0.00888848863542079925537109375, 0.00571323931217193603515625), float3(-0.0424978695809841156005859375, 0.122786454856395721435546875, 0.03013108484447002410888671875), float3(-0.012614764273166656494140625, -0.01173587143421173095703125, 0.0161450766026973724365234375), float3(0.02246730588376522064208984375, -0.023659668862819671630859375, 0.01735904999077320098876953125), float3(0.0280994363129138946533203125, -0.0286351330578327178955078125, 0.0076164784841239452362060546875), float3(0.0701790750026702880859375, -0.1532168686389923095703125, 0.0887149870395660400390625), float3(0.0073889424093067646026611328125, 0.152280390262603759765625, 0.00664083100855350494384765625), float3(0.07831905782222747802734375, -0.072104983031749725341796875, 0.094614334404468536376953125), float3(0.03289596736431121826171875, -0.0408993400633335113525390625, 0.040609411895275115966796875), float3(-0.141404449939727783203125, 0.17826557159423828125, 0.067046172916889190673828125), float3(0.108955644071102142333984375, 0.1114947497844696044921875, 0.21018303930759429931640625), float3(0.02759261615574359893798828125, 0.0139005817472934722900390625, 0.036677159368991851806640625), float3(0.05564410984516143798828125, -0.099730752408504486083984375, 0.113144241273403167724609375), float3(-0.0315654389560222625732421875, -0.22426509857177734375, 0.23739193379878997802734375), float3(-0.0474216155707836151123046875, 0.00566783733665943145751953125, 0.1736856400966644287109375), float3(0.088452465832233428955078125, 0.096331931650638580322265625, 0.083578832447528839111328125), float3(-0.0036428333260118961334228515625, 0.010955554433166980743408203125, 0.00330849713645875453948974609375), float3(-0.1911892592906951904296875, -0.18971312046051025390625, 0.1564487516880035400390625), float3(0.034361146390438079833984375, 0.0655452907085418701171875, 0.0308254323899745941162109375), float3(0.371889293193817138671875, 0.0229042805731296539306640625, 0.2982411682605743408203125), float3(-0.014679887332022190093994140625, 0.01349230110645294189453125, 0.00740495882928371429443359375), float3(-0.00653826631605625152587890625, -0.0058869807980954647064208984375, 0.005725885741412639617919921875), float3(-0.2333120405673980712890625, -0.35499393939971923828125, 0.03432808816432952880859375), float3(0.0411357469856739044189453125, -0.023320116102695465087890625, 0.01891444809734821319580078125), float3(-0.0945928990840911865234375, 0.02529100514948368072509765625, 0.092956520617008209228515625), float3(-0.0317381806671619415283203125, 0.226026356220245361328125, 0.2367977797985076904296875), float3(-0.3801217377185821533203125, 0.2481244504451751708984375, 0.47917068004608154296875), float3(0.13565014302730560302734375, 0.13791494071483612060546875, 0.4077457487583160400390625), float3(0.523879945278167724609375, -0.388758122920989990234375, 0.24387760460376739501953125), float3(-0.0520826168358325958251953125, -0.118409633636474609375, 0.095709107816219329833984375), float3(0.122609488666057586669921875, -0.4220634996891021728515625, 0.178109467029571533203125), float3(-0.2801954448223114013671875, -0.520291268825531005859375, 0.26809024810791015625), float3(-0.3271856009960174560546875, 0.23393590748310089111328125, 0.098123751580715179443359375), float3(0.3826406896114349365234375, 0.08367092907428741455078125, 0.257561206817626953125) }); + +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]], constant type_Uniforms& Uniforms [[buffer(0)]], texture2d PositionTexture [[texture(0)]], texture2d NormalTexture [[texture(1)]], texture2d NoiseTexture [[texture(2)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]], sampler Sampler2 [[sampler(2)]]) +{ + main0_out out = {}; + float2 _314 = in.in_var_TEXCOORD0; + float4 _410; + do + { + _314.y = (_314.y * (-1.0)) + 1.0; + float4 _326 = PositionTexture.sample(Sampler0, _314); + float4 _327 = Uniforms.View * _326; + float3 _328 = _327.xyz; + float _329 = _327.z; + if (_329 < 0.00999999977648258209228515625) + { + _410 = float4(1.0); + break; + } + float4 _336 = NormalTexture.sample(Sampler1, _314); + float3 _339 = fast::normalize((Uniforms.View * _336).xyz); + float4 _344 = NoiseTexture.sample(Sampler2, (_314 * float2(320.0, 180.0))); + float3 _346 = fast::normalize(_344.xyz); + float3 _350 = fast::normalize(_346 - (_339 * dot(_346, _339))); + float3x3 _352 = float3x3(_350, cross(_339, _350), _339); + float _354; + _354 = 0.0; + for (int _357 = 0; _357 < Uniforms.numSamples; ) + { + float3 _369 = _328 + ((_311[_357] * _352) * Uniforms.radius); + float4 _376 = Uniforms.Projection * float4(_369, 1.0); + float3 _383 = ((_376.xyz / float3(_376.w)).xyz * 0.5) + float3(0.5); + float4 _384 = float4(_383.x, _383.y, _383.z, _376.w); + _384.y = _383.y * (-1.0); + float4 _391 = Uniforms.View * PositionTexture.sample(Sampler0, _384.xy); + float _392 = _391.z; + _354 += (float(_392 >= (_369.z + Uniforms.bias0)) * smoothstep(0.0, 1.0, Uniforms.radius / abs(_329 - _392))); + _357++; + continue; + } + float _405 = 1.0 - (_354 / float(Uniforms.numSamples)); + _410 = float4(_405) + float4(_405 * 9.9999997473787516355514526367188e-06); + break; + } while(false); + out.out_var_SV_Target0 = _410; + return out; +} + diff --git a/projects/content/_shaders/spv/lit_mesh.frag.spv b/projects/content/_shaders/spv/lit_mesh.frag.spv index 13a99ea..b2e4ad4 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 9848202..b0b1c96 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/_shaders/spv/postProc.frag.spv b/projects/content/_shaders/spv/postProc.frag.spv index 9f5a7d1..76a405b 100644 Binary files a/projects/content/_shaders/spv/postProc.frag.spv and b/projects/content/_shaders/spv/postProc.frag.spv differ diff --git a/projects/content/_shaders/spv/ssao.frag.spv b/projects/content/_shaders/spv/ssao.frag.spv new file mode 100644 index 0000000..0bc7ed7 Binary files /dev/null and b/projects/content/_shaders/spv/ssao.frag.spv differ