Line data Source code
1 : /* Copyright (C) 2023 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_POSTPROCMANAGER
19 : #define INCLUDED_POSTPROCMANAGER
20 :
21 : #include "graphics/ShaderTechniquePtr.h"
22 : #include "ps/CStr.h"
23 : #include "renderer/backend/IFramebuffer.h"
24 : #include "renderer/backend/IDeviceCommandContext.h"
25 : #include "renderer/backend/IShaderProgram.h"
26 : #include "renderer/backend/ITexture.h"
27 :
28 : #include <array>
29 : #include <vector>
30 :
31 : class CPostprocManager
32 : {
33 : public:
34 : CPostprocManager();
35 : ~CPostprocManager();
36 :
37 : // Returns true if the the manager can be used.
38 : bool IsEnabled() const;
39 :
40 : // Create all buffers/textures in GPU memory and set default effect.
41 : // @note Must be called before using in the renderer. May be called multiple times.
42 : void Initialize();
43 :
44 : // Update the size of the screen
45 : void Resize();
46 :
47 : // Returns a list of xml files found in shaders/effects/postproc.
48 : static std::vector<CStrW> GetPostEffects();
49 :
50 : // Returns the name of the current effect.
51 0 : const CStrW& GetPostEffect() const
52 : {
53 0 : return m_PostProcEffect;
54 : }
55 :
56 : // Sets the current effect.
57 : void SetPostEffect(const CStrW& name);
58 :
59 : // Triggers update of shaders and FBO if needed.
60 : void UpdateAntiAliasingTechnique();
61 : void UpdateSharpeningTechnique();
62 : void UpdateSharpnessFactor();
63 :
64 : void SetDepthBufferClipPlanes(float nearPlane, float farPlane);
65 :
66 : // @note CPostprocManager must be initialized first
67 : Renderer::Backend::IFramebuffer* PrepareAndGetOutputFramebuffer();
68 :
69 : // First renders blur textures, then calls ApplyEffect for each effect pass,
70 : // ping-ponging the buffers at each step.
71 : // @note CPostprocManager must be initialized first
72 : void ApplyPostproc(
73 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
74 :
75 : // Blits the final postprocessed texture to the system framebuffer. The system
76 : // framebuffer is selected as the output buffer. Should be called before
77 : // silhouette rendering.
78 : // @note CPostprocManager must be initialized first
79 : void BlitOutputFramebuffer(
80 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
81 : Renderer::Backend::IFramebuffer* destination);
82 :
83 : // Returns true if we render main scene in the MSAA framebuffer.
84 : bool IsMultisampleEnabled() const;
85 :
86 : // Resolves the MSAA framebuffer into the regular one.
87 : void ResolveMultisampleFramebuffer(
88 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
89 :
90 : private:
91 : void CreateMultisampleBuffer();
92 : void DestroyMultisampleBuffer();
93 :
94 : std::unique_ptr<Renderer::Backend::IFramebuffer> m_CaptureFramebuffer;
95 :
96 : // Two framebuffers, that we flip between at each shader pass.
97 : std::unique_ptr<Renderer::Backend::IFramebuffer>
98 : m_PingFramebuffer, m_PongFramebuffer;
99 :
100 : // Unique color textures for the framebuffers.
101 : std::unique_ptr<Renderer::Backend::ITexture> m_ColorTex1, m_ColorTex2;
102 :
103 : // The framebuffers share a depth/stencil texture.
104 : std::unique_ptr<Renderer::Backend::ITexture> m_DepthTex;
105 : float m_NearPlane, m_FarPlane;
106 :
107 : // A framebuffer and textures x2 for each blur level we render.
108 18 : struct BlurScale
109 : {
110 36 : struct Step
111 : {
112 : std::unique_ptr<Renderer::Backend::IFramebuffer> framebuffer;
113 : std::unique_ptr<Renderer::Backend::ITexture> texture;
114 : };
115 : std::array<Step, 2> steps;
116 : };
117 : std::array<BlurScale, 3> m_BlurScales;
118 :
119 : // Indicates which of the ping-pong buffers is used for reading and which for drawing.
120 : bool m_WhichBuffer;
121 :
122 : Renderer::Backend::IVertexInputLayout* m_VertexInputLayout = nullptr;
123 :
124 : // The name and shader technique we are using. "default" name means no technique is used
125 : // (i.e. while we do allocate the buffers, no effects are rendered).
126 : CStrW m_PostProcEffect;
127 : CShaderTechniquePtr m_PostProcTech;
128 :
129 : CStr m_SharpName;
130 : CShaderTechniquePtr m_SharpTech;
131 : float m_Sharpness;
132 :
133 : CStr m_AAName;
134 : CShaderTechniquePtr m_AATech;
135 : bool m_UsingMultisampleBuffer;
136 : std::unique_ptr<Renderer::Backend::IFramebuffer> m_MultisampleFramebuffer;
137 : std::unique_ptr<Renderer::Backend::ITexture>
138 : m_MultisampleColorTex, m_MultisampleDepthTex;
139 : uint32_t m_MultisampleCount;
140 : std::vector<uint32_t> m_AllowedSampleCounts;
141 :
142 : // The current screen dimensions in pixels.
143 : int m_Width, m_Height;
144 :
145 : // Is the postproc manager initialized? Buffers created? Default effect loaded?
146 : bool m_IsInitialized;
147 :
148 : // Creates blur textures at various scales, for bloom, DOF, etc.
149 : void ApplyBlur(
150 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
151 :
152 : // High quality GPU image scaling to half size. outTex must have exactly half the size
153 : // of inTex. inWidth and inHeight are the dimensions of inTex in texels.
154 : void ApplyBlurDownscale2x(
155 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
156 : Renderer::Backend::IFramebuffer* framebuffer,
157 : Renderer::Backend::ITexture* inTex,
158 : int inWidth, int inHeight);
159 :
160 : // GPU-based Gaussian blur in two passes. inOutTex contains the input image and will be filled
161 : // with the blurred image. tempTex must have the same size as inOutTex.
162 : // inWidth and inHeight are the dimensions of the images in texels.
163 : void ApplyBlurGauss(
164 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
165 : Renderer::Backend::ITexture* inTex,
166 : Renderer::Backend::ITexture* tempTex,
167 : Renderer::Backend::IFramebuffer* tempFramebuffer,
168 : Renderer::Backend::IFramebuffer* outFramebuffer,
169 : int inWidth, int inHeight);
170 :
171 : // Applies a pass of a given effect to the entire current framebuffer. The shader is
172 : // provided with a number of general-purpose variables, including the rendered screen so far,
173 : // the depth buffer, a number of blur textures, the screen size, the zNear/zFar planes and
174 : // some other parameters used by the optional bloom/HDR pass.
175 : void ApplyEffect(
176 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
177 : const CShaderTechniquePtr& shaderTech, int pass);
178 :
179 : // Delete all allocated buffers/textures from GPU memory.
180 : void Cleanup();
181 :
182 : // Delete existing buffers/textures and create them again, using a new screen size if needed.
183 : // (the textures are also attached to the framebuffers)
184 : void RecreateBuffers();
185 : };
186 :
187 : #endif // INCLUDED_POSTPROCMANAGER
|