./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 / 9
0.0%
Branches:
-
-%
Functions:
0 / 6
0.0%

libs/render/src/eu/render/postproc.h
Line Branch Exec Source
1 #pragma once
2
3 #include <memory>
4
5 #include "eu/render/texture.h"
6
7 namespace eu::imgui
8 {
9 struct PropTable;
10 struct ImguiShaderCache;
11 }
12
13 namespace eu::render
14 {
15 struct Texture2d;
16 struct Renderer;
17 struct Camera;
18 struct World;
19 struct RenderWorld;
20
21 /** \addtogroup postproc Post Processing
22 * \brief A basic framework for applying post-processing effects and rendering the \ref World.
23 * @{
24 */
25
26 /// Arguments for rendering a post-processing effect.
27 struct PostProcArg
28 {
29 const World* world = nullptr;
30 Size window_size = {.width = 0, .height = 0};
31 Rect final_rect = {};
32 const Camera* camera = nullptr;
33 Renderer* renderer = nullptr;
34 };
35
36 /// A source that can be rendered to a framebuffer or a screen.
37 /// Pretty much always a "render world" call or the output of an existing \ref RenderTextureWithShader.
38 struct RenderSource
39 {
40 ✗ RenderSource() = default;
41 ✗ virtual ~RenderSource() = default;
42
43 RenderSource(const RenderSource&) = delete;
44 RenderSource(RenderSource&&) = delete;
45 void operator=(const RenderSource&) = delete;
46 void operator=(RenderSource&&) = delete;
47
48 virtual void render(const PostProcArg& arg) = 0;
49 };
50
51 /// A functor that sends properties/uniforms to the shader.
52 /// First and foremost this would the used texture/fbo, but it could also be other uniforms like time, resolution, etc.
53 struct ShaderPropertyProvider
54 {
55 ✗ ShaderPropertyProvider() = default;
56 ✗ virtual ~ShaderPropertyProvider() = default;
57
58 ShaderPropertyProvider(const ShaderPropertyProvider&) = delete;
59 ShaderPropertyProvider(ShaderPropertyProvider&&) = delete;
60 void operator=(const ShaderPropertyProvider&) = delete;
61 void operator=(ShaderPropertyProvider&&) = delete;
62
63 virtual void use_shader(const PostProcArg& a, const FrameBuffer& t) = 0;
64 };
65
66 /// Applies a shader to the output of another source.
67 /// This is done using a framebuffer that is rendered to a quad with the shader applied.
68 struct RenderTextureWithShader : RenderSource
69 {
70 std::string name;
71 std::shared_ptr<RenderSource> source;
72 std::shared_ptr<FrameBuffer> fbo;
73 ShaderPropertyProvider* effect;
74
75 RenderTextureWithShader(std::string n, std::shared_ptr<RenderSource> s, std::shared_ptr<FrameBuffer> f, ShaderPropertyProvider* e);
76
77 /// render internal fbo to a quad with a shader
78 void render(const PostProcArg& arg) override;
79
80 /// call render on linked source and render to fbo
81 void update(const PostProcArg& arg);
82 };
83
84 /// A compiled full-screen-effect.
85 /// when compiled it could be:
86 /// * [render world to screen]
87 /// * [render world to fbo], [render fbo to screen with shader]
88 /// * [render world to fbo] [[render fbo to intermediate with shader] [render int to screen with shader]]
89 /// * [render world to fbo] [[render fbo to intermediate with shader] [render int to fbo with shader]] [render fbo to screen with shader]
90 struct CompiledStack
91 {
92 /// start with a simple world, but depending on the current effect list, could be more...
93 std::shared_ptr<RenderSource> last_source;
94
95 std::vector<std::shared_ptr<RenderTextureWithShader>> targets;
96 };
97
98
99 /// Arguments for when building a effect stack.
100 /// @see \ref Effect::build
101 struct BuildArg
102 {
103 CompiledStack* builder;
104 Size window_size;
105 };
106
107
108 struct EffectStack;
109
110 /// A effect that can be toggled.
111 /// Common effects are: blur, bloom, color grading, etc.
112 /// Most effects from https://lettier.github.io/3d-game-shaders-for-beginners/index.html would be implemented as effects.
113 struct Effect
114 {
115 ✗ Effect() = default;
116 ✗ virtual ~Effect() = default;
117
118 Effect(const Effect&) = delete;
119 Effect(Effect&&) = delete;
120 void operator=(const Effect&) = delete;
121 void operator=(Effect&&) = delete;
122
123 virtual void build(const BuildArg& arg) = 0;
124 virtual void update(float dt) = 0;
125 virtual void gui() = 0;
126
127 [[nodiscard]] bool enabled() const;
128
129 protected:
130
131 void set_enabled(bool n);
132
133 private:
134
135 friend struct EffectStack;
136
137 bool is_enabled = false;
138 EffectStack* owner = nullptr;
139 };
140
141 /// A special effect where the effect can be eased into existence.
142 /// Setting it to 0 will disable the effect, setting it anything above will enable it.
143 struct FactorEffect : Effect
144 {
145 FactorEffect();
146 [[nodiscard]] float get_factor() const;
147 void set_factor(float f);
148
149 private:
150
151 float factor = 0.0f;
152 };
153
154 /// The facade of the post-proc framework.
155 struct EffectStack
156 {
157 int current_msaa_setting = -1;
158 bool dirty = true;
159 std::optional<Size> window_size;
160 std::vector<std::shared_ptr<Effect>> effects;
161 CompiledStack compiled;
162
163 // render world settings
164 // todo(Gustav): is it useful to disable hdr rendering or should that just be removed?
165 // todo(Gustav): move exposure to a better place?
166 bool use_hdr = true;
167 float exposure = 1.0f;
168
169 std::shared_ptr<RenderWorld> render_world;
170
171 /// rebuilds stack if dirty, update all targets, then render the last_source
172 void render(const PostProcArg& arg);
173 void update(float dt) const;
174 void gui(imgui::ImguiShaderCache* cache, const imgui::PropTable& prop);
175 void gui_effects();
176 };
177
178 /**
179 * @}
180 */
181
182 }
183