载入中...
搜索中...
未找到
BloomGaussian.cpp
浏览该文件的文档.
1#include "graphics/Bloom.h"
2
3#include <algorithm>
4#include <cmath>
5#include <string>
6#include <vector>
7#include "common/Exception.h"
8#include "graphics/Canvas.h"
9#include "graphics/Graphics.h"
10#include "graphics/Shader.h"
11#include "graphics/Texture.h"
14#include "graphics/shaders/bloom_gaussian_frag_spv.inc"
15
16namespace eve::graphics {
20 !std::isfinite(value.scatter) || value.scatter < 0.f || value.scatter > 1.f || value.maxIterations < 1 ||
21 value.maxIterations > 16 || !std::isfinite(value.clamp) || value.clamp <= 0.f || value.clamp > 65504.f)
23 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid bloom filter settings", "graphics.bloom"));
24 return Result<void>::success();
25}
26
33
34Texture* Bloom::buildGaussian(Texture* source, float threshold) {
35 if (!gaussianShader_) {
36 gaussianShader_ = gfx_->getBackendName() == "webgpu"
38 : gfx_->newShaderFromSpv(
39 {}, std::vector<uint32_t>(bloom_gaussian_frag_spv,
40 bloom_gaussian_frag_spv + bloom_gaussian_frag_spv_count));
41 if (!gaussianShader_ || !gaussianShader_->gpuHandle) throw Exception("Gaussian bloom shader creation failed");
42 for (const char* name : {"texelW", "texelH", "phase", "threshold", "clamp", "scatter", "intensity", "radius",
43 "tint", "hasLow", "prefilter"})
44 gaussianShader_->declareFloat(name);
45 }
46 const bool pyramid = filterSettings_.filter == BloomFilter::GaussianPyramid;
47 constexpr float sizes[]{.3f, 1.f, 2.f, 10.f, 30.f, 64.f};
48 const int width = std::max(source->getWidth(), 1), height = std::max(source->getHeight(), 1);
49 const int halfWidth = std::max((width + (pyramid ? 1 : 0)) / 2, 1);
50 const int halfHeight = std::max((height + (pyramid ? 1 : 0)) / 2, 1);
51 const int count = pyramid ? std::min(6, filterSettings_.maxIterations)
52 : std::clamp(int(std::floor(std::log2(std::max(halfWidth, halfHeight)))) - 1, 1,
53 filterSettings_.maxIterations);
54 // Check each target so switching filters with equal level counts rebuilds
55 // the differently sized fast-blur intermediate without stale reuse.
56 int w = halfWidth, h = halfHeight;
57 for (int i = 0; i < count; ++i) {
58 const bool fast = pyramid && w * sizes[i] * .02f >= 7.f;
59 const int intermediateWidth = fast ? std::max((w + 1) / 2, 1) : w;
60 if (!gaussianDown_[i] || gaussianDown_[i]->getWidth() != w || gaussianDown_[i]->getHeight() != h) {
61 gaussianDown_[i] = gfx_->newHDRCanvas(w, h);
62 }
63 if (!gaussianUp_[i] || gaussianUp_[i]->getWidth() != intermediateWidth || gaussianUp_[i]->getHeight() != h) {
64 gaussianUp_[i] = gfx_->newHDRCanvas(intermediateWidth, h);
65 }
66 if (!gaussianDown_[i] || !gaussianUp_[i]) throw Exception("Gaussian bloom target allocation failed");
67 w = std::max((w + (pyramid ? 1 : 0)) / 2, 1);
68 h = std::max((h + (pyramid ? 1 : 0)) / 2, 1);
69 }
70 struct RestoreCanvas {
71 Graphics* gfx;
72 Canvas* previous;
73 ~RestoreCanvas() { gfx->setCanvas(previous); }
74 } restore{gfx_, gfx_->getCanvas()};
75 float pyramidRadius = 0, pyramidTint = 0;
76 auto draw = [&](Texture* high, Texture* low, Canvas* target, float phase) {
77 target->clear(Color(0.f, 0.f, 0.f, 0.f), {}, {});
78 gfx_->setCanvas(target);
79 gaussianShader_->sendFloat("texelW", 1.f / high->getWidth());
80 gaussianShader_->sendFloat("texelH", 1.f / high->getHeight());
81 gaussianShader_->sendFloat("phase", phase);
82 gaussianShader_->sendFloat("radius", pyramidRadius);
83 gaussianShader_->sendFloat("tint", pyramidTint);
84 gaussianShader_->sendFloat("hasLow", low ? 1.f : 0.f);
85 gaussianShader_->sendFloat("prefilter", phase == 5.f && high == source ? 1.f : 0.f);
86 gaussianShader_->sendFloat("threshold", std::max(threshold, 0.f));
87 gaussianShader_->sendFloat("clamp", filterSettings_.clamp);
88 gaussianShader_->sendFloat("scatter", filterSettings_.scatter);
89 gfx_->drawTexturedRectShaderDepth(high, low ? low : high, gaussianShader_, 0, 0, float(target->getWidth()),
90 float(target->getHeight()), Color(1.f));
91 };
92 if (pyramid) {
94 for (int i = 0; i < count; ++i) {
95 draw(input, nullptr, gaussianDown_[i], 5.f);
96 input = gaussianDown_[i]->getTexture();
97 }
98 constexpr float tints[]{.3465f, .138f, .1176f, .066f, .066f, .061f};
99 Texture* low = nullptr;
100 for (int i = count - 1; i >= 0; --i) {
101 const float radius = std::clamp(gaussianDown_[i]->getWidth() * sizes[i] * .02f, .0001f, 31.f);
102 pyramidRadius = radius;
103 pyramidTint = tints[i] / 6.f;
104 draw(gaussianDown_[i]->getTexture(), nullptr, gaussianUp_[i], 6.f);
105 draw(gaussianUp_[i]->getTexture(), low, gaussianDown_[i], 7.f);
106 low = gaussianDown_[i]->getTexture();
107 }
108 return low;
109 }
110 draw(source, nullptr, gaussianDown_[0], 0.f);
111 for (int i = 1; i < count; ++i) {
112 draw(gaussianDown_[i - 1]->getTexture(), nullptr, gaussianUp_[i], 1.f);
113 draw(gaussianUp_[i]->getTexture(), nullptr, gaussianDown_[i], 2.f);
114 }
115 Texture* low = gaussianDown_[count - 1]->getTexture();
116 for (int i = count - 2; i >= 0; --i) {
117 draw(gaussianDown_[i]->getTexture(), low, gaussianUp_[i], 3.f);
118 low = gaussianUp_[i]->getTexture();
119 }
120 return low;
121}
122
123Texture* Bloom::compositeGaussian(Texture* source, Texture* bloom, float intensity) {
124 struct RestoreCanvas {
125 Graphics* gfx;
126 Canvas* previous;
127 ~RestoreCanvas() { gfx->setCanvas(previous); }
128 } restore{gfx_, gfx_->getCanvas()};
129 composite_->clear(Color(0.f, 0.f, 0.f, 0.f), {}, {});
130 gfx_->setCanvas(composite_);
131 gaussianShader_->sendFloat("texelW", 1.f / source->getWidth());
132 gaussianShader_->sendFloat("texelH", 1.f / source->getHeight());
133 gaussianShader_->sendFloat("phase", 4.f);
134 gaussianShader_->sendFloat("intensity", intensity);
135 gfx_->drawTexturedRectShaderDepth(source, bloom, gaussianShader_, 0, 0, float(composite_->getWidth()),
136 float(composite_->getHeight()), Color(1.f));
137 return composite_->getTexture();
138}
139} // namespace eve::graphics
LogicalId target
double value
float w
Definition AnimClip.cpp:738
float phase
Definition CaveMesh.cpp:58
EvpackChunkInput input
Definition Evpack.cpp:170
int h
std::uint32_t height
std::uint32_t width
std::string name
bool valid
MeshVfxBatchedDraw draw
graphics::Canvas * previous
float radius
float halfWidth
float halfHeight
std::uint32_t count
TerrainThermalSettings settings
const UnitySourceAsset & source
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Result< void > configureFilter(const BloomFilterSettings &settings)
Select a reconstruction filter for subsequent builds.
virtual int getWidth() const =0
Returns the width.
virtual void clear(std::optional< Color > color, std::optional< int > stencil, std::optional< double > depth)=0
Clears .
virtual Texture * getTexture()=0
Sampleable color buffer; screen Canvas returns nullptr.
virtual int getHeight() const =0
Returns the height.
virtual std::string getBackendName() const =0
Renderer backend id used by sibling modules (e.g. Gpgpu).
virtual Shader * newShaderFromWgsl(const std::string &vertWgsl, const std::string &fragWgsl)=0
Create a 2D custom shader from WGSL source (WebGPU backend). Empty vert → default textured vertex sha...
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 Canvas * newHDRCanvas(int width, int height)=0
Create an engine-internal linear RGBA16F post-process target.
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,...
void sendFloat(const std::string &name, float x)
Definition Shader.cpp:95
int declareFloat(const std::string &name)
Reserve sequential float slots in the push-constant block. Returns start index.
Definition Shader.cpp:43
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
constexpr const char * kPostCommon
constexpr const char * kBloomGaussian
Gaussian-scatter HDR bloom stages. @lifetime Static process storage.
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13
EVENGINE_API_BACKENDS Result< void > validateBloomFilterSettings(const BloomFilterSettings &settings)
Validate enum, finite scatter [0,1], iterations [1,16], and finite clamp (0,65504].
Value-owned Gaussian bloom settings, independent of camera intensity and threshold.
Definition Bloom.h:21