Skip to content

Commit 80ff4a4

Browse files
committed
Added slang shaders for ssao sample
1 parent 8d50885 commit 80ff4a4

6 files changed

Lines changed: 261 additions & 0 deletions

File tree

shaders/slang/ssao/blur.slang

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
import types;
8+
9+
Sampler2D samplerSSAO;
10+
11+
[shader("fragment")]
12+
float4 fragmentMain(VSOutput input)
13+
{
14+
const int blurRange = 2;
15+
int n = 0;
16+
int2 texDim;
17+
samplerSSAO.GetDimensions(texDim.x, texDim.y);
18+
float2 texelSize = 1.0 / (float2)texDim;
19+
float result = 0.0;
20+
for (int x = -blurRange; x <= blurRange; x++)
21+
{
22+
for (int y = -blurRange; y <= blurRange; y++)
23+
{
24+
float2 offset = float2(float(x), float(y)) * texelSize;
25+
result += samplerSSAO.Sample(input.UV + offset).r;
26+
n++;
27+
}
28+
}
29+
return result / (float(n));
30+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
import types;
8+
9+
Sampler2D samplerposition;
10+
Sampler2D samplerNormal;
11+
Sampler2D samplerAlbedo;
12+
Sampler2D samplerSSAO;
13+
Sampler2D samplerSSAOBlur;
14+
15+
struct UBO
16+
{
17+
float4x4 _dummy;
18+
int ssao;
19+
int ssaoOnly;
20+
int ssaoBlur;
21+
};
22+
ConstantBuffer<UBO> uboParams;
23+
24+
[shader("fragment")]
25+
float4 fragmentMain(VSOutput input)
26+
{
27+
float3 fragPos = samplerposition.Sample(input.UV).rgb;
28+
float3 normal = normalize(samplerNormal.Sample(input.UV).rgb * 2.0 - 1.0);
29+
float4 albedo = samplerAlbedo.Sample(input.UV);
30+
31+
float ssao = (uboParams.ssaoBlur == 1) ? samplerSSAOBlur.Sample(input.UV).r : samplerSSAO.Sample(input.UV).r;
32+
33+
float3 lightPos = float3(0.0, 0.0, 0.0);
34+
float3 L = normalize(lightPos - fragPos);
35+
float NdotL = max(0.5, dot(normal, L));
36+
37+
float4 outFragColor;
38+
if (uboParams.ssaoOnly == 1)
39+
{
40+
outFragColor.rgb = ssao.rrr;
41+
}
42+
else
43+
{
44+
float3 baseColor = albedo.rgb * NdotL;
45+
46+
if (uboParams.ssao == 1)
47+
{
48+
outFragColor.rgb = ssao.rrr;
49+
50+
if (uboParams.ssaoOnly != 1)
51+
outFragColor.rgb *= baseColor;
52+
}
53+
else
54+
{
55+
outFragColor.rgb = baseColor;
56+
}
57+
}
58+
return outFragColor;
59+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
import types;
8+
9+
[shader("vertex")]
10+
VSOutput vertexMain(uint VertexIndex : SV_VertexID)
11+
{
12+
VSOutput output;
13+
output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2);
14+
output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f);
15+
return output;
16+
}

shaders/slang/ssao/gbuffer.slang

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
struct VSInput
8+
{
9+
float4 Pos;
10+
float2 UV;
11+
float3 Color;
12+
float3 Normal;
13+
};
14+
15+
struct VSOutput
16+
{
17+
float4 Pos : SV_POSITION;
18+
float3 Normal;
19+
float2 UV;
20+
float3 Color;
21+
float3 WorldPos;
22+
};
23+
24+
struct FSOutput
25+
{
26+
float4 Position : SV_TARGET0;
27+
float4 Normal : SV_TARGET1;
28+
float4 Albedo : SV_TARGET2;
29+
};
30+
31+
struct UBO
32+
{
33+
float4x4 projection;
34+
float4x4 model;
35+
float4x4 view;
36+
float nearPlane;
37+
float farPlane;
38+
};
39+
ConstantBuffer<UBO> ubo;
40+
41+
[[vk::binding(0, 1)]] Texture2D textureColorMap;
42+
[[vk::binding(0, 1)]] SamplerState samplerColorMap;
43+
44+
[shader("vertex")]
45+
VSOutput vertexMain(VSInput input)
46+
{
47+
VSOutput output;
48+
output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, input.Pos)));
49+
output.UV = input.UV;
50+
// Vertex position in view space
51+
output.WorldPos = mul(ubo.view, mul(ubo.model, input.Pos)).xyz;
52+
// Normal in view space
53+
float3x3 normalMatrix = (float3x3)mul(ubo.view, ubo.model);
54+
output.Normal = mul(normalMatrix, input.Normal);
55+
output.Color = input.Color;
56+
return output;
57+
}
58+
59+
float linearDepth(float depth)
60+
{
61+
float z = depth * 2.0f - 1.0f;
62+
return (2.0f * ubo.nearPlane * ubo.farPlane) / (ubo.farPlane + ubo.nearPlane - z * (ubo.farPlane - ubo.nearPlane));
63+
}
64+
65+
[shader("fragment")]
66+
FSOutput fragmentMain(VSOutput input)
67+
{
68+
FSOutput output;
69+
output.Position = float4(input.WorldPos, linearDepth(input.Pos.z));
70+
output.Normal = float4(normalize(input.Normal) * 0.5 + 0.5, 1.0);
71+
output.Albedo = textureColorMap.Sample(samplerColorMap, input.UV) * float4(input.Color, 1.0);
72+
return output;
73+
}

shaders/slang/ssao/ssao.slang

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
import types;
8+
9+
Sampler2D samplerPositionDepth;
10+
Sampler2D samplerNormal;
11+
Sampler2D ssaoNoiseSampler;
12+
13+
struct UBOSSAOKernel
14+
{
15+
float4 samples[64];
16+
};
17+
ConstantBuffer<UBOSSAOKernel> uboSSAOKernel;
18+
19+
struct UBO
20+
{
21+
float4x4 projection;
22+
};
23+
ConstantBuffer<UBO> ubo;
24+
25+
[[SpecializationConstant]] const int SSAO_KERNEL_SIZE = 64;
26+
[[SpecializationConstant]] const float SSAO_RADIUS = 0.5;
27+
28+
[shader("fragment")]
29+
float fragmentMain(VSOutput input)
30+
{
31+
// Get G-Buffer values
32+
float3 fragPos = samplerPositionDepth.Sample(input.UV).rgb;
33+
float3 normal = normalize(samplerNormal.Sample(input.UV).rgb * 2.0 - 1.0);
34+
35+
// Get a random vector using a noise lookup
36+
int2 texDim;
37+
samplerPositionDepth.GetDimensions(texDim.x, texDim.y);
38+
int2 noiseDim;
39+
ssaoNoiseSampler.GetDimensions(noiseDim.x, noiseDim.y);
40+
const float2 noiseUV = float2(float(texDim.x) / float(noiseDim.x), float(texDim.y) / (noiseDim.y)) * input.UV;
41+
float3 randomVec = ssaoNoiseSampler.Sample(noiseUV).xyz * 2.0 - 1.0;
42+
43+
// Create TBN matrix
44+
float3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
45+
float3 bitangent = cross(tangent, normal);
46+
float3x3 TBN = transpose(float3x3(tangent, bitangent, normal));
47+
48+
// Calculate occlusion value
49+
float occlusion = 0.0f;
50+
for(int i = 0; i < SSAO_KERNEL_SIZE; i++)
51+
{
52+
float3 samplePos = mul(TBN, uboSSAOKernel.samples[i].xyz);
53+
samplePos = fragPos + samplePos * SSAO_RADIUS;
54+
55+
// project
56+
float4 offset = float4(samplePos, 1.0f);
57+
offset = mul(ubo.projection, offset);
58+
offset.xyz /= offset.w;
59+
offset.xyz = offset.xyz * 0.5f + 0.5f;
60+
61+
float sampleDepth = -samplerPositionDepth.Sample(offset.xy).w;
62+
63+
float rangeCheck = smoothstep(0.0f, 1.0f, SSAO_RADIUS / abs(fragPos.z - sampleDepth));
64+
occlusion += (sampleDepth >= samplePos.z ? 1.0f : 0.0f) * rangeCheck;
65+
}
66+
occlusion = 1.0 - (occlusion / float(SSAO_KERNEL_SIZE));
67+
68+
return occlusion;
69+
}
70+

shaders/slang/ssao/types.slang

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
module types;
8+
9+
public struct VSOutput
10+
{
11+
public float4 Pos : SV_POSITION;
12+
public float2 UV;
13+
};

0 commit comments

Comments
 (0)