Skip to content

Commit 90073f4

Browse files
committed
improve ssao shader (rename stuff to match)
1 parent a35aeb1 commit 90073f4

File tree

6 files changed

+119
-84
lines changed

6 files changed

+119
-84
lines changed

data/cage/shaders/effects/effects.assets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
[]
32
scheme = pack
43
effects.pack
@@ -15,6 +14,7 @@ luminanceApply.glsl
1514
luminanceCollection.glsl
1615
luminanceHistogram.glsl
1716
sharpening.glsl
17+
ssaoDownscaleDepth.glsl
1818
ssaoGenerate.glsl
1919
ssaoResolve.glsl
2020
tonemap.glsl

data/cage/shaders/effects/effects.pack

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
[]
32
bloomApply.glsl
43
bloomGenerate.glsl
@@ -10,6 +9,7 @@ luminanceApply.glsl
109
luminanceCollection.glsl
1110
luminanceHistogram.glsl
1211
sharpening.glsl
12+
ssaoDownscaleDepth.glsl
1313
ssaoGenerate.glsl
1414
ssaoResolve.glsl
1515
tonemap.glsl
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
$include ../shaderConventions.h
3+
4+
$define shader vertex
5+
6+
layout(location = CAGE_SHADER_ATTRIB_IN_POSITION) in vec3 inPosition;
7+
layout(location = CAGE_SHADER_ATTRIB_IN_UV) in vec3 inUv;
8+
out vec2 varUv;
9+
10+
void main()
11+
{
12+
gl_Position = vec4(inPosition.xy * 2 - 1, inPosition.z, 1);
13+
varUv = inUv.xy;
14+
varUv.y = 1 - varUv.y;
15+
}
16+
17+
$define shader fragment
18+
19+
layout(binding = 0) uniform sampler2D texDepth;
20+
in vec2 varUv;
21+
out float outDepth;
22+
23+
void main()
24+
{
25+
outDepth = textureLod(texDepth, varUv, 0).x;
26+
}

data/cage/shaders/effects/ssaoGenerate.glsl

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,67 +7,84 @@ $define shader fragment
77

88
$include ../functions/common.glsl
99
$include ../functions/hash.glsl
10-
$include ssaoParams.glsl
10+
//$include ssaoParams.glsl
11+
12+
13+
layout(std140, binding = CAGE_SHADER_UNIBLOCK_CUSTOMDATA) uniform Ssao
14+
{
15+
mat4 proj;
16+
mat4 projInv;
17+
vec4 params; // strength, bias, power, radius
18+
ivec4 iparams; // sampleCount, hashSeed
19+
};
20+
1121

1222
layout(std140, binding = 3) uniform SsaoPoints
1323
{
24+
// unit sphere samples; .w is [0,1] random scalar
1425
vec4 pointsOnSphere[256];
1526
};
1627

17-
layout(binding = 0) uniform sampler2D texDepth;
28+
layout(binding = 0) uniform sampler2D texDepth; // NDC depth [0,1]
1829

1930
out float outAo;
2031

21-
vec3 reconstructNormal(vec3 position)
22-
{
23-
return normalize(cross(dFdx(position), dFdy(position)));
24-
}
25-
26-
vec3 s2w(vec2 p, float d)
32+
// inputs in NDC [-1,1]
33+
vec3 ndcToView(vec2 p, float d)
2734
{
2835
vec4 p4 = vec4(p, d, 1);
2936
p4 = projInv * p4;
3037
return p4.xyz / p4.w;
3138
}
3239

40+
// all view-space
41+
vec3 reconstructNormal(vec3 position)
42+
{
43+
return normalize(cross(dFdx(position), dFdy(position)));
44+
}
45+
3346
void main()
3447
{
3548
vec2 resolution = vec2(textureSize(texDepth, 0));
36-
vec2 myUv = gl_FragCoord.xy / resolution;
37-
float myDepth = textureLod(texDepth, myUv, 0).x * 2.0 - 1.0;
49+
vec2 myUv = gl_FragCoord.xy / resolution; // screen-space [0,1]
50+
float myDepth = textureLod(texDepth, myUv, 0).x * 2 - 1; // NDC depth [-1,1]
3851
if (myDepth > 0.999)
3952
{ // no occlusion on skybox
4053
outAo = 0;
4154
return;
4255
}
43-
vec3 myPos = s2w(myUv, myDepth);
44-
vec3 myNormal = reconstructNormal(myPos);
56+
vec3 myPos = ndcToView(myUv * 2 - 1, myDepth); // view-space position
57+
vec3 myNormal = reconstructNormal(myPos); // view-space normal
4558

4659
// sampling
47-
int n = int(hash(uint(gl_FragCoord.x) ^ hash(uint(gl_FragCoord.y)) ^ uint(iparams[1])));
60+
uint n = hash(uint(gl_FragCoord.x) ^ hash(uint(gl_FragCoord.y)) ^ uint(iparams[1])); // per-pixel seed
4861
float ssaoRadius = params[3];
49-
float occ = 0.0;
50-
float total = 0.0;
62+
float occ = 0;
63+
float total = 0;
5164
for (int i = 0; i < iparams[0]; i++)
5265
{
53-
vec3 dir = pointsOnSphere[hash(uint(n * 17 + i)) % 256].xyz;
54-
float d = dot(myNormal, dir);
66+
// view-space ray direction
67+
vec3 rayDir = pointsOnSphere[hash(uint(n * 17 + i)) % 256].xyz;
68+
float d = dot(myNormal, rayDir);
5569
if (abs(d) < 0.1)
5670
continue; // the direction is close to the surface and susceptible to noise
57-
dir = sign(d) * dir; // move the direction into front hemisphere
58-
float r = (sqr(pointsOnSphere[hash(uint(n * 13 + i)) % 256].w) * 0.9 + 0.1) * ssaoRadius;
59-
vec3 sw = myPos + dir * r;
60-
vec4 s4 = proj * vec4(sw, 1.0);
61-
vec3 ss = s4.xyz / s4.w;
62-
float sampleDepth = textureLod(texDepth, ss.xy, 0).x * 2.0 - 1.0;
63-
if (sampleDepth < ss.z)
71+
rayDir = sign(d) * rayDir; // move the direction into front hemisphere
72+
rayDir *= (sqr(pointsOnSphere[hash(uint(n * 13 + i)) % 256].w) * 0.9 + 0.1) * ssaoRadius;
73+
74+
vec3 rayPos = myPos + rayDir; // view-space ray position
75+
vec4 r4 = proj * vec4(rayPos, 1); // clip space
76+
vec3 rayNdc = r4.xyz / r4.w; // NDC [-1,1]
77+
78+
float sampleDepth = textureLod(texDepth, rayNdc.xy * 0.5 + 0.5, 0).x * 2 - 1; // NDC depth [-1,1]
79+
if (sampleDepth < rayNdc.z)
6480
{
65-
vec3 otherPos = s2w(ss.xy, sampleDepth);
66-
float diff = length(sw - otherPos);
67-
occ += smoothstep(1.0, 0.0, diff / ssaoRadius);
81+
vec3 samplePos = ndcToView(rayNdc.xy, sampleDepth); // view-space sample position
82+
float diff = length(rayPos - samplePos);
83+
occ += smoothstep(1, 0, diff / ssaoRadius);
6884
}
69-
total += 1.0;
85+
total += 1;
7086
}
87+
7188
if (total > 0)
7289
outAo = occ / total;
7390
else

sources/libengine/graphics/renderPipeline.cpp

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ namespace cage
202202
struct RenderPipelineImpl : public RenderPipelineConfig
203203
{
204204
Holder<Model> modelSquare, modelBone, modelIcon;
205-
Holder<ShaderProgram> shaderBlitPixels, shaderBlitScaled;
205+
Holder<ShaderProgram> shaderBlitPixels;
206206
Holder<ShaderProgram> shaderDepth, shaderDepthCutOut;
207207
Holder<ShaderProgram> shaderStandard, shaderStandardCutOut;
208208
Holder<ShaderProgram> shaderIcon, shaderIconCutOut;
@@ -239,8 +239,7 @@ namespace cage
239239
CAGE_ASSERT(modelSquare && modelBone && modelIcon);
240240

241241
shaderBlitPixels = assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/engine/blitPixels.glsl"))->get(0);
242-
shaderBlitScaled = assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/engine/blitScaled.glsl"))->get(0);
243-
CAGE_ASSERT(shaderBlitPixels && shaderBlitScaled);
242+
CAGE_ASSERT(shaderBlitPixels);
244243

245244
Holder<MultiShaderProgram> standard = assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/engine/standard.glsl"));
246245
CAGE_ASSERT(standard);
@@ -255,6 +254,7 @@ namespace cage
255254
shaderIconCutOut = icon->get(HashString("CutOut"));
256255

257256
shaderText = assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/engine/text.glsl"))->get(0);
257+
CAGE_ASSERT(shaderText);
258258

259259
transformComponent = scene->component<TransformComponent>();
260260
prevTransformComponent = scene->componentsByType(detail::typeIndex<TransformComponent>())[1];
@@ -272,7 +272,6 @@ namespace cage
272272
SHARE(modelBone);
273273
SHARE(modelIcon);
274274
SHARE(shaderBlitPixels);
275-
SHARE(shaderBlitScaled);
276275
SHARE(shaderDepth);
277276
SHARE(shaderDepthCutOut);
278277
SHARE(shaderStandard);
@@ -1199,40 +1198,11 @@ namespace cage
11991198

12001199
if (any(effects.effects & ScreenSpaceEffectsFlags::AmbientOcclusion))
12011200
{
1202-
const Vec2i ssaoResolution = resolution / 3;
1203-
1204-
TextureHandle depthTextureLowRes = [&]()
1205-
{
1206-
const auto graphicsDebugScope = renderQueue->namedScope("lowResDepth");
1207-
TextureHandle t = provisionalGraphics->texture(Stringizer() + "depthTextureLowRes_" + name + "_" + resolution,
1208-
[ssaoResolution](Texture *t)
1209-
{
1210-
t->initialize(ssaoResolution, 1, GL_R32F);
1211-
t->filters(GL_NEAREST, GL_NEAREST, 0);
1212-
t->wraps(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
1213-
});
1214-
1215-
FrameBufferHandle renderTarget = provisionalGraphics->frameBufferDraw(Stringizer() + "depthTargetLowRes_" + name);
1216-
renderQueue->bind(renderTarget);
1217-
renderQueue->colorTexture(renderTarget, 0, t);
1218-
renderQueue->depthTexture(renderTarget, {});
1219-
renderQueue->activeAttachments(renderTarget, 1);
1220-
renderQueue->checkFrameBuffer(renderTarget);
1221-
renderQueue->viewport(Vec2i(), ssaoResolution);
1222-
renderQueue->bind(shaderBlitScaled);
1223-
renderQueue->bind(depthTexture, 0);
1224-
renderQueue->draw(modelSquare);
1225-
renderQueue->resetAllState();
1226-
renderQueue->resetFrameBuffer();
1227-
return t;
1228-
}();
1229-
12301201
ScreenSpaceAmbientOcclusionConfig cfg;
12311202
(ScreenSpaceCommonConfig &)cfg = commonConfig;
12321203
(ScreenSpaceAmbientOcclusion &)cfg = effects.ssao;
1233-
cfg.resolution = ssaoResolution;
12341204
cfg.proj = projection;
1235-
cfg.inDepth = depthTextureLowRes;
1205+
cfg.inDepth = depthTexture;
12361206
cfg.frameIndex = frameIndex;
12371207
screenSpaceAmbientOcclusion(cfg);
12381208

sources/libengine/graphics/screenSpaceEffects.cpp

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,14 @@ namespace cage
7272
PointerRange<const char> pointsForSsaoShader();
7373
}
7474

75-
void screenSpaceAmbientOcclusion(const ScreenSpaceAmbientOcclusionConfig &config)
75+
void screenSpaceAmbientOcclusion(const ScreenSpaceAmbientOcclusionConfig &config_)
7676
{
77-
RenderQueue *q = config.queue;
77+
RenderQueue *q = config_.queue;
7878
const auto graphicsDebugScope = q->namedScope("ssao");
79+
ScreenSpaceAmbientOcclusionConfig config = config_;
80+
config.resolution /= 3;
7981

80-
q->viewport(Vec2i(), config.resolution);
81-
FrameBufferHandle fb = config.provisionals->frameBufferDraw("graphicsEffects");
82-
q->bind(fb);
83-
84-
UniformBufferHandle ssaoPoints = config.provisionals->uniformBuffer("ssaoPoints", [](UniformBuffer *ub) { ub->writeWhole(privat::pointsForSsaoShader(), GL_STATIC_DRAW); });
85-
q->bind(ssaoPoints, 3);
86-
82+
// params
8783
struct Shader
8884
{
8985
Mat4 proj;
@@ -98,14 +94,36 @@ namespace cage
9894
s.iparams[1] = hash(config.frameIndex);
9995
q->universalUniformStruct(s, CAGE_SHADER_UNIBLOCK_CUSTOMDATA);
10096

101-
// generate
102-
config.outAo = provTex(config.provisionals, "ssao", config.resolution, 1, GL_R8);
103-
q->colorTexture(fb, 0, config.outAo);
104-
q->checkFrameBuffer(fb);
105-
q->bind(config.inDepth, 0);
106-
q->bind(config.assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/effects/ssaoGenerate.glsl"))->get(0));
97+
// framebuffer
98+
q->viewport(Vec2i(), config.resolution);
99+
FrameBufferHandle fb = config.provisionals->frameBufferDraw("graphicsEffects");
100+
q->bind(fb);
107101
Holder<Model> model = config.assets->get<AssetSchemeIndexModel, Model>(HashString("cage/models/square.obj"));
108-
q->draw(model);
102+
103+
// low res depth
104+
TextureHandle depthTextureLowRes = provTex(config.provisionals, "ssaoDepthLowRes", config.resolution, 1, GL_R32F);
105+
{
106+
const auto graphicsDebugScope = q->namedScope("lowResDepth");
107+
q->colorTexture(fb, 0, depthTextureLowRes);
108+
q->checkFrameBuffer(fb);
109+
q->bind(config.assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/effects/ssaoDownscaleDepth.glsl"))->get(0));
110+
q->bind(config.inDepth, 0);
111+
q->draw(model);
112+
}
113+
114+
// points
115+
UniformBufferHandle ssaoPoints = config.provisionals->uniformBuffer("ssaoPoints", [](UniformBuffer *ub) { ub->writeWhole(privat::pointsForSsaoShader(), GL_STATIC_DRAW); });
116+
q->bind(ssaoPoints, 3);
117+
118+
{ // generate
119+
const auto graphicsDebugScope = q->namedScope("generate");
120+
config.outAo = provTex(config.provisionals, "ssao", config.resolution, 1, GL_R8);
121+
q->colorTexture(fb, 0, config.outAo);
122+
q->checkFrameBuffer(fb);
123+
q->bind(depthTextureLowRes, 0);
124+
q->bind(config.assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/effects/ssaoGenerate.glsl"))->get(0));
125+
q->draw(model);
126+
}
109127

110128
// blur
111129
GfGaussianBlurConfig gb;
@@ -115,10 +133,14 @@ namespace cage
115133
for (uint32 i = 0; i < config.blurPasses; i++)
116134
gfGaussianBlur(gb);
117135

118-
// resolve - update outAo inplace
119-
q->bind(config.outAo, 0);
120-
q->bind(config.assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/effects/ssaoResolve.glsl"))->get(0));
121-
q->draw(model);
136+
{ // resolve - update outAo inplace
137+
const auto graphicsDebugScope = q->namedScope("resolve");
138+
q->bind(config.outAo, 0);
139+
q->bind(config.assets->get<AssetSchemeIndexShaderProgram, MultiShaderProgram>(HashString("cage/shaders/effects/ssaoResolve.glsl"))->get(0));
140+
q->draw(model);
141+
}
142+
143+
config_.outAo = config.outAo;
122144
}
123145

124146
void screenSpaceDepthOfField(const ScreenSpaceDepthOfFieldConfig &config)

0 commit comments

Comments
 (0)