very shitty ssao implementation

This commit is contained in:
Peter Li 2025-05-10 17:27:37 -07:00
parent 5ecd94d92f
commit cd902baa85
28 changed files with 900 additions and 132 deletions

View File

@ -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],

View File

@ -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});

View File

@ -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();
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -4,6 +4,9 @@ SamplerState Sampler0 : register(s0, space2);
Texture2D<float4> EmissiveTexture : register(t1, space2);
SamplerState Sampler1 : register(s1, space2);
Texture2D<float4> 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);
}

View File

@ -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
}
]
}

View File

@ -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 ),
};

View File

@ -0,0 +1,79 @@
Texture2D<float4> PositionTexture : register(t0, space2);
SamplerState Sampler0 : register(s0, space2);
Texture2D<float4> NormalTexture : register(t1, space2);
SamplerState Sampler1 : register(s1, space2);
Texture2D<float4> 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;
}

View File

@ -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
}
]
}

View File

@ -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;

View File

@ -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");

View File

@ -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(&gtti, &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;

View File

@ -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");

Binary file not shown.

View File

@ -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<float> Texture0 [[texture(0)]], texture2d<float> Texture1 [[texture(1)]], texture2d<float> Texture2 [[texture(2)]], texture2d<float> 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;
}

View File

@ -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;
}

View File

@ -13,31 +13,31 @@ struct main0_in
float2 in_var_TEXCOORD0 [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> ColorTexture [[texture(0)]], texture2d<float> EmissiveTexture [[texture(1)]], sampler Sampler0 [[sampler(0)]], sampler Sampler1 [[sampler(1)]])
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> ColorTexture [[texture(0)]], texture2d<float> EmissiveTexture [[texture(1)]], texture2d<float> 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;
}

File diff suppressed because one or more lines are too long

Binary file not shown.