载入中...
搜索中...
未找到
AntiAliasing.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
4#include "graphics/Canvas.h"
5#include "graphics/Graphics.h"
6#include "graphics/Shader.h"
7#include "graphics/Texture.h"
8#include "graphics/shaders/aa_fxaa_frag_spv.inc"
9#include "graphics/shaders/aa_nfaa_frag_spv.inc"
10#include "graphics/shaders/aa_smaa_frag_spv.inc"
11#include "graphics/shaders/aa_ssaa_frag_spv.inc"
12
13#include <algorithm>
14#include <cmath>
15#include <cstdint>
16#include <vector>
17
18#include <glm/vec4.hpp>
19
20namespace eve::graphics {
21namespace {
22
23std::vector<uint32_t> copySpv(const uint32_t *data, size_t count) {
24 return std::vector<uint32_t>(data, data + count);
25}
26
27Shader *createFxaaShader(Graphics *gfx) {
28 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
29 auto frag = copySpv(aa_fxaa_frag_spv, aa_fxaa_frag_spv_count);
30 Shader *sh = gfx->newShaderFromSpv({}, frag);
31 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create FXAA shader");
32 sh->declareFloat("texelW");
33 sh->declareFloat("texelH");
34 sh->declareFloat("edgeThreshold");
35 sh->declareFloat("edgeThresholdMin");
36 sh->declareFloat("subpix");
37 sh->declareFloat("quality");
38 sh->sendFloat("texelW", 1.f / 256.f);
39 sh->sendFloat("texelH", 1.f / 256.f);
40 sh->sendFloat("edgeThreshold", 0.166f);
41 sh->sendFloat("edgeThresholdMin", 0.0833f);
42 sh->sendFloat("subpix", 0.75f);
43 sh->sendFloat("quality", 1.f);
44 return sh;
45}
46
47Shader *createSmaaShader(Graphics *gfx) {
48 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
49 auto frag = copySpv(aa_smaa_frag_spv, aa_smaa_frag_spv_count);
50 Shader *sh = gfx->newShaderFromSpv({}, frag);
51 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create SMAA shader");
52 sh->declareFloat("texelW");
53 sh->declareFloat("texelH");
54 sh->declareFloat("threshold");
55 sh->declareFloat("localContrast");
56 sh->declareFloat("maxSearch");
57 sh->declareFloat("cornerRounding");
58 sh->sendFloat("texelW", 1.f / 256.f);
59 sh->sendFloat("texelH", 1.f / 256.f);
60 sh->sendFloat("threshold", 0.1f);
61 sh->sendFloat("localContrast", 0.5f);
62 sh->sendFloat("maxSearch", 8.f);
63 sh->sendFloat("cornerRounding", 0.25f);
64 return sh;
65}
66
67Shader *createSsaaShader(Graphics *gfx) {
68 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
69 auto frag = copySpv(aa_ssaa_frag_spv, aa_ssaa_frag_spv_count);
70 Shader *sh = gfx->newShaderFromSpv({}, frag);
71 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create SSAA shader");
72 sh->declareFloat("texelW");
73 sh->declareFloat("texelH");
74 sh->declareFloat("scale");
75 sh->declareFloat("kernel");
76 sh->declareFloat("sampleRadius");
77 sh->sendFloat("texelW", 1.f / 512.f);
78 sh->sendFloat("texelH", 1.f / 512.f);
79 sh->sendFloat("scale", 2.f);
80 sh->sendFloat("kernel", 1.f); // tent
81 sh->sendFloat("sampleRadius", 1.f);
82 return sh;
83}
84
85Shader *createNfaaShader(Graphics *gfx) {
86 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
87 auto frag = copySpv(aa_nfaa_frag_spv, aa_nfaa_frag_spv_count);
88 Shader *sh = gfx->newShaderFromSpv({}, frag);
89 if (!sh || !sh->gpuHandle) throw eve::Exception("AntiAliasing: failed to create NFAA shader");
90 sh->declareFloat("texelW");
91 sh->declareFloat("texelH");
92 sh->declareFloat("strength");
93 sh->declareFloat("power");
94 sh->declareFloat("blurScale");
95 sh->sendFloat("texelW", 1.f / 256.f);
96 sh->sendFloat("texelH", 1.f / 256.f);
97 sh->sendFloat("strength", 1.f);
98 sh->sendFloat("power", 1.f);
99 sh->sendFloat("blurScale", 1.f);
100 return sh;
101}
102
103} // namespace
104
106 fxaa_ = createFxaaShader(gfx);
107 smaa_ = createSmaaShader(gfx);
108 ssaa_ = createSsaaShader(gfx);
109 nfaa_ = createNfaaShader(gfx);
110 applyQualityDefaults();
111}
112
114
115void AntiAliasing::applyQualityDefaults() {
116 if (quality_ == "low") {
117 fxaa_->sendFloat("edgeThreshold", 0.25f);
118 fxaa_->sendFloat("edgeThresholdMin", 0.0833f);
119 fxaa_->sendFloat("subpix", 0.5f);
120 fxaa_->sendFloat("quality", 0.f);
121 smaa_->sendFloat("threshold", 0.15f);
122 smaa_->sendFloat("localContrast", 0.55f);
123 smaa_->sendFloat("maxSearch", 4.f);
124 smaa_->sendFloat("cornerRounding", 0.1f);
125 ssaa_->sendFloat("scale", 2.f);
126 ssaa_->sendFloat("kernel", 0.f); // box
127 ssaa_->sendFloat("sampleRadius", 0.75f);
128 nfaa_->sendFloat("strength", 0.7f);
129 nfaa_->sendFloat("power", 1.2f);
130 nfaa_->sendFloat("blurScale", 0.85f);
131 return;
132 }
133 if (quality_ == "high") {
134 fxaa_->sendFloat("edgeThreshold", 0.125f);
135 fxaa_->sendFloat("edgeThresholdMin", 0.0312f);
136 fxaa_->sendFloat("subpix", 0.85f);
137 fxaa_->sendFloat("quality", 2.f);
138 smaa_->sendFloat("threshold", 0.05f);
139 smaa_->sendFloat("localContrast", 0.4f);
140 smaa_->sendFloat("maxSearch", 16.f);
141 smaa_->sendFloat("cornerRounding", 0.4f);
142 ssaa_->sendFloat("scale", 4.f);
143 ssaa_->sendFloat("kernel", 2.f); // gaussian
144 ssaa_->sendFloat("sampleRadius", 2.f);
145 nfaa_->sendFloat("strength", 1.25f);
146 nfaa_->sendFloat("power", 0.85f);
147 nfaa_->sendFloat("blurScale", 1.35f);
148 return;
149 }
150 // medium (default / unknown)
151 quality_ = "medium";
152 fxaa_->sendFloat("edgeThreshold", 0.166f);
153 fxaa_->sendFloat("edgeThresholdMin", 0.0833f);
154 fxaa_->sendFloat("subpix", 0.75f);
155 fxaa_->sendFloat("quality", 1.f);
156 smaa_->sendFloat("threshold", 0.1f);
157 smaa_->sendFloat("localContrast", 0.5f);
158 smaa_->sendFloat("maxSearch", 8.f);
159 smaa_->sendFloat("cornerRounding", 0.25f);
160 ssaa_->sendFloat("scale", 2.f);
161 ssaa_->sendFloat("kernel", 1.f); // tent
162 ssaa_->sendFloat("sampleRadius", 1.25f);
163 nfaa_->sendFloat("strength", 1.f);
164 nfaa_->sendFloat("power", 1.f);
165 nfaa_->sendFloat("blurScale", 1.f);
166}
167
168void AntiAliasing::setQuality(const std::string &quality) {
169 if (quality == "low" || quality == "medium" || quality == "high")
170 quality_ = quality;
171 else
172 quality_ = "medium";
173 applyQualityDefaults();
174}
175
176void AntiAliasing::setMode(const std::string &mode) {
177 if (mode == "fxaa" || mode == "smaa" || mode == "ssaa" || mode == "nfaa")
178 mode_ = mode;
179 else
180 mode_ = "fxaa";
181}
182
183Shader *AntiAliasing::shaderForMode() const {
184 if (mode_ == "smaa") return smaa_;
185 if (mode_ == "ssaa") return ssaa_;
186 if (mode_ == "nfaa") return nfaa_;
187 return fxaa_;
188}
189
190Shader *AntiAliasing::getShader() const { return shaderForMode(); }
191
192bool AntiAliasing::hasParam(const std::string &name) const {
193 Shader *sh = shaderForMode();
194 return sh && sh->hasUniform(name);
195}
196
197void AntiAliasing::setFloat(const std::string &name, float value) {
198 Shader *sh = shaderForMode();
199 if (!sh) throw eve::Exception("AntiAliasing.setFloat: null shader");
200 sh->sendFloat(name, value);
201}
202
203float AntiAliasing::getFloat(const std::string &name) const {
204 Shader *sh = shaderForMode();
205 if (!sh) throw eve::Exception("AntiAliasing.getFloat: null shader");
206 float v = 0.f;
207 if (sh->getFromVar(name, &v, sizeof(v)) != int(sizeof(v)))
208 throw eve::Exception("AntiAliasing.getFloat: missing param '%s'", name.c_str());
209 return v;
210}
211
213 if (mode_ != "ssaa") return 1.f;
214 if (quality_ == "high") return 4.f;
215 return 2.f;
216}
217
218int AntiAliasing::resolutionFor(int destSize) const {
219 if (destSize < 1) destSize = 1;
220 const float s = suggestScale();
221 return std::max(1, int(std::floor(float(destSize) * s)));
222}
223
224void AntiAliasing::uploadScreenUniforms(Texture *source) {
225 if (!source) throw eve::Exception("AntiAliasing: null source texture");
226 const int w = std::max(1, source->getWidth());
227 const int h = std::max(1, source->getHeight());
228 const float tw = 1.f / float(w);
229 const float th = 1.f / float(h);
230 Shader *sh = shaderForMode();
231 if (sh->hasUniform("texelW")) sh->sendFloat("texelW", tw);
232 if (sh->hasUniform("texelH")) sh->sendFloat("texelH", th);
233 if (mode_ == "ssaa" && sh->hasUniform("scale")) {
234 // Keep user override if they set scale explicitly after setQuality;
235 // still ensure scale reflects suggestScale when it matches the quality default.
236 // Prefer the quality-driven suggestScale unless caller already changed it away
237 // from {2,4}. Here we always sync scale to suggestScale for predictability.
238 sh->sendFloat("scale", suggestScale());
239 }
240}
241
242void AntiAliasing::drawFullscreen(Graphics *gfx, Texture *source, Shader *shader) {
243 if (!gfx) throw eve::Exception("AntiAliasing: null graphics");
244 if (!source) throw eve::Exception("AntiAliasing: null source texture");
245 if (!shader) throw eve::Exception("AntiAliasing: null shader");
246 uploadScreenUniforms(source);
247 const float dw = gfx->getCanvas() ? float(gfx->getCanvas()->getWidth()) : float(gfx->getWidth());
248 const float dh =
249 gfx->getCanvas() ? float(gfx->getCanvas()->getHeight()) : float(gfx->getHeight());
250 gfx->drawTexturedRectShader(source, shader, 0.f, 0.f, dw, dh, glm::vec4(1.f, 1.f, 1.f, 1.f));
251}
252
253void AntiAliasing::prepareSource(Texture *source) { uploadScreenUniforms(source); }
254
256 drawFullscreen(gfx, source, shaderForMode());
257}
258
259void AntiAliasing::applyTo(Graphics *gfx, Texture *source, Canvas *dest) {
260 if (!gfx) throw eve::Exception("AntiAliasing.applyTo: null graphics");
261 if (!dest) throw eve::Exception("AntiAliasing.applyTo: null dest");
262 Canvas *prev = gfx->getCanvas();
263 gfx->setCanvas(dest);
264 apply(gfx, source);
265 gfx->setCanvas(prev);
266}
267
269 if (!source) throw eve::Exception("AntiAliasing.applyCanvas: null source");
270 Texture *tex = source->getTexture();
271 if (!tex) throw eve::Exception("AntiAliasing.applyCanvas: source has no sampleable texture");
272 apply(gfx, tex);
273}
274
276 if (!source) throw eve::Exception("AntiAliasing.applyCanvasTo: null source");
277 Texture *tex = source->getTexture();
278 if (!tex) throw eve::Exception("AntiAliasing.applyCanvasTo: source has no sampleable texture");
279 applyTo(gfx, tex, dest);
280}
281
282} // namespace eve::graphics
std::string value
vk::ShaderModule frag
int h
int w
Shader * shader
const char * name
Definition RockMesh.cpp:21
int v
uint32_t s
Definition Weather.cpp:28
bool hasParam(const std::string &name) const
void apply(Graphics *gfx, Texture *source)
Apply current mode to source, writing into the currently bound canvas / screen. Uploads texelW/texelH...
void setMode(const std::string &mode)
"fxaa" | "smaa" | "ssaa" | "nfaa" (unknown → fxaa).
void prepareSource(Texture *source)
Upload texel uniforms from source without drawing (3D scene-color resolve).
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)
float getFloat(const std::string &name) const
void setFloat(const std::string &name, float value)
void applyCanvas(Graphics *gfx, Canvas *source)
int resolutionFor(int destSize) const
void applyCanvasTo(Graphics *gfx, Canvas *source, Canvas *dest)
void setQuality(const std::string &quality)
"low" | "medium" | "high" (unknown → medium).
virtual Texture * getTexture()=0
Sampleable color buffer; screen Canvas returns nullptr.
virtual Canvas * getCanvas() const =0
virtual void setCanvas(Canvas *canvas)=0
nullptr or this → screen. Switching flushes pending draws to the previous target.
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
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