载入中...
搜索中...
未找到
DepthOfField.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <string>
5#include <vector>
6
7#include "common/Exception.h"
9#include "graphics/Canvas.h"
10#include "graphics/Color.h"
11#include "graphics/Graphics.h"
12#include "graphics/Shader.h"
13#include "graphics/Texture.h"
15#include "graphics/shaders/dof_gaussian_frag_spv.inc"
16
17namespace eve::graphics {
18namespace {
19
20std::vector<uint32_t> copySpv(const uint32_t *data, size_t count) {
21 return std::vector<uint32_t>(data, data + count);
22}
23
24Shader *newDofShader(Graphics *gfx) {
25 Shader *shader =
26 gfx->getBackendName() == "webgpu"
27 ? gfx->newShaderFromWgsl({}, std::string(shaders::kPostCommon) + shaders::kDofGaussian)
28 : gfx->newShaderFromSpv({},
29 copySpv(dof_gaussian_frag_spv, dof_gaussian_frag_spv_count));
30 if (!shader || !shader->gpuHandle) throw eve::Exception("DepthOfField: failed to create shader");
31 shader->declareFloat("texelW");
32 shader->declareFloat("texelH");
33 shader->declareFloat("directionX");
34 shader->declareFloat("directionY");
35 shader->declareFloat("focusDistance");
36 shader->declareFloat("focusRange");
37 shader->declareFloat("maxBlurPx");
38 shader->declareFloat("nearZ");
39 shader->declareFloat("farZ");
40 return shader;
41}
42
43} // namespace
44
46 if (!gfx_) throw eve::Exception("DepthOfField: null graphics");
47 shader_ = newDofShader(gfx_);
48}
49
50void DepthOfField::ensureTargets(int width, int height) {
51 width = std::max(width, 1);
52 height = std::max(height, 1);
53 if (temp_ && width_ == width && height_ == height) return;
54 width_ = width;
55 height_ = height;
56 temp_ = gfx_->newHDRCanvas(width, height);
57 output_ = gfx_->newHDRCanvas(width, height);
58 if (!temp_ || !output_) throw eve::Exception("DepthOfField: failed to allocate HDR targets");
59}
60
61void DepthOfField::configure(float dirX, float dirY, float focusDistance, float maxBlurPx,
62 float focusRange, float nearZ, float farZ, int width, int height) {
63 shader_->sendFloat("texelW", 1.f / float(std::max(width, 1)));
64 shader_->sendFloat("texelH", 1.f / float(std::max(height, 1)));
65 shader_->sendFloat("directionX", dirX);
66 shader_->sendFloat("directionY", dirY);
67 shader_->sendFloat("focusDistance", std::max(focusDistance, 0.f));
68 shader_->sendFloat("focusRange", std::max(focusRange, 1e-3f));
69 shader_->sendFloat("maxBlurPx", std::max(maxBlurPx, 0.f));
70 const float nearClip = nearZ > 1e-4f ? nearZ : 0.1f;
71 const float farClip = farZ > nearClip ? farZ : nearClip + 1.f;
72 shader_->sendFloat("nearZ", nearClip);
73 shader_->sendFloat("farZ", farClip);
74}
75
76Texture *DepthOfField::apply(Texture *source, Texture *hwDepth, float focusDistance,
77 float maxBlurPx, float focusRange, float nearZ, float farZ) {
78 if (!source) throw eve::Exception("DepthOfField.apply: null source");
79 if (!hwDepth || maxBlurPx <= 0.f) return source;
80
81 ensureTargets(source->getWidth(), source->getHeight());
82 Canvas *previous = gfx_->getCanvas();
83
84 temp_->clear(Color(0.f, 0.f, 0.f, 0.f), {}, {});
85 gfx_->setCanvas(temp_);
86 configure(1.f, 0.f, focusDistance, maxBlurPx, focusRange, nearZ, farZ, width_, height_);
87 gfx_->drawTexturedRectShaderDepth(source, hwDepth, shader_, 0.f, 0.f, float(width_),
88 float(height_), Color(1.f, 1.f, 1.f, 1.f));
89
90 output_->clear(Color(0.f, 0.f, 0.f, 0.f), {}, {});
91 gfx_->setCanvas(output_);
92 configure(0.f, 1.f, focusDistance, maxBlurPx, focusRange, nearZ, farZ, width_, height_);
93 gfx_->drawTexturedRectShaderDepth(temp_->getTexture(), hwDepth, shader_, 0.f, 0.f, float(width_),
94 float(height_), Color(1.f, 1.f, 1.f, 1.f));
95
96 gfx_->setCanvas(previous);
97 Texture *result = output_->getTexture();
98 if (!result) throw eve::Exception("DepthOfField: output texture missing");
99 return result;
100}
101
102} // namespace eve::graphics
std::uint32_t height
std::uint32_t width
graphics::Canvas * previous
Shader * shader
std::uint32_t count
const UnitySourceAsset & source
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
Canvas public API.
Definition Canvas.h:17
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.
Texture * apply(Texture *source, Texture *hwDepth, float focusDistance, float maxBlurPx, float focusRange, float nearZ, float farZ)
Apply separable Gaussian DOF.
DepthOfField(Graphics *gfx)
Create the cross-backend DOF shaders.
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 * kDofGaussian
constexpr const char * kPostCommon
卡牌游戏 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