Skip to content

Commit 6f35c17

Browse files
committed
ssao and dof
1 parent e123860 commit 6f35c17

File tree

5 files changed

+249
-30
lines changed

5 files changed

+249
-30
lines changed

data/cage/shaders/effects/dofApply.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ void dofContribution(vec2 uv, float depth, out float near, out float far)
3333
}
3434

3535
layout(set = 2, binding = 1) uniform sampler2D texColor;
36-
layout(set = 2, binding = 2) uniform sampler2D texDepth;
37-
layout(set = 2, binding = 3) uniform sampler2D texDof;
36+
layout(set = 2, binding = 3) uniform sampler2D texDepth;
37+
layout(set = 2, binding = 5) uniform sampler2D texDof;
3838

3939
layout(location = 0) out vec4 outColor;
4040

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,16 @@
11

2-
layout(location = 0) varying vec2 varUv;
3-
4-
5-
$define shader vertex
6-
7-
layout(location = 0) in vec3 inPosition;
8-
layout(location = 4) in vec3 inUv;
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-
2+
$include vertex.glsl
173

184
$define shader fragment
195

206
layout(set = 2, binding = 0) uniform sampler2D texDepth;
217

228
layout(location = 0) out float outDepth;
239

10+
const int downscale = 3;
11+
2412
void main()
2513
{
26-
outDepth = textureLod(texDepth, varUv, 0).x;
14+
vec2 uv = downscale * vec2(gl_FragCoord) / vec2(textureSize(texDepth, 0));
15+
outDepth = textureLod(texDepth, uv, 0).x;
2716
}

data/cage/shaders/effects/ssaoGenerate.glsl

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ layout(std140, set = 2, binding = 1) uniform SsaoPoints
1212
vec4 ssaoPoints[256];
1313
};
1414

15-
layout(set = 2, binding = 2) uniform sampler2D texDepth; // NDC depth [0,1]
15+
layout(set = 2, binding = 2) uniform sampler2D texDepth; // NDC depth [0..1]
1616

1717
layout(location = 0) out float outAo;
1818

19-
// inputs in NDC [-1,1]
19+
// inputs in NDC [p: -1..1, d: 0..1]
2020
vec3 ndcToView(vec2 p, float d)
2121
{
2222
vec4 p4 = vec4(p, d, 1);
@@ -32,7 +32,6 @@ vec3 reconstructNormal(vec3 position)
3232

3333
mat3 makeTbn(vec3 myNormal)
3434
{
35-
//float angle = 2.0 * 3.14159265 * fract(sin(dot(gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453);
3635
uint n = hash(uint(gl_FragCoord.x) ^ hash(uint(gl_FragCoord.y)) ^ uint(iparams[1])); // per-pixel seed
3736
float angle = 2.0 * 3.14159265 * egacIntToFloat(n);
3837
float ca = cos(angle);
@@ -47,8 +46,8 @@ mat3 makeTbn(vec3 myNormal)
4746
void main()
4847
{
4948
vec2 resolution = vec2(textureSize(texDepth, 0));
50-
vec2 myUv = gl_FragCoord.xy / resolution; // screen-space [0,1]
51-
float myDepth = textureLod(texDepth, myUv, 0).x * 2 - 1; // NDC depth [-1,1]
49+
vec2 myUv = gl_FragCoord.xy / resolution; // screen-space [0..1]
50+
float myDepth = textureLod(texDepth, myUv, 0).x; // NDC depth [0..1]
5251
vec3 myPos = ndcToView(myUv * 2 - 1, myDepth); // view-space position
5352
vec3 myNormal = reconstructNormal(myPos); // view-space normal
5453

@@ -73,10 +72,10 @@ void main()
7372
// view-space ray position
7473
vec3 rayPos = myPos + rayDir;
7574
vec4 r4 = proj * vec4(rayPos, 1); // clip space
76-
vec3 rayNdc = r4.xyz / r4.w; // NDC [-1,1]
75+
vec3 rayNdc = r4.xyz / r4.w; // NDC [xy: -1..1, z: 0..1]
7776

7877
vec2 sampleUv = saturate(rayNdc.xy * 0.5 + 0.5);
79-
float sampleDepth = textureLod(texDepth, sampleUv, 0).x * 2 - 1; // NDC depth [-1,1]
78+
float sampleDepth = textureLod(texDepth, sampleUv, 0).x; // NDC depth [0,1]
8079
if (sampleDepth < rayNdc.z)
8180
{
8281
vec3 samplePos = ndcToView(rayNdc.xy, sampleDepth); // view-space sample position

sources/libengine/graphics/sceneRender.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,9 +1091,10 @@ namespace cage
10911091

10921092
Holder<Texture> createSsaoTextureTarget()
10931093
{
1094+
static constexpr int downscale = 3;
10941095
wgpu::TextureDescriptor desc = {};
1095-
desc.size.width = resolution[0];
1096-
desc.size.height = resolution[1];
1096+
desc.size.width = resolution[0] / downscale;
1097+
desc.size.height = resolution[1] / downscale;
10971098
desc.format = wgpu::TextureFormat::R16Float;
10981099
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
10991100
desc.label = "ssao target";
@@ -1168,7 +1169,7 @@ namespace cage
11681169
(ScreenSpaceCommonConfig &)cfg = commonConfig;
11691170
(ScreenSpaceAmbientOcclusion &)cfg = effects.ssao;
11701171
cfg.proj = projection;
1171-
cfg.inDepth = +depthTexture;
1172+
cfg.inDepth = +depthSampling;
11721173
cfg.outAo = +ssaoTexture;
11731174
cfg.frameIndex = frameIndex;
11741175
screenSpaceAmbientOcclusion(cfg);

sources/libengine/graphics/screenSpaceEffects.cpp

Lines changed: 232 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,242 @@ namespace cage
7575

7676
void screenSpaceAmbientOcclusion(const ScreenSpaceAmbientOcclusionConfig &config)
7777
{
78-
// todo
78+
static constexpr int downscale = 3;
79+
80+
GraphicsEncoder *q = config.encoder;
81+
GraphicsDevice *d = q->getDevice();
82+
83+
Holder<Model> model = config.assets->get<Model>(HashString("cage/models/square.obj"));
84+
85+
// prepare
86+
87+
const Vec2i res = max(config.resolution / downscale, 1u);
88+
Holder<Texture> depthLowRes = [&]()
89+
{
90+
wgpu::TextureDescriptor desc = {};
91+
desc.size.width = res[0];
92+
desc.size.height = res[1];
93+
desc.format = wgpu::TextureFormat::R32Float;
94+
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
95+
desc.label = "ssao depth target";
96+
wgpu::Texture tex = d->nativeDevice()->CreateTexture(&desc);
97+
wgpu::Sampler samp = d->nativeDevice()->CreateSampler();
98+
return newTexture(tex, tex.CreateView(), samp, "ssao depth target");
99+
}();
100+
Holder<Texture> ssaoLowRes = [&]()
101+
{
102+
wgpu::TextureDescriptor desc = {};
103+
desc.size.width = res[0];
104+
desc.size.height = res[1];
105+
desc.format = wgpu::TextureFormat::R16Float;
106+
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
107+
desc.label = "ssao lowres target";
108+
wgpu::Texture tex = d->nativeDevice()->CreateTexture(&desc);
109+
wgpu::Sampler samp = d->nativeDevice()->CreateSampler();
110+
return newTexture(tex, tex.CreateView(), samp, "ssao lowres target");
111+
}();
112+
113+
struct Shader
114+
{
115+
Mat4 proj;
116+
Mat4 projInv;
117+
Vec4 params; // strength, bias, power, raysLength
118+
Vec4i iparams; // sampleCount, hashSeed
119+
} s;
120+
s.proj = config.proj;
121+
s.projInv = inverse(config.proj);
122+
s.params = Vec4(config.strength, config.bias, config.power, config.raysLength);
123+
s.iparams[0] = config.samplesCount;
124+
s.iparams[1] = hash(config.frameIndex);
125+
Holder<GpuBuffer> buff = newGpuBufferUniform(config.encoder->getDevice(), "UniSsao");
126+
buff->write(s);
127+
128+
Holder<GpuBuffer> buffPoints = newGpuBufferUniform(config.encoder->getDevice(), "SsaoPoints");
129+
buffPoints->write(privat::pointsForSsaoShader(config.samplesCount));
130+
131+
{ // low-res depth
132+
PassConfig pass;
133+
pass.colorTargets.push_back({ +depthLowRes });
134+
q->nextPass(pass);
135+
const auto scope = config.encoder->namedScope("ssao depth");
136+
137+
BindingsCreateConfig bind;
138+
bind.textures.push_back({ config.inDepth, 0 });
139+
140+
Holder<MultiShader> ms = config.assets->get<MultiShader>(HashString("cage/shaders/effects/ssaoDownscaleDepth.glsl"));
141+
142+
DrawConfig draw;
143+
draw.bindings = newGpuBindings(d, bind);
144+
draw.model = +model;
145+
draw.shader = +ms->get(0);
146+
q->draw(draw);
147+
}
148+
149+
{ // generate
150+
PassConfig pass;
151+
pass.colorTargets.push_back({ +ssaoLowRes });
152+
q->nextPass(pass);
153+
const auto scope = config.encoder->namedScope("ssao generate");
154+
155+
BindingsCreateConfig bind;
156+
bind.buffers.push_back({ +buff, 0 });
157+
bind.buffers.push_back({ +buffPoints, 1 });
158+
bind.textures.push_back({ +depthLowRes, 2 });
159+
160+
Holder<MultiShader> ms = config.assets->get<MultiShader>(HashString("cage/shaders/effects/ssaoGenerate.glsl"));
161+
162+
DrawConfig draw;
163+
draw.bindings = newGpuBindings(d, bind);
164+
draw.model = +model;
165+
draw.shader = +ms->get(0);
166+
q->draw(draw);
167+
}
168+
169+
{ // blur
170+
Holder<Texture> tmp = [&]()
171+
{
172+
wgpu::TextureDescriptor desc = {};
173+
desc.size.width = res[0];
174+
desc.size.height = res[1];
175+
desc.format = wgpu::TextureFormat::R16Float;
176+
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
177+
desc.label = "ssao blur temporary";
178+
wgpu::Texture tex = d->nativeDevice()->CreateTexture(&desc);
179+
return newTexture(tex, tex.CreateView(), d->nativeDevice()->CreateSampler(), "ssao blur temporary");
180+
}();
181+
182+
GaussianBlurConfig gb;
183+
(ScreenSpaceCommonConfig &)gb = config;
184+
gb.inTex = +ssaoLowRes;
185+
gb.tmpTex = +tmp;
186+
for (uint32 i = 0; i < config.blurPasses; i++)
187+
gaussianBlur(gb);
188+
}
189+
190+
{ // resolve
191+
PassConfig pass;
192+
pass.colorTargets.push_back({ +config.outAo });
193+
q->nextPass(pass);
194+
const auto scope = config.encoder->namedScope("ssao resolve");
195+
196+
BindingsCreateConfig bind;
197+
bind.buffers.push_back({ +buff, 0 });
198+
bind.textures.push_back({ +ssaoLowRes, 1 });
199+
200+
Holder<MultiShader> ms = config.assets->get<MultiShader>(HashString("cage/shaders/effects/ssaoResolve.glsl"));
201+
202+
DrawConfig draw;
203+
draw.bindings = newGpuBindings(d, bind);
204+
draw.model = +model;
205+
draw.shader = +ms->get(0);
206+
q->draw(draw);
207+
}
79208
}
80209

81210
void screenSpaceDepthOfField(const ScreenSpaceDepthOfFieldConfig &config)
82211
{
83-
// todo
212+
static constexpr int downscale = 3;
213+
214+
GraphicsEncoder *q = config.encoder;
215+
GraphicsDevice *d = q->getDevice();
216+
217+
Holder<Model> model = config.assets->get<Model>(HashString("cage/models/square.obj"));
218+
219+
// prepare
220+
221+
const Vec2i res = max(config.resolution / downscale, 1u);
222+
Holder<Texture> texDof = [&]()
223+
{
224+
wgpu::TextureDescriptor desc = {};
225+
desc.size.width = res[0];
226+
desc.size.height = res[1];
227+
desc.format = wgpu::TextureFormat::RGBA16Float;
228+
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
229+
desc.label = "dof color target";
230+
wgpu::Texture tex = d->nativeDevice()->CreateTexture(&desc);
231+
wgpu::SamplerDescriptor sd = {};
232+
sd.addressModeU = sd.addressModeV = sd.addressModeW = wgpu::AddressMode::ClampToEdge;
233+
sd.magFilter = sd.minFilter = wgpu::FilterMode::Linear;
234+
sd.mipmapFilter = wgpu::MipmapFilterMode::Nearest;
235+
sd.label = "dof color sampler";
236+
wgpu::Sampler samp = d->nativeDevice()->CreateSampler(&sd);
237+
return newTexture(tex, tex.CreateView(), samp, "dof color target");
238+
}();
239+
240+
struct Shader
241+
{
242+
Mat4 projInv;
243+
Vec4 dofNear; // near, far
244+
Vec4 dofFar; // near, far
245+
} s;
246+
const Real fd = config.focusDistance;
247+
const Real fr = config.focusRadius;
248+
const Real br = config.blendRadius;
249+
s.projInv = inverse(config.proj);
250+
s.dofNear = Vec4(fd - fr - br, fd - fr, 0, 0);
251+
s.dofFar = Vec4(fd + fr, fd + fr + br, 0, 0);
252+
Holder<GpuBuffer> buff = newGpuBufferUniform(config.encoder->getDevice(), "UniDof");
253+
buff->write(s);
254+
255+
{ // collect
256+
PassConfig pass;
257+
pass.colorTargets.push_back({ +texDof });
258+
q->nextPass(pass);
259+
const auto scope = config.encoder->namedScope("dof collect");
260+
261+
BindingsCreateConfig bind;
262+
bind.textures.push_back({ config.inColor, 0 });
263+
264+
Holder<MultiShader> ms = config.assets->get<MultiShader>(HashString("cage/shaders/effects/dofCollect.glsl"));
265+
266+
DrawConfig draw;
267+
draw.bindings = newGpuBindings(d, bind);
268+
draw.model = +model;
269+
draw.shader = +ms->get(0);
270+
q->draw(draw);
271+
}
272+
273+
{ // blur
274+
Holder<Texture> tmp = [&]()
275+
{
276+
wgpu::TextureDescriptor desc = {};
277+
desc.size.width = res[0];
278+
desc.size.height = res[1];
279+
desc.format = wgpu::TextureFormat::RGBA16Float;
280+
desc.usage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding;
281+
desc.label = "dof blur temporary";
282+
wgpu::Texture tex = d->nativeDevice()->CreateTexture(&desc);
283+
return newTexture(tex, tex.CreateView(), d->nativeDevice()->CreateSampler(), "dof blur temporary");
284+
}();
285+
286+
GaussianBlurConfig gb;
287+
(ScreenSpaceCommonConfig &)gb = config;
288+
gb.inTex = +texDof;
289+
gb.tmpTex = +tmp;
290+
for (uint32 i = 0; i < config.blurPasses; i++)
291+
gaussianBlur(gb);
292+
}
293+
294+
{ // apply
295+
PassConfig pass;
296+
pass.colorTargets.push_back({ +config.outColor });
297+
q->nextPass(pass);
298+
const auto scope = config.encoder->namedScope("dof apply");
299+
300+
BindingsCreateConfig bind;
301+
bind.buffers.push_back({ +buff, 0 });
302+
bind.textures.push_back({ config.inColor, 1 });
303+
bind.textures.push_back({ config.inDepth, 3 });
304+
bind.textures.push_back({ +texDof, 5 });
305+
306+
Holder<MultiShader> ms = config.assets->get<MultiShader>(HashString("cage/shaders/effects/dofApply.glsl"));
307+
308+
DrawConfig draw;
309+
draw.bindings = newGpuBindings(d, bind);
310+
draw.model = +model;
311+
draw.shader = +ms->get(0);
312+
q->draw(draw);
313+
}
84314
}
85315

86316
void screenSpaceBloom(const ScreenSpaceBloomConfig &config)

0 commit comments

Comments
 (0)