Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezGL is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : :
30 : : /* Simple quad Vfx
31 : : * Quad Mesh
32 : : * FBO with one attachment
33 : : * One vertex Shader quad
34 : : * One fragment Shader
35 : : */
36 : :
37 : : #include "ezGL.hpp"
38 : :
39 : : #ifdef IMGUI_INCLUDE
40 : : #include IMGUI_INCLUDE
41 : : #endif
42 : :
43 : : #include <array>
44 : : #include <memory>
45 : : #include <cassert>
46 : : #include <functional>
47 : :
48 : : namespace ez {
49 : : namespace gl {
50 : :
51 : : class QuadVfxAuto;
52 : : typedef std::shared_ptr<QuadVfxAuto> QuadVfxAutoPtr;
53 : : typedef std::weak_ptr<QuadVfxAuto> QuadVfxAutoWeak;
54 : :
55 : : class QuadVfxAuto {
56 : : private:
57 : : QuadVfxAutoWeak m_This;
58 : : std::string m_Name;
59 : : QuadMeshWeak m_QuadMesh;
60 : : ShaderAutoWeak m_VertShader;
61 : : FBOPipeLinePtr m_FBOPipeLinePtr = nullptr;
62 : : ShaderAutoPtr m_FragShaderPtr = nullptr;
63 : : ProgramAutoPtr m_ProgramPtr = nullptr;
64 : : std::array<GLuint, 2U> m_Size;
65 : : bool m_UseMipMapping = false;
66 : : bool m_MultiPass = false;
67 : : GLuint m_RenderIterations = 1U;
68 : : bool m_RenderingPause = false;
69 : :
70 : : public:
71 : : static QuadVfxAutoPtr create( //
72 : : const std::string& vName, //
73 : : ShaderAutoWeak vVertShader, //
74 : : QuadMeshWeak vQuadMesh, //
75 : : const std::string& vFragFile, //
76 : : const GLsizei& vSx, //
77 : : const GLsizei& vSy, //
78 : : const uint32_t& vCountBuffers, //
79 : : const bool vUseMipMapping, //
80 : 0 : const bool vMultiPass) { //
81 : 0 : auto res = std::make_shared<QuadVfxAuto>();
82 : 0 : res->m_This = res;
83 : 0 : if (!res->init(vName, vVertShader, vQuadMesh, vFragFile, vSx, vSy, vCountBuffers, vUseMipMapping, vMultiPass)) {
84 : 0 : res.reset();
85 : 0 : }
86 : 0 : return res;
87 : 0 : }
88 : :
89 : : public:
90 : : QuadVfxAuto() = default;
91 : 0 : ~QuadVfxAuto() {
92 : 0 : unit();
93 : 0 : }
94 : :
95 : : bool init( //
96 : : const std::string& vName, //
97 : : ShaderAutoWeak vVertShader, //
98 : : QuadMeshWeak vQuadMesh, //
99 : : const std::string& vFragFile, //
100 : : const GLsizei& vSx, //
101 : : const GLsizei& vSy, //
102 : : const uint32_t& vCountBuffers, //
103 : : const bool vUseMipMapping, //
104 : 0 : const bool vMultiPass) { //
105 : 0 : assert(!vVertShader.expired());
106 : 0 : assert(!vQuadMesh.expired());
107 : 0 : assert(!vFragFile.empty());
108 : 0 : assert(vSx > 0);
109 : 0 : assert(vSy > 0);
110 : 0 : assert(vCountBuffers > 0U);
111 : 0 : m_Name = vName;
112 : 0 : m_VertShader = vVertShader;
113 : 0 : m_QuadMesh = vQuadMesh;
114 : 0 : m_Size[0] = vSx;
115 : 0 : m_Size[1] = vSy;
116 : 0 : m_UseMipMapping = vUseMipMapping;
117 : 0 : m_MultiPass = vMultiPass;
118 : 0 : m_FBOPipeLinePtr = FBOPipeLine::create(vSx, vSy, vCountBuffers, vUseMipMapping, m_MultiPass);
119 : 0 : if (m_FBOPipeLinePtr != nullptr) {
120 : 0 : m_FragShaderPtr = ez::gl::ShaderAuto::createFromFile(vName, GL_FRAGMENT_SHADER, vFragFile);
121 : 0 : if (m_FragShaderPtr != nullptr) {
122 : 0 : m_ProgramPtr = ez::gl::ProgramAuto::create(vName);
123 : 0 : if (m_ProgramPtr != nullptr) {
124 : 0 : if (m_ProgramPtr->addShader(m_VertShader)) {
125 : 0 : if (m_ProgramPtr->addShader(m_FragShaderPtr)) {
126 : 0 : return m_ProgramPtr->link();
127 : 0 : }
128 : 0 : }
129 : 0 : }
130 : 0 : }
131 : 0 : }
132 : 0 : return false;
133 : 0 : }
134 : 0 : const char* getLabelName() {
135 : 0 : return m_Name.c_str();
136 : 0 : }
137 : 0 : const std::array<GLuint, 2U>& getSize() {
138 : 0 : return m_Size;
139 : 0 : }
140 : 0 : void setRenderingIterations(const GLuint vRenderingIterations) {
141 : 0 : m_RenderIterations = vRenderingIterations;
142 : 0 : }
143 : 0 : GLuint& getRenderingIterationsRef() {
144 : 0 : return m_RenderIterations;
145 : 0 : }
146 : 0 : void setRenderingPause(const bool vRenderingPause) {
147 : 0 : m_RenderingPause = vRenderingPause;
148 : 0 : }
149 : 0 : bool& getRenderingPauseRef() {
150 : 0 : return m_RenderingPause;
151 : 0 : }
152 : 0 : void setUniformPreUploadFunctor(ProgramAuto::UniformPreUploadFunctor vUniformPreUploadFunctor) {
153 : 0 : assert(m_ProgramPtr != nullptr);
154 : 0 : m_ProgramPtr->setUniformPreUploadFunctor(vUniformPreUploadFunctor);
155 : 0 : }
156 : 0 : void addBufferBlock(const GLenum vShaderType, const std::string& vBufferName, const int32_t vBinding, BufferBlock* vBufferPtr) {
157 : 0 : assert(m_ProgramPtr != nullptr);
158 : 0 : m_ProgramPtr->addBufferBlock(vShaderType, vBufferName, vBinding, vBufferPtr);
159 : 0 : }
160 : : void addUniformFloat( //
161 : : const GLenum vShaderType, //
162 : : const std::string& vUniformName, //
163 : : float* vUniformPtr, //
164 : : const GLuint vCountChannels, //
165 : : const bool vShowWidget, //
166 : 0 : const ProgramAuto::UniformWidgetFunctor& vWidgetFunctor) {
167 : 0 : assert(m_ProgramPtr != nullptr);
168 : 0 : m_ProgramPtr->addUniformFloat(vShaderType, vUniformName, vUniformPtr, vCountChannels, vShowWidget, vWidgetFunctor);
169 : 0 : }
170 : : void addUniformInt( //
171 : : const GLenum vShaderType, //
172 : : const std::string& vUniformName, //
173 : : int32_t* vUniformPtr, //
174 : : const GLuint vCountChannels, //
175 : : const bool vShowWidget, //
176 : 0 : const ProgramAuto::UniformWidgetFunctor& vWidgetFunctor) {
177 : 0 : assert(m_ProgramPtr != nullptr);
178 : 0 : m_ProgramPtr->addUniformInt(vShaderType, vUniformName, vUniformPtr, vCountChannels, vShowWidget, vWidgetFunctor);
179 : 0 : }
180 : : void addUniformSampler2D( //
181 : : const GLenum vShaderType, //
182 : : const std::string& vUniformName, //
183 : : int32_t vSampler2D, //
184 : : const bool vShowWidget, //
185 : 0 : const ProgramAuto::UniformWidgetFunctor& vWidgetFunctor) {
186 : 0 : assert(m_ProgramPtr != nullptr);
187 : 0 : m_ProgramPtr->addUniformSampler2D(vShaderType, vUniformName, vSampler2D, vShowWidget, vWidgetFunctor);
188 : 0 : }
189 : 0 : void finalizeBeforeRendering() {
190 : 0 : assert(m_ProgramPtr != nullptr);
191 : 0 : m_ProgramPtr->locateUniforms();
192 : 0 : }
193 : 0 : bool resize(const GLsizei& vSx, const GLsizei vSy) {
194 : 0 : assert(m_FBOPipeLinePtr != nullptr);
195 : 0 : if (m_FBOPipeLinePtr->resize(vSx, vSy)) {
196 : 0 : m_Size[0] = vSx;
197 : 0 : m_Size[1] = vSy;
198 : 0 : return true;
199 : 0 : }
200 : 0 : return false;
201 : 0 : }
202 : 0 : void clearBuffers(const std::array<float, 4U>& vColor) {
203 : 0 : assert(m_FBOPipeLinePtr != nullptr);
204 : 0 : m_FBOPipeLinePtr->clearBuffer(vColor);
205 : 0 : }
206 : 0 : void render() {
207 : 0 : if (m_RenderingPause) {
208 : 0 : return;
209 : 0 : }
210 : 0 : #ifdef PROFILER_SCOPED
211 : 0 : auto name_c_str = m_Name.c_str(); // remvoe some warnings
212 : 0 : PROFILER_SCOPED("VFX", "Render %s", name_c_str);
213 : 0 : #endif
214 : 0 : auto quad_ptr = m_QuadMesh.lock();
215 : 0 : assert(quad_ptr != nullptr);
216 : 0 : assert(m_FBOPipeLinePtr != nullptr);
217 : 0 : assert(m_ProgramPtr != nullptr);
218 : 0 : for (GLuint idx = 0; idx < m_RenderIterations; ++idx) {
219 : 0 : #ifdef PROFILER_SCOPED
220 : 0 : PROFILER_SCOPED("VFX", "Iter %i", idx);
221 : 0 : #endif
222 : 0 : if (m_FBOPipeLinePtr->bind()) {
223 : 0 : if (m_ProgramPtr->use()) {
224 : 0 : m_ProgramPtr->uploadUniforms(m_FBOPipeLinePtr);
225 : 0 : m_FBOPipeLinePtr->selectBuffers();
226 : 0 : {
227 : 0 : #ifdef PROFILER_SCOPED
228 : 0 : PROFILER_SCOPED("Opengl", "glViewport");
229 : 0 : #endif
230 : 0 : glViewport(0, 0, m_Size[0], m_Size[1]);
231 : 0 : }
232 : 0 : quad_ptr->render(GL_TRIANGLES);
233 : 0 : m_ProgramPtr->unuse();
234 : 0 : }
235 : 0 : m_FBOPipeLinePtr->updateMipMaping();
236 : 0 : m_FBOPipeLinePtr->unbind();
237 : 0 : }
238 : 0 : }
239 : 0 : }
240 : 0 : GLuint getTextureId() {
241 : 0 : assert(m_FBOPipeLinePtr != nullptr);
242 : 0 : auto front_fbo_ptr = m_FBOPipeLinePtr->getFrontFBO().lock();
243 : 0 : if (front_fbo_ptr != nullptr) {
244 : 0 : return front_fbo_ptr->getTextureId();
245 : 0 : }
246 : 0 : return 0U;
247 : 0 : }
248 : : #ifdef IMGUI_INCLUDE
249 : : void drawImGuiThumbnail(const float& vSx, const float& vSy, const float& vScaleInv) {
250 : : assert(m_FBOPipeLinePtr != nullptr);
251 : : auto front_fbo_ptr = m_FBOPipeLinePtr->getFrontFBO().lock();
252 : : if (front_fbo_ptr != nullptr) {
253 : : const auto texId = front_fbo_ptr->getTextureId();
254 : : if (texId > 0U) {
255 : : ImGui::ImageButton(m_Name.c_str(), (ImTextureID)(size_t)texId, ImVec2(vSx, vSy), ImVec2(0, vScaleInv), ImVec2(vScaleInv, 0));
256 : : }
257 : : }
258 : : }
259 : : void drawUniformWidgets() {
260 : : assert(m_ProgramPtr != nullptr);
261 : : m_ProgramPtr->drawUniformWidgets();
262 : : }
263 : : #endif
264 : 0 : void unit() {
265 : 0 : m_ProgramPtr.reset();
266 : 0 : m_FragShaderPtr.reset();
267 : 0 : m_FBOPipeLinePtr.reset();
268 : 0 : }
269 : : };
270 : :
271 : : } // namespace gl
272 : : } // namespace ez
|