载入中...
搜索中...
未找到
AntiAliasing.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4#include "graphics/Canvas.h"
5#include "graphics/Exposure.h"
6#include "graphics/Graphics.h"
7#include "graphics/Shader.h"
8#include "graphics/Texture.h"
9#include "graphics/shaders/aa_fxaa_frag_spv.inc"
10#include "graphics/shaders/aa_nfaa_frag_spv.inc"
11#include "graphics/shaders/aa_smaa_frag_spv.inc"
12#include "graphics/shaders/aa_ssaa_frag_spv.inc"
13#include "graphics/shaders/aa_taa_frag_spv.inc"
15
16#include <algorithm>
17#include <cmath>
18#include <cstdint>
19#include <vector>
20
21#include <glm/vec4.hpp>
22#include <glm/geometric.hpp>
23#include <glm/gtc/matrix_inverse.hpp>
24#include <glm/gtc/type_ptr.hpp>
25
26namespace eve::graphics {
27namespace {
28
29std::vector<uint32_t> copySpv(const uint32_t *data, size_t count) {
30 return std::vector<uint32_t>(data, data + count);
31}
32
33Shader *newPostShader(Graphics *gfx, const std::vector<uint32_t> &frag, const char *wgsl) {
34 if (gfx->getBackendName() == "webgpu")
35 return gfx->newShaderFromWgsl({}, std::string(shaders::kPostCommon) + wgsl);
36 return gfx->newShaderFromSpv({}, frag);
37}
38
39Shader *createFxaaShader(Graphics *gfx) {
40 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
41 auto frag = copySpv(aa_fxaa_frag_spv, aa_fxaa_frag_spv_count);
42 Shader *sh = newPostShader(gfx, frag, shaders::kFxaa);
43 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create FXAA shader");
44 sh->declareFloat("texelW");
45 sh->declareFloat("texelH");
46 sh->declareFloat("edgeThreshold");
47 sh->declareFloat("edgeThresholdMin");
48 sh->declareFloat("subpix");
49 sh->declareFloat("quality");
50 sh->sendFloat("texelW", 1.f / 256.f);
51 sh->sendFloat("texelH", 1.f / 256.f);
52 sh->sendFloat("edgeThreshold", 0.166f);
53 sh->sendFloat("edgeThresholdMin", 0.0833f);
54 sh->sendFloat("subpix", 0.75f);
55 sh->sendFloat("quality", 1.f);
56 return sh;
57}
58
59Shader *createSmaaShader(Graphics *gfx) {
60 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
61 auto frag = copySpv(aa_smaa_frag_spv, aa_smaa_frag_spv_count);
62 Shader *sh = newPostShader(gfx, frag, shaders::kSmaa);
63 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create SMAA shader");
64 sh->declareFloat("texelW");
65 sh->declareFloat("texelH");
66 sh->declareFloat("threshold");
67 sh->declareFloat("localContrast");
68 sh->declareFloat("maxSearch");
69 sh->declareFloat("cornerRounding");
70 sh->sendFloat("texelW", 1.f / 256.f);
71 sh->sendFloat("texelH", 1.f / 256.f);
72 sh->sendFloat("threshold", 0.1f);
73 sh->sendFloat("localContrast", 0.5f);
74 sh->sendFloat("maxSearch", 8.f);
75 sh->sendFloat("cornerRounding", 0.25f);
76 return sh;
77}
78
79Shader *createSsaaShader(Graphics *gfx) {
80 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
81 auto frag = copySpv(aa_ssaa_frag_spv, aa_ssaa_frag_spv_count);
82 Shader *sh = newPostShader(gfx, frag, shaders::kSsaa);
83 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create SSAA shader");
84 sh->declareFloat("texelW");
85 sh->declareFloat("texelH");
86 sh->declareFloat("scale");
87 sh->declareFloat("kernel");
88 sh->declareFloat("sampleRadius");
89 sh->sendFloat("texelW", 1.f / 512.f);
90 sh->sendFloat("texelH", 1.f / 512.f);
91 sh->sendFloat("scale", 2.f);
92 sh->sendFloat("kernel", 1.f); // tent
93 sh->sendFloat("sampleRadius", 1.f);
94 return sh;
95}
96
97Shader *createNfaaShader(Graphics *gfx) {
98 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
99 auto frag = copySpv(aa_nfaa_frag_spv, aa_nfaa_frag_spv_count);
100 Shader *sh = newPostShader(gfx, frag, shaders::kNfaa);
101 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create NFAA shader");
102 sh->declareFloat("texelW");
103 sh->declareFloat("texelH");
104 sh->declareFloat("strength");
105 sh->declareFloat("power");
106 sh->declareFloat("blurScale");
107 sh->sendFloat("texelW", 1.f / 256.f);
108 sh->sendFloat("texelH", 1.f / 256.f);
109 sh->sendFloat("strength", 1.f);
110 sh->sendFloat("power", 1.f);
111 sh->sendFloat("blurScale", 1.f);
112 return sh;
113}
114
115Shader *createTaaShader(Graphics *gfx) {
116 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
117 auto frag = copySpv(aa_taa_frag_spv, aa_taa_frag_spv_count);
118 Shader *sh = newPostShader(gfx, frag, shaders::kTaa);
119 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create TAA shader");
120 sh->declareFloat("texelW");
121 sh->declareFloat("texelH");
122 sh->declareFloat("blendCurrent");
123 sh->declareFloat("clampAmount");
124 sh->declareFloat("historyValid");
125 sh->declareFloat("jitterDeltaX");
126 sh->declareFloat("jitterDeltaY");
127 for (int i = 0; i < 16; ++i) sh->declareFloat("reprojection" + std::to_string(i));
128 sh->declareFloat("temporalNearZ");
129 sh->declareFloat("temporalFarZ");
130 sh->declareFloat("reprojectionValid");
131 sh->declareFloat("motionValid");
132 sh->sendFloat("texelW", 1.f / 256.f);
133 sh->sendFloat("texelH", 1.f / 256.f);
134 sh->sendFloat("blendCurrent", 0.92f);
135 sh->sendFloat("clampAmount", 0.85f);
136 sh->sendFloat("historyValid", 0.f);
137 sh->sendFloat("jitterDeltaX", 0.f);
138 sh->sendFloat("jitterDeltaY", 0.f);
139 for (int i = 0; i < 16; ++i)
140 sh->sendFloat("reprojection" + std::to_string(i), i % 5 == 0 ? 1.f : 0.f);
141 sh->sendFloat("temporalNearZ", 0.1f);
142 sh->sendFloat("temporalFarZ", 100.f);
143 sh->sendFloat("reprojectionValid", 0.f);
144 sh->sendFloat("motionValid", 0.f);
145 return sh;
146}
147
148} // namespace
149
151 fxaa_ = createFxaaShader(gfx);
152 smaa_ = createSmaaShader(gfx);
153 ssaa_ = createSsaaShader(gfx);
154 nfaa_ = createNfaaShader(gfx);
155 taa_ = createTaaShader(gfx);
156 applyQualityDefaults();
157}
158
160
161void AntiAliasing::applyQualityDefaults() {
162 if (quality_ == "low") {
163 fxaa_->sendFloat("edgeThreshold", 0.25f);
164 fxaa_->sendFloat("edgeThresholdMin", 0.0833f);
165 fxaa_->sendFloat("subpix", 0.5f);
166 fxaa_->sendFloat("quality", 0.f);
167 smaa_->sendFloat("threshold", 0.15f);
168 smaa_->sendFloat("localContrast", 0.55f);
169 smaa_->sendFloat("maxSearch", 4.f);
170 smaa_->sendFloat("cornerRounding", 0.1f);
171 ssaa_->sendFloat("scale", 2.f);
172 ssaa_->sendFloat("kernel", 0.f); // box
173 ssaa_->sendFloat("sampleRadius", 0.75f);
174 nfaa_->sendFloat("strength", 0.7f);
175 nfaa_->sendFloat("power", 1.2f);
176 nfaa_->sendFloat("blurScale", 0.85f);
177 taa_->sendFloat("blendCurrent", 0.20f);
178 taa_->sendFloat("clampAmount", 0.7f);
179 return;
180 }
181 if (quality_ == "high") {
182 fxaa_->sendFloat("edgeThreshold", 0.125f);
183 fxaa_->sendFloat("edgeThresholdMin", 0.0312f);
184 fxaa_->sendFloat("subpix", 0.85f);
185 fxaa_->sendFloat("quality", 2.f);
186 smaa_->sendFloat("threshold", 0.05f);
187 smaa_->sendFloat("localContrast", 0.4f);
188 smaa_->sendFloat("maxSearch", 16.f);
189 smaa_->sendFloat("cornerRounding", 0.4f);
190 ssaa_->sendFloat("scale", 4.f);
191 ssaa_->sendFloat("kernel", 2.f); // gaussian
192 ssaa_->sendFloat("sampleRadius", 2.f);
193 nfaa_->sendFloat("strength", 1.25f);
194 nfaa_->sendFloat("power", 0.85f);
195 nfaa_->sendFloat("blurScale", 1.35f);
196 taa_->sendFloat("blendCurrent", 0.08f);
197 taa_->sendFloat("clampAmount", 0.95f);
198 return;
199 }
200 // medium (default / unknown)
201 quality_ = "medium";
202 fxaa_->sendFloat("edgeThreshold", 0.166f);
203 fxaa_->sendFloat("edgeThresholdMin", 0.0833f);
204 fxaa_->sendFloat("subpix", 0.75f);
205 fxaa_->sendFloat("quality", 1.f);
206 smaa_->sendFloat("threshold", 0.1f);
207 smaa_->sendFloat("localContrast", 0.5f);
208 smaa_->sendFloat("maxSearch", 8.f);
209 smaa_->sendFloat("cornerRounding", 0.25f);
210 ssaa_->sendFloat("scale", 2.f);
211 ssaa_->sendFloat("kernel", 1.f); // tent
212 ssaa_->sendFloat("sampleRadius", 1.25f);
213 nfaa_->sendFloat("strength", 1.f);
214 nfaa_->sendFloat("power", 1.f);
215 nfaa_->sendFloat("blurScale", 1.f);
216 taa_->sendFloat("blendCurrent", 0.12f);
217 taa_->sendFloat("clampAmount", 0.8f);
218}
219
220void AntiAliasing::setQuality(const std::string &quality) {
221 if (quality == "low" || quality == "medium" || quality == "high")
222 quality_ = quality;
223 else
224 quality_ = "medium";
225 applyQualityDefaults();
226}
227
228void AntiAliasing::setMode(const std::string &mode) {
229 const std::string next =
230 (mode == "fxaa" || mode == "smaa" || mode == "ssaa" || mode == "nfaa" || mode == "taa")
231 ? mode
232 : "fxaa";
233 if (next == "taa" && mode_ != "taa") resetHistory();
234 mode_ = next;
235}
236
237void AntiAliasing::resetHistory() {
238 taaHistoryValid_ = false;
239}
240
241void AntiAliasing::ensureHistoryCanvases(int width, int height) {
242 width = std::max(1, width);
243 height = std::max(1, height);
244 if (!taaHistoryA_ || !taaHistoryB_ || historyW_ != width || historyH_ != height) {
245 taaHistoryA_ = gfx_ ? gfx_->newHDRCanvas(width, height) : nullptr;
246 taaHistoryB_ = gfx_ ? gfx_->newHDRCanvas(width, height) : nullptr;
247 if (!taaHistoryA_ || !taaHistoryB_)
248 throw eve::Exception("AntiAliasing: failed to allocate temporal history canvases");
249 historyRead_ = taaHistoryA_;
250 historyWrite_ = taaHistoryB_;
251 resetHistory();
252 }
253 historyW_ = width;
254 historyH_ = height;
255 if (!historyRead_) historyRead_ = taaHistoryA_;
256 if (!historyWrite_) historyWrite_ = taaHistoryB_;
257}
258
259void AntiAliasing::swapHistoryBuffers() {
260 std::swap(historyRead_, historyWrite_);
261}
262
263Shader *AntiAliasing::shaderForMode() const {
264 if (mode_ == "taa") return taa_;
265 if (mode_ == "smaa") return smaa_;
266 if (mode_ == "ssaa") return ssaa_;
267 if (mode_ == "nfaa") return nfaa_;
268 return fxaa_;
269}
270
271Shader *AntiAliasing::getShader() const { return shaderForMode(); }
272
273bool AntiAliasing::hasParam(const std::string &name) const {
274 Shader *sh = shaderForMode();
275 return sh && sh->hasUniform(name);
276}
277
278void AntiAliasing::setFloat(const std::string &name, float value) {
279 Shader *sh = shaderForMode();
280 if (!sh) throw eve::Exception("AntiAliasing.setFloat: null shader");
281 sh->sendFloat(name, value);
282}
283
284float AntiAliasing::getFloat(const std::string &name) const {
285 Shader *sh = shaderForMode();
286 if (!sh) throw eve::Exception("AntiAliasing.getFloat: null shader");
287 float v = 0.f;
288 if (sh->getFromVar(name, &v, sizeof(v)) != int(sizeof(v)))
289 throw eve::Exception("AntiAliasing.getFloat: missing param '%s'", name.c_str());
290 return v;
291}
292
294 if (mode_ != "ssaa") return 1.f;
295 if (quality_ == "high") return 4.f;
296 return 2.f;
297}
298
299int AntiAliasing::resolutionFor(int destSize) const {
300 if (destSize < 1) destSize = 1;
301 const float s = suggestScale();
302 return std::max(1, int(std::floor(float(destSize) * s)));
303}
304
305void AntiAliasing::uploadScreenUniforms(Texture *source) {
306 if (!source) throw eve::Exception("AntiAliasing: null source texture");
307 const int w = std::max(1, source->getWidth());
308 const int h = std::max(1, source->getHeight());
309 const float tw = 1.f / float(w);
310 const float th = 1.f / float(h);
311 Shader *sh = shaderForMode();
312 if (sh->hasUniform("texelW")) sh->sendFloat("texelW", tw);
313 if (sh->hasUniform("texelH")) sh->sendFloat("texelH", th);
314 if (mode_ == "ssaa" && sh->hasUniform("scale")) {
315 // Keep user override if they set scale explicitly after setQuality;
316 // still ensure scale reflects suggestScale when it matches the quality default.
317 // Prefer the quality-driven suggestScale unless caller already changed it away
318 // from {2,4}. Here we always sync scale to suggestScale for predictability.
319 sh->sendFloat("scale", suggestScale());
320 }
321}
322
323void AntiAliasing::drawFullscreen(Graphics *gfx, Texture *source, Shader *shader) {
324 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
325 if (!source) throw eve::Exception("AntiAliasing: null source texture");
326 if (!shader) throw eve::Exception("AntiAliasing: null shader");
327 uploadScreenUniforms(source);
328 const float dw = gfx->getCanvas() ? float(gfx->getCanvas()->getWidth()) : float(gfx->getWidth());
329 const float dh =
330 gfx->getCanvas() ? float(gfx->getCanvas()->getHeight()) : float(gfx->getHeight());
331 gfx->drawTexturedRectShader(source, shader, 0.f, 0.f, dw, dh, glm::vec4(1.f, 1.f, 1.f, 1.f));
332}
333
334void AntiAliasing::prepareSource(Texture *source) { uploadScreenUniforms(source); }
335
337 if (!source) throw eve::Exception("AntiAliasing.beginTemporalFrame: null source");
338 ensureHistoryCanvases(std::max(1, source->getWidth()), std::max(1, source->getHeight()));
339 if (!historyRead_ || !historyWrite_)
340 throw eve::Exception("AntiAliasing.beginTemporalFrame: history canvases missing");
341 uploadScreenUniforms(source);
342 taa_->sendFloat("historyValid", taaHistoryValid_ ? 1.f : 0.f);
343 const glm::vec2 jitterDelta = (previousJitterNdc_ - temporalJitterNdc_) * 0.5f;
344 taa_->sendFloat("jitterDeltaX", jitterDelta.x);
345 taa_->sendFloat("jitterDeltaY", jitterDelta.y);
346 const glm::mat4 reprojection = previousViewProj_ * glm::inverse(temporalViewProj_);
347 const float *matrixData = glm::value_ptr(reprojection);
348 for (int i = 0; i < 16; ++i)
349 taa_->sendFloat("reprojection" + std::to_string(i), matrixData[i]);
350 taa_->sendFloat("temporalNearZ", temporalNearZ_);
351 taa_->sendFloat("temporalFarZ", temporalFarZ_);
352 taa_->sendFloat("reprojectionValid",
353 taaHistoryValid_ && temporalViewValid_ ? 1.f : 0.f);
354 taa_->sendFloat("motionValid", motion ? 1.f : 0.f);
355 return historyWrite_;
356}
357
359 return taaHistoryValid_ && historyRead_ ? historyRead_->getTexture() : nullptr;
360}
361
363 taaHistoryValid_ = true;
364 previousJitterNdc_ = temporalJitterNdc_;
365 previousViewProj_ = temporalViewProj_;
366 temporalViewValid_ = true;
367 temporalObjectHistory_ = std::move(temporalObjectPending_);
368 temporalObjectPending_.clear();
369 ++temporalFrameIndex_;
370 swapHistoryBuffers();
371}
372
374 auto halton = [](uint32_t index, uint32_t base) {
375 float result = 0.f;
376 float fraction = 1.f / float(base);
377 while (index > 0) {
378 result += fraction * float(index % base);
379 index /= base;
380 fraction /= float(base);
381 }
382 return result;
383 };
384 const uint32_t sample = temporalFrameIndex_ % 8u + 1u;
385 temporalJitterNdc_.x = 2.f * (halton(sample, 2u) - 0.5f) / float(std::max(1, width));
386 temporalJitterNdc_.y = 2.f * (halton(sample, 3u) - 0.5f) / float(std::max(1, height));
387 return temporalJitterNdc_;
388}
389
390void AntiAliasing::setTemporalCamera(const glm::vec3 &eye, const glm::vec3 &target,
391 float fovYDeg) {
392 glm::vec3 forward = target - eye;
393 const float forwardLength = glm::length(forward);
394 if (forwardLength > 1e-5f) forward /= forwardLength;
395 if (temporalCameraValid_) {
396 const float positionCut = std::max(1.f, forwardLength * 0.25f);
397 const bool cut = glm::length(eye - temporalEye_) > positionCut ||
398 glm::dot(forward, temporalForward_) < 0.94f ||
399 std::fabs(fovYDeg - temporalFovY_) > 5.f;
400 if (cut) {
401 resetHistory();
402 if (gfx_) gfx_->pipelineExposure()->invalidateHistory();
403 }
404 }
405 temporalEye_ = eye;
406 temporalForward_ = forward;
407 temporalFovY_ = fovYDeg;
408 temporalCameraValid_ = true;
409}
410
412 resetHistory();
413 if (gfx_) gfx_->pipelineExposure()->invalidateHistory();
414}
415
416void AntiAliasing::setTemporalViewProjection(const glm::mat4 &viewProjection, float nearZ,
417 float farZ) {
418 temporalViewProj_ = viewProjection;
419 temporalNearZ_ = std::max(nearZ, 1e-4f);
420 temporalFarZ_ = std::max(farZ, temporalNearZ_ + 1e-3f);
421}
422
423glm::vec2 AntiAliasing::prepareTemporalObjectMotion(const void *objectKey,
424 const glm::mat4 &model) {
425 if (!objectKey) return glm::vec2(0.f);
426 temporalObjectPending_[objectKey] = model;
427 const auto previous = temporalObjectHistory_.find(objectKey);
428 if (!taaHistoryValid_ || !temporalViewValid_ || previous == temporalObjectHistory_.end())
429 return glm::vec2(0.f);
430 const glm::vec4 origin(0.f, 0.f, 0.f, 1.f);
431 const glm::vec4 staticPrevious = previousViewProj_ * model * origin;
432 const glm::vec4 actualPrevious = previousViewProj_ * previous->second * origin;
433 if (std::fabs(staticPrevious.w) < 1e-6f || std::fabs(actualPrevious.w) < 1e-6f)
434 return glm::vec2(0.f);
435 const glm::vec2 staticUv = glm::vec2(staticPrevious) / staticPrevious.w * 0.5f + 0.5f;
436 const glm::vec2 actualUv = glm::vec2(actualPrevious) / actualPrevious.w * 0.5f + 0.5f;
437 return glm::clamp(actualUv - staticUv, glm::vec2(-1.f), glm::vec2(1.f));
438}
439
441 if (!gfx) throw eve::Exception("AntiAliasing.applyTemporal: null graphics");
442 if (!source) throw eve::Exception("AntiAliasing.applyTemporal: null source");
443
444 Canvas *finalCanvas = gfx->getCanvas();
445 const float dw = finalCanvas ? float(finalCanvas->getWidth()) : float(gfx->getWidth());
446 const float dh = finalCanvas ? float(finalCanvas->getHeight()) : float(gfx->getHeight());
447 Canvas *writeTarget = beginTemporalFrame(source, motion);
448 Texture *prevTex = getTemporalReadTexture();
449 Shader *sh = getTaaShader();
450 if (!sh) throw eve::Exception("AntiAliasing.applyTemporal: missing taa shader");
451
452 gfx->setCanvas(writeTarget);
454 source, prevTex ? prevTex : source, motion ? motion : source, sh, 0.f, 0.f,
455 float(writeTarget->getWidth()), float(writeTarget->getHeight()),
456 glm::vec4(1.f, 1.f, 1.f, 1.f));
457
458 Texture *resolved = writeTarget->getTexture();
459 if (!resolved) throw eve::Exception("AntiAliasing.applyTemporal: resolved texture missing");
460 gfx->setCanvas(finalCanvas);
461 gfx->drawTexturedRectShaderUV(resolved, nullptr, 0.f, 0.f, dw, dh, 0.f, 0.f, 1.f, 1.f,
462 glm::vec4(1.f, 1.f, 1.f, 1.f), false,
465}
466
468 if (!gfx) throw eve::Exception("AntiAliasing.resolveTemporal: null graphics");
469 if (!source) throw eve::Exception("AntiAliasing.resolveTemporal: null source");
470 Canvas *finalCanvas = gfx->getCanvas();
471 Canvas *writeTarget = beginTemporalFrame(source, motion);
474 if (!shader) throw eve::Exception("AntiAliasing.resolveTemporal: missing taa shader");
475 gfx->setCanvas(writeTarget);
477 source, previous ? previous : source, motion ? motion : source, shader, 0.f, 0.f,
478 float(writeTarget->getWidth()), float(writeTarget->getHeight()),
479 glm::vec4(1.f, 1.f, 1.f, 1.f));
480 Texture *resolved = writeTarget->getTexture();
481 if (!resolved) throw eve::Exception("AntiAliasing.resolveTemporal: result missing");
482 gfx->setCanvas(finalCanvas);
484 return resolved;
485}
486
488 float height, float r, float g, float b, float a) {
489 if (!gfx) throw eve::Exception("AntiAliasing.applyTemporalRect: null graphics");
490 if (!source) throw eve::Exception("AntiAliasing.applyTemporalRect: null source");
491
492 Canvas *finalCanvas = gfx->getCanvas();
493 Canvas *writeTarget = beginTemporalFrame(source);
494 Texture *prevTex = getTemporalReadTexture();
495 Shader *sh = getTaaShader();
496 if (!sh) throw eve::Exception("AntiAliasing.applyTemporal: missing taa shader");
497
498 // Pass 1: merge current + previous to history-write target.
499 gfx->setCanvas(writeTarget);
501 source, prevTex ? prevTex : source, source, sh, 0.f, 0.f,
502 float(writeTarget->getWidth()), float(writeTarget->getHeight()),
503 glm::vec4(1.f, 1.f, 1.f, 1.f));
504
505 // Pass 2: composite resolved temporal result to the requested final target.
506 Texture *resolved = writeTarget->getTexture();
507 if (!resolved) throw eve::Exception("AntiAliasing.applyTemporal: resolved texture missing");
508 gfx->setCanvas(finalCanvas);
509 gfx->drawTexturedRectShaderUV(resolved, nullptr, x, y, width, height, 0.f, 0.f, 1.f, 1.f,
510 glm::vec4(r, g, b, a), false, BlendMode::Opaque);
511
513}
514
516 if (mode_ == "taa")
517 applyTemporal(gfx, source);
518 else
519 drawFullscreen(gfx, source, shaderForMode());
520}
521
523 if (!gfx) throw eve::Exception("AntiAliasing.applyTo: null graphics");
524 if (!dest) throw eve::Exception("AntiAliasing.applyTo: null dest");
525 Canvas *prev = gfx->getCanvas();
526 gfx->setCanvas(dest);
527 apply(gfx, source);
528 gfx->setCanvas(prev);
529}
530
532 if (!source) throw eve::Exception("AntiAliasing.applyCanvas: null source");
533 Texture *tex = source->getTexture();
534 if (!tex) throw eve::Exception("AntiAliasing.applyCanvas: source has no sampleable texture");
535 apply(gfx, tex);
536}
537
539 if (!source) throw eve::Exception("AntiAliasing.applyCanvasTo: null source");
540 Texture *tex = source->getTexture();
541 if (!tex) throw eve::Exception("AntiAliasing.applyCanvasTo: source has no sampleable texture");
542 applyTo(gfx, tex, dest);
543}
544
545} // namespace eve::graphics
LogicalId target
double value
float w
Definition AnimClip.cpp:738
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
const std::string & s
tensor::Graph g
Definition GpuGraph.cpp:7
vk::ShaderModule frag
double r
float v
int h
std::uint32_t height
std::uint32_t width
std::string name
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
graphics::Canvas * previous
glm::vec3 eye
Shader * shader
glm::mat4 model
V3 origin
Definition RoadBake.cpp:138
std::uint32_t count
uint32_t index
const UnitySourceAsset & source
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
void setTemporalCamera(const glm::vec3 &eye, const glm::vec3 &target, float fovYDeg)
Detect camera cuts and invalidate incompatible temporal history.
bool hasParam(const std::string &name) const
True when param.
void apply(Graphics *gfx, Texture *source)
Apply current mode to source, writing into the currently bound canvas / screen. Uploads texelW/texelH...
Texture * getTemporalReadTexture() const
Previous resolved frame, or nullptr when history is invalid. @lifetime Returned texture is borrowed f...
glm::vec2 prepareTemporalJitter(int width, int height)
Return this frame's Halton projection jitter in NDC units.
Canvas * beginTemporalFrame(Texture *source, Texture *motion=nullptr)
Prepare uniforms/resources for a backend-recorded temporal pass. @lifetime Returned canvas is borrowe...
void setMode(const std::string &mode)
"fxaa" | "smaa" | "ssaa" | "nfaa" | "taa" (unknown → fxaa).
void invalidateTemporalHistory()
Discard TAA history after a render-chain discontinuity.
void prepareSource(Texture *source)
Upload texel uniforms from source without drawing (3D scene-color resolve).
Shader * getTaaShader() const
Returns the taa shader.
glm::vec2 prepareTemporalObjectMotion(const void *objectKey, const glm::mat4 &model)
Per-object UV correction relative to static-world camera reprojection.
Texture * resolveTemporal(Graphics *gfx, Texture *source, Texture *motion=nullptr)
Resolve TAA into history and return the linear HDR result without compositing it. @lifetime Returned ...
float suggestScale() const
Suggested supersample scale for the active quality when using "ssaa" (2 for low/medium,...
void applyTo(Graphics *gfx, Texture *source, Canvas *dest)
Applies to.
void setTemporalViewProjection(const glm::mat4 &viewProjection, float nearZ, float farZ)
Set the jittered camera matrix used for depth-based history reprojection.
~AntiAliasing()
Anti aliasing.
float getFloat(const std::string &name) const
Returns the float.
void applyTemporal(Graphics *gfx, Texture *source, Texture *motion=nullptr)
Applies temporal.
Shader * getShader() const
Returns the shader.
void setFloat(const std::string &name, float value)
Sets the float.
AntiAliasing(Graphics *gfx)
Anti aliasing.
void applyCanvas(Graphics *gfx, Canvas *source)
Applies canvas.
int resolutionFor(int destSize) const
Resolution for.
void applyCanvasTo(Graphics *gfx, Canvas *source, Canvas *dest)
Applies canvas to.
void endTemporalFrame()
Mark the prepared write target valid and rotate temporal buffers.
void applyTemporalRect(Graphics *gfx, Texture *source, float x, float y, float width, float height, float r=1.f, float g=1.f, float b=1.f, float a=1.f)
Resolve TAA history and composite it into an arbitrary destination rectangle.
void setQuality(const std::string &quality)
"low" | "medium" | "high" (unknown → medium).
Canvas public API.
Definition Canvas.h:17
virtual int getWidth() const =0
Returns the width.
virtual Texture * getTexture()=0
Sampleable color buffer; screen Canvas returns nullptr.
virtual int getHeight() const =0
Returns the height.
void invalidateHistory()
Invalidate eye-adaptation history, for camera cuts and mode changes.
Definition Exposure.h:46
int getWidth() const
Returns the width.
Definition Graphics.h:502
virtual void drawTexturedRectShaderUV(Texture *texture, Shader *shader, float x, float y, float w, float h, float u0, float v0, float u1, float v1, const Color &color, bool rotatedUV=false, BlendMode blend=BlendMode::Alpha)=0
UV draw with an explicit Shader (nullptr = default textured pipeline).
Exposure * pipelineExposure()
Pipeline-owned GPU exposure metering and eye adaptation. @lifetime Returned effect remains valid unti...
virtual Canvas * getCanvas() const =0
Returns the canvas.
virtual void setCanvas(Canvas *canvas)=0
nullptr or this → screen. Switching flushes pending draws to the previous target.
virtual void drawTexturedRectShaderDepthMotion(Texture *color, Texture *depth, Texture *motion, Shader *shader, float x, float y, float w, float h, const Color &tint)=0
Post draw with color, depth/history and motion/reactive textures.
virtual Canvas * newHDRCanvas(int width, int height)=0
Create an engine-internal linear RGBA16F post-process target.
int getHeight() const
Returns the height.
Definition Graphics.h:504
Custom GPU program.
Definition Shader.h:39
bool hasUniform(const std::string &name) const
Definition Shader.cpp:59
void sendFloat(const std::string &name, float x)
Definition Shader.cpp:95
int getFromVar(const std::string &name, void *data, size_t size) const
Definition Shader.cpp:84
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
constexpr const char * kSmaa
constexpr const char * kPostCommon
constexpr const char * kTaa
constexpr const char * kFxaa
constexpr const char * kNfaa
constexpr const char * kSsaa
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25