载入中...
搜索中...
未找到
AmbientOcclusion.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4#include "graphics/Canvas.h"
6#include "graphics/Graphics.h"
7#include "graphics/Shader.h"
8#include "graphics/Texture.h"
9#include "graphics/shaders/ao_ssao_frag_spv.inc"
10#include "graphics/shaders/ao_hbao_frag_spv.inc"
11#include "graphics/shaders/ao_gtao_frag_spv.inc"
12#include "graphics/shaders/ao_blur_frag_spv.inc"
13#include "graphics/shaders/ao_overlay_frag_spv.inc"
14#include "graphics/shaders/ao_from_depth_frag_spv.inc"
15
16#include <algorithm>
17#include <cmath>
18#include <cstdint>
19#include <vector>
20
21#include <glm/gtc/matrix_transform.hpp>
22
23namespace eve::graphics {
24namespace {
25
26void declareComputeCommon(Shader *sh, bool horizonStyle) {
27 sh->declareMatrix("invViewProj");
28 sh->declareFloat("nearZ");
29 sh->declareFloat("farZ");
30 sh->declareFloat("radius");
31 sh->declareFloat("bias");
32 sh->declareFloat("intensity");
33 sh->declareFloat("power");
34 if (horizonStyle) {
35 sh->declareFloat("dirCount");
36 sh->declareFloat("stepCount");
37 } else {
38 sh->declareFloat("sampleCount");
39 }
40 sh->declareFloat("texelW");
41 sh->declareFloat("texelH");
42}
43
44Shader *createSsaoShader(Graphics *gfx) {
45 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
46 std::vector<uint32_t> frag(ao_ssao_frag_spv, ao_ssao_frag_spv + ao_ssao_frag_spv_count);
47 std::vector<uint32_t> vert;
48 Shader *sh = gfx->newShaderFromSpv(vert, frag);
49 declareComputeCommon(sh, false);
50 sh->sendMatrix("invViewProj", glm::mat4(1.f));
51 sh->sendFloat("nearZ", 0.1f);
52 sh->sendFloat("farZ", 100.f);
53 sh->sendFloat("radius", 0.75f);
54 sh->sendFloat("bias", 0.025f);
55 sh->sendFloat("intensity", 1.f);
56 sh->sendFloat("power", 1.5f);
57 sh->sendFloat("sampleCount", 16.f);
58 sh->sendFloat("texelW", 1.f / 256.f);
59 sh->sendFloat("texelH", 1.f / 256.f);
60 return sh;
61}
62
63Shader *createHbaoShader(Graphics *gfx) {
64 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
65 std::vector<uint32_t> frag(ao_hbao_frag_spv, ao_hbao_frag_spv + ao_hbao_frag_spv_count);
66 std::vector<uint32_t> vert;
67 Shader *sh = gfx->newShaderFromSpv(vert, frag);
68 declareComputeCommon(sh, true);
69 sh->sendMatrix("invViewProj", glm::mat4(1.f));
70 sh->sendFloat("nearZ", 0.1f);
71 sh->sendFloat("farZ", 100.f);
72 sh->sendFloat("radius", 0.75f);
73 sh->sendFloat("bias", 0.025f);
74 sh->sendFloat("intensity", 1.f);
75 sh->sendFloat("power", 1.5f);
76 sh->sendFloat("dirCount", 6.f);
77 sh->sendFloat("stepCount", 6.f);
78 sh->sendFloat("texelW", 1.f / 256.f);
79 sh->sendFloat("texelH", 1.f / 256.f);
80 return sh;
81}
82
83Shader *createGtaoShader(Graphics *gfx) {
84 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
85 std::vector<uint32_t> frag(ao_gtao_frag_spv, ao_gtao_frag_spv + ao_gtao_frag_spv_count);
86 std::vector<uint32_t> vert;
87 Shader *sh = gfx->newShaderFromSpv(vert, frag);
88 declareComputeCommon(sh, true);
89 sh->declareFloat("thickness");
90 sh->sendMatrix("invViewProj", glm::mat4(1.f));
91 sh->sendFloat("nearZ", 0.1f);
92 sh->sendFloat("farZ", 100.f);
93 sh->sendFloat("radius", 0.75f);
94 sh->sendFloat("bias", 0.025f);
95 sh->sendFloat("intensity", 1.f);
96 sh->sendFloat("power", 1.5f);
97 sh->sendFloat("dirCount", 6.f);
98 sh->sendFloat("stepCount", 6.f);
99 sh->sendFloat("texelW", 1.f / 256.f);
100 sh->sendFloat("texelH", 1.f / 256.f);
101 sh->sendFloat("thickness", 0.5f);
102 return sh;
103}
104
105Shader *createBlurShader(Graphics *gfx) {
106 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
107 std::vector<uint32_t> frag(ao_blur_frag_spv, ao_blur_frag_spv + ao_blur_frag_spv_count);
108 std::vector<uint32_t> vert;
109 Shader *sh = gfx->newShaderFromSpv(vert, frag);
110 sh->declareFloat("texelW");
111 sh->declareFloat("texelH");
112 sh->declareFloat("depthSigma");
113 sh->declareFloat("spatialKernel");
114 sh->sendFloat("texelW", 1.f / 256.f);
115 sh->sendFloat("texelH", 1.f / 256.f);
116 sh->sendFloat("depthSigma", 0.05f);
117 sh->sendFloat("spatialKernel", 2.f);
118 return sh;
119}
120
121Shader *createOverlayShader(Graphics *gfx) {
122 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
123 std::vector<uint32_t> frag(ao_overlay_frag_spv, ao_overlay_frag_spv + ao_overlay_frag_spv_count);
124 std::vector<uint32_t> vert;
125 Shader *sh = gfx->newShaderFromSpv(vert, frag);
126 sh->declareFloat("intensity");
127 sh->declareFloat("power");
128 sh->sendFloat("intensity", 1.f);
129 sh->sendFloat("power", 1.f);
130 return sh;
131}
132
133Shader *createFromDepthShader(Graphics *gfx) {
134 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
135 std::vector<uint32_t> frag(ao_from_depth_frag_spv,
136 ao_from_depth_frag_spv + ao_from_depth_frag_spv_count);
137 Shader *sh = gfx->newShaderFromSpv({}, frag);
138 if (!sh || !sh->gpuHandle)
139 throw eve::Exception("AmbientOcclusion: failed to create from-depth shader");
140 declareComputeCommon(sh, false);
141 sh->sendMatrix("invViewProj", glm::mat4(1.f));
142 sh->sendFloat("nearZ", 0.1f);
143 sh->sendFloat("farZ", 100.f);
144 sh->sendFloat("radius", 0.75f);
145 sh->sendFloat("bias", 0.025f);
146 sh->sendFloat("intensity", 0.55f);
147 sh->sendFloat("power", 1.35f);
148 sh->sendFloat("sampleCount", 16.f);
149 sh->sendFloat("texelW", 1.f / 256.f);
150 sh->sendFloat("texelH", 1.f / 256.f);
151 sh->declareFloat("hasNormal");
152 sh->sendFloat("hasNormal", 0.f);
153 return sh;
154}
155
156} // namespace
157
159 ssaoShader_ = createSsaoShader(gfx);
160 hbaoShader_ = createHbaoShader(gfx);
161 gtaoShader_ = createGtaoShader(gfx);
162 blurShader_ = createBlurShader(gfx);
163 overlayShader_ = createOverlayShader(gfx);
164 fromDepthShader_ = createFromDepthShader(gfx);
165 applyQualityDefaults();
166}
167
169
170Shader *AmbientOcclusion::activeComputeShader() const {
171 if (mode_ == "hbao") return hbaoShader_;
172 if (mode_ == "gtao") return gtaoShader_;
173 return ssaoShader_;
174}
175
176Shader *AmbientOcclusion::getShader() const { return activeComputeShader(); }
177
178void AmbientOcclusion::applyQualityDefaults() {
179 if (quality_ == "low") {
180 downscale_ = 4.f;
181 radius_ = 0.55f;
182 if (mode_ == "hbao" || mode_ == "gtao") {
183 setFloat("dirCount", 4.f);
184 setFloat("stepCount", 4.f);
185 } else {
186 setFloat("sampleCount", 8.f);
187 }
188 } else if (quality_ == "high") {
189 downscale_ = 1.f;
190 radius_ = 1.f;
191 if (mode_ == "hbao" || mode_ == "gtao") {
192 setFloat("dirCount", 8.f);
193 setFloat("stepCount", 8.f);
194 } else {
195 setFloat("sampleCount", 24.f);
196 }
197 } else {
198 quality_ = "medium";
199 downscale_ = 2.f;
200 radius_ = 0.75f;
201 if (mode_ == "hbao" || mode_ == "gtao") {
202 setFloat("dirCount", 6.f);
203 setFloat("stepCount", 6.f);
204 } else {
205 setFloat("sampleCount", 16.f);
206 }
207 }
208 setRadius(radius_);
209 setBias(bias_);
210 setIntensity(intensity_);
211 setPower(power_);
212 setThickness(thickness_);
213}
214
215void AmbientOcclusion::setQuality(const std::string &quality) {
216 quality_ = quality;
217 applyQualityDefaults();
218}
219
220void AmbientOcclusion::setMode(const std::string &mode) {
221 if (mode == "hbao")
222 mode_ = "hbao";
223 else if (mode == "gtao")
224 mode_ = "gtao";
225 else
226 mode_ = "ssao";
227 applyQualityDefaults();
228}
229
230void AmbientOcclusion::setInvViewProj(const glm::mat4 &invViewProj) {
231 invViewProj_ = invViewProj;
232 ssaoShader_->sendMatrix("invViewProj", invViewProj_);
233 hbaoShader_->sendMatrix("invViewProj", invViewProj_);
234 gtaoShader_->sendMatrix("invViewProj", invViewProj_);
235 if (fromDepthShader_) fromDepthShader_->sendMatrix("invViewProj", invViewProj_);
236}
237
238void AmbientOcclusion::setCamera(float eyeX, float eyeY, float eyeZ, float targetX, float targetY,
239 float targetZ, float upX, float upY, float upZ, float fovYDeg,
240 float aspect, float nearZ, float farZ) {
241 nearZ_ = nearZ > 1e-4f ? nearZ : 0.1f;
242 farZ_ = farZ > nearZ_ ? farZ : nearZ_ + 1.f;
243 const float aspectSafe = aspect > 1e-4f ? aspect : 1.f;
244 const float fovRad = fovYDeg * 0.017453292519943295f;
245 const glm::mat4 view =
246 glm::lookAtRH(glm::vec3(eyeX, eyeY, eyeZ), glm::vec3(targetX, targetY, targetZ),
247 glm::vec3(upX, upY, upZ));
248 const glm::mat4 proj = perspectiveVulkanRH_ZO(fovRad, aspectSafe, nearZ_, farZ_);
249 setInvViewProj(glm::inverse(proj * view));
250 ssaoShader_->sendFloat("nearZ", nearZ_);
251 ssaoShader_->sendFloat("farZ", farZ_);
252 hbaoShader_->sendFloat("nearZ", nearZ_);
253 hbaoShader_->sendFloat("farZ", farZ_);
254 gtaoShader_->sendFloat("nearZ", nearZ_);
255 gtaoShader_->sendFloat("farZ", farZ_);
256 if (fromDepthShader_) {
257 fromDepthShader_->sendFloat("nearZ", nearZ_);
258 fromDepthShader_->sendFloat("farZ", farZ_);
259 }
260}
261
262void AmbientOcclusion::setRadius(float radius) {
263 radius_ = radius > 1e-4f ? radius : 1e-4f;
264 setFloat("radius", radius_);
265}
266
268 bias_ = bias < 0.f ? 0.f : bias;
269 setFloat("bias", bias_);
270}
271
272void AmbientOcclusion::setIntensity(float intensity) {
273 intensity_ = intensity < 0.f ? 0.f : intensity;
274 setFloat("intensity", intensity_);
275 if (overlayShader_) overlayShader_->sendFloat("intensity", intensity_);
276}
277
279 power_ = power < 0.01f ? 0.01f : power;
280 setFloat("power", power_);
281}
282
284 thickness_ = thickness < 0.f ? 0.f : thickness;
285 if (gtaoShader_ && gtaoShader_->hasUniform("thickness"))
286 gtaoShader_->sendFloat("thickness", thickness_);
287}
288
289float AmbientOcclusion::getRadius() const { return radius_; }
290float AmbientOcclusion::getBias() const { return bias_; }
291float AmbientOcclusion::getIntensity() const { return intensity_; }
292float AmbientOcclusion::getPower() const { return power_; }
293
294bool AmbientOcclusion::hasParam(const std::string &name) const {
295 return (ssaoShader_ && ssaoShader_->hasUniform(name)) ||
296 (hbaoShader_ && hbaoShader_->hasUniform(name)) ||
297 (gtaoShader_ && gtaoShader_->hasUniform(name)) ||
298 (blurShader_ && blurShader_->hasUniform(name)) ||
299 (overlayShader_ && overlayShader_->hasUniform(name));
300}
301
302void AmbientOcclusion::setFloat(const std::string &name, float value) {
303 if (ssaoShader_ && ssaoShader_->hasUniform(name)) ssaoShader_->sendFloat(name, value);
304 if (hbaoShader_ && hbaoShader_->hasUniform(name)) hbaoShader_->sendFloat(name, value);
305 if (gtaoShader_ && gtaoShader_->hasUniform(name)) gtaoShader_->sendFloat(name, value);
306 if (blurShader_ && blurShader_->hasUniform(name)) blurShader_->sendFloat(name, value);
307 if (overlayShader_ && overlayShader_->hasUniform(name)) overlayShader_->sendFloat(name, value);
308 if (fromDepthShader_ && fromDepthShader_->hasUniform(name)) fromDepthShader_->sendFloat(name, value);
309}
310
311float AmbientOcclusion::getFloat(const std::string &name) const {
312 Shader *active = activeComputeShader();
313 if (active && active->hasUniform(name)) {
314 float v = 0.f;
315 if (active->getFromVar(name, &v, sizeof(v)) == int(sizeof(v))) return v;
316 }
317 if (blurShader_ && blurShader_->hasUniform(name)) {
318 float v = 0.f;
319 if (blurShader_->getFromVar(name, &v, sizeof(v)) == int(sizeof(v))) return v;
320 }
321 if (overlayShader_ && overlayShader_->hasUniform(name)) {
322 float v = 0.f;
323 if (overlayShader_->getFromVar(name, &v, sizeof(v)) == int(sizeof(v))) return v;
324 }
325 // Fall back across compute shaders.
326 for (Shader *sh : {ssaoShader_, hbaoShader_, gtaoShader_}) {
327 if (sh && sh->hasUniform(name)) {
328 float v = 0.f;
329 if (sh->getFromVar(name, &v, sizeof(v)) == int(sizeof(v))) return v;
330 }
331 }
332 throw eve::Exception("AmbientOcclusion.getFloat: missing param '%s'", name.c_str());
333}
334
336 if (mode_ == "hbao" || mode_ == "gtao") {
337 const int dirs = int(std::lround(getFloat("dirCount")));
338 const int steps = int(std::lround(getFloat("stepCount")));
339 return dirs * steps;
340 }
341 return int(std::lround(getFloat("sampleCount")));
342}
343
344int AmbientOcclusion::resolutionFor(int fullSize) const {
345 if (fullSize < 1) return 1;
346 const float ds = std::max(downscale_, 1.f);
347 return std::max(1, int(std::floor(float(fullSize) / ds)));
348}
349
350void AmbientOcclusion::uploadComputeCommon(Shader *shader, int width, int height) {
351 if (!shader) throw eve::Exception("AmbientOcclusion: null compute shader");
352 if (width < 1) width = 1;
353 if (height < 1) height = 1;
354 shader->sendMatrix("invViewProj", invViewProj_);
355 shader->sendFloat("nearZ", nearZ_);
356 shader->sendFloat("farZ", farZ_);
357 shader->sendFloat("radius", radius_);
358 shader->sendFloat("bias", bias_);
359 shader->sendFloat("intensity", intensity_);
360 shader->sendFloat("power", power_);
361 shader->sendFloat("texelW", 1.f / float(width));
362 shader->sendFloat("texelH", 1.f / float(height));
363 if (shader->hasUniform("thickness")) shader->sendFloat("thickness", thickness_);
364}
365
366void AmbientOcclusion::drawFullscreen(Graphics *gfx, Texture *source, Shader *shader) {
367 if (!gfx) throw eve::Exception("AmbientOcclusion: null graphics");
368 if (!source) throw eve::Exception("AmbientOcclusion: null source texture");
369 if (!shader) throw eve::Exception("AmbientOcclusion: null shader");
370 const float dw = gfx->getCanvas() ? float(gfx->getCanvas()->getWidth()) : float(gfx->getWidth());
371 const float dh =
372 gfx->getCanvas() ? float(gfx->getCanvas()->getHeight()) : float(gfx->getHeight());
373 gfx->drawTexturedRectShader(source, shader, 0.f, 0.f, dw, dh, Color(1.f, 1.f, 1.f, 1.f));
374}
375
377 if (!linearDepth) throw eve::Exception("AmbientOcclusion.compute: null depth");
378 Shader *sh = activeComputeShader();
379 uploadComputeCommon(sh, linearDepth->getWidth(), linearDepth->getHeight());
380 drawFullscreen(gfx, linearDepth, sh);
381}
382
383void AmbientOcclusion::computeTo(Graphics *gfx, Texture *linearDepth, Canvas *dest) {
384 if (!gfx) throw eve::Exception("AmbientOcclusion.computeTo: null graphics");
385 if (!dest) throw eve::Exception("AmbientOcclusion.computeTo: null dest");
386 Canvas *prev = gfx->getCanvas();
387 gfx->setCanvas(dest);
388 compute(gfx, linearDepth);
389 gfx->setCanvas(prev == gfx ? nullptr : prev);
390}
391
393 if (!aoMap) throw eve::Exception("AmbientOcclusion.blur: null aoMap");
394 blurShader_->sendFloat("texelW", 1.f / float(std::max(aoMap->getWidth(), 1)));
395 blurShader_->sendFloat("texelH", 1.f / float(std::max(aoMap->getHeight(), 1)));
396 drawFullscreen(gfx, aoMap, blurShader_);
397}
398
400 if (!gfx) throw eve::Exception("AmbientOcclusion.blurTo: null graphics");
401 if (!dest) throw eve::Exception("AmbientOcclusion.blurTo: null dest");
402 Canvas *prev = gfx->getCanvas();
403 gfx->setCanvas(dest);
404 blur(gfx, aoMap);
405 gfx->setCanvas(prev == gfx ? nullptr : prev);
406}
407
409 if (!aoMap) throw eve::Exception("AmbientOcclusion.applyOverlay: null aoMap");
410 overlayShader_->sendFloat("intensity", intensity_);
411 // Overlay uses power=1 by default so compute-pass power is not double-applied.
412 if (!overlayShader_->hasUniform("power")) {
413 // unreachable — declared at create
414 }
415 overlayShader_->sendFloat("power", 1.f);
416 drawFullscreen(gfx, aoMap, overlayShader_);
417}
418
420 if (!gfx) throw eve::Exception("AmbientOcclusion.applyOverlayTo: null graphics");
421 if (!dest) throw eve::Exception("AmbientOcclusion.applyOverlayTo: null dest");
422 Canvas *prev = gfx->getCanvas();
423 gfx->setCanvas(dest);
424 applyOverlay(gfx, aoMap);
425 gfx->setCanvas(prev == gfx ? nullptr : prev);
426}
427
429 applyFromGBuffer(gfx, hwDepth, nullptr);
430}
431
432void AmbientOcclusion::applyFromGBuffer(Graphics *gfx, Texture *hwDepth, Texture *worldNormal) {
433 if (!gfx) throw eve::Exception("AmbientOcclusion.applyFromGBuffer: null graphics");
434 if (!hwDepth) throw eve::Exception("AmbientOcclusion.applyFromGBuffer: null hwDepth");
435 if (!fromDepthShader_) throw eve::Exception("AmbientOcclusion.applyFromGBuffer: missing shader");
436 fromDepthShader_->sendFloat("hasNormal", worldNormal ? 1.f : 0.f);
437 uploadComputeCommon(fromDepthShader_, hwDepth->getWidth(), hwDepth->getHeight());
438 if (worldNormal) {
439 const float dw =
440 gfx->getCanvas() ? float(gfx->getCanvas()->getWidth()) : float(gfx->getWidth());
441 const float dh =
442 gfx->getCanvas() ? float(gfx->getCanvas()->getHeight()) : float(gfx->getHeight());
443 gfx->drawTexturedRectShaderDepth(hwDepth, worldNormal, fromDepthShader_, 0.f, 0.f, dw, dh,
444 Color(1.f, 1.f, 1.f, 1.f));
445 } else {
446 drawFullscreen(gfx, hwDepth, fromDepthShader_);
447 }
448}
449
451 if (!gfx) throw eve::Exception("AmbientOcclusion.applyFromDepthTo: null graphics");
452 if (!dest) throw eve::Exception("AmbientOcclusion.applyFromDepthTo: null dest");
453 Canvas *prev = gfx->getCanvas();
454 gfx->setCanvas(dest);
455 applyFromDepth(gfx, linearDepth);
456 gfx->setCanvas(prev == gfx ? nullptr : prev);
457}
458
460 float (*depth01)(int x, int y, void *userdata),
461 void *userdata) {
462 if (!gfx) throw eve::Exception("AmbientOcclusion.newLinearDepthTexture: null graphics");
463 if (width < 1 || height < 1)
464 throw eve::Exception("AmbientOcclusion.newLinearDepthTexture: invalid size");
465 if (!depth01) throw eve::Exception("AmbientOcclusion.newLinearDepthTexture: null depth fn");
466 std::vector<uint8_t> rgba(size_t(width) * size_t(height) * 4);
467 for (int y = 0; y < height; ++y) {
468 for (int x = 0; x < width; ++x) {
469 float d = depth01(x, y, userdata);
470 if (d < 0.f) d = 0.f;
471 if (d > 1.f) d = 1.f;
472 const uint8_t b = uint8_t(std::lround(d * 255.f));
473 const size_t i = size_t(y * width + x) * 4;
474 rgba[i + 0] = b;
475 rgba[i + 1] = b;
476 rgba[i + 2] = b;
477 rgba[i + 3] = 255;
478 }
479 }
480 return gfx->newTexture(width, height, rgba.data());
481}
482
483} // namespace eve::graphics
bool active
Definition CardTypes.cpp:34
std::string value
vk::ShaderModule vert
vk::ShaderModule frag
int y
Definition Grass.cpp:135
float height
Definition Grass.cpp:235
int x
Definition Grass.cpp:135
float thickness
uint32_t b
int width
float fovRad
Shader * shader
glm::mat4 view
glm::mat4 proj
const char * name
Definition RockMesh.cpp:21
float power
Definition RockMesh.cpp:23
int d
int v
void applyFromDepthTo(Graphics *gfx, Texture *linearDepth, Canvas *dest)
void applyFromDepth(Graphics *gfx, Texture *hwDepth)
One-pass SSAO overlay for the 3D swapchain path. Samples hardware D32 (Vulkan NDC z in ....
int resolutionFor(int fullSize) const
Downscale helper: returns floor(dim / downscale), at least 1. Callers create AO canvases at this size...
void setFloat(const std::string &name, float value)
void computeTo(Graphics *gfx, Texture *linearDepth, Canvas *dest)
void setCamera(float eyeX, float eyeY, float eyeZ, float targetX, float targetY, float targetZ, float upX, float upY, float upZ, float fovYDeg, float aspect, float nearZ, float farZ)
Camera for depth reconstruction (RH + ZO). Builds inv(viewProj) and near/far used by compute*.
void setMode(const std::string &mode)
"ssao" | "hbao" | "gtao".
void blurTo(Graphics *gfx, Texture *aoMap, Canvas *dest)
void setInvViewProj(const glm::mat4 &invViewProj)
bool hasParam(const std::string &name) const
void applyFromGBuffer(Graphics *gfx, Texture *hwDepth, Texture *worldNormal)
Texture * newLinearDepthTexture(Graphics *gfx, int width, int height, float(*depth01)(int x, int y, void *userdata), void *userdata)
Build an RGBA8 texture with linear depth in R (G=B=R, A=255). Owned by Graphics (same convention as V...
float getFloat(const std::string &name) const
void setQuality(const std::string &quality)
"low" | "medium" | "high" (unknown → medium).
void compute(Graphics *gfx, Texture *linearDepth)
Compute AO into the currently bound canvas / screen. Output RGB = AO (1=open), A = depth01.
void blur(Graphics *gfx, Texture *aoMap)
Bilateral blur of an AO map (RGB=AO, A=depth).
void applyOverlayTo(Graphics *gfx, Texture *aoMap, Canvas *dest)
void applyOverlay(Graphics *gfx, Texture *aoMap)
Darken the current target with AO: black + alpha=(1-ao)*intensity. Draw over an already-rendered scen...
virtual int getWidth() const =0
virtual int getHeight() const =0
virtual Canvas * getCanvas() const =0
virtual Texture * newTexture(int width, int height, const uint8_t *rgba, bool repeatU=false, bool repeatV=false)=0
virtual void setCanvas(Canvas *canvas)=0
nullptr or this → screen. Switching flushes pending draws to the previous target.
int getHeight() const
Definition Graphics.h:118
virtual void drawTexturedRectShaderDepth(Texture *color, Texture *depth, Shader *shader, float x, float y, float w, float h, const Color &tint)=0
Fullscreen/post draw sampling color at binding 0 and depth at binding 1 (hardware D32,...
Custom GPU program.
Definition Shader.h:30
bool hasUniform(const std::string &name) const
Definition Shader.cpp:46
void sendFloat(const std::string &name, float x)
Definition Shader.cpp:82
void sendMatrix(const std::string &name, const glm::mat4 &m)
Definition Shader.cpp:99
int getFromVar(const std::string &name, void *data, size_t size) const
Definition Shader.cpp:71
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:17
int getWidth() const
Definition Texture.h:26
int getHeight() const
Definition Texture.h:27
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition AnimTrail.h:6
glm::mat4 perspectiveVulkanRH_ZO(float fovyRad, float aspect, float zNear, float zFar)
Right-handed, zero-to-one depth perspective for Vulkan swapchains.
Definition ClipSpace.h:20
glm::vec4 Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13