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 QuadVfx;
52 : : typedef std::shared_ptr<QuadVfx> QuadVfxPtr;
53 : : typedef std::weak_ptr<QuadVfx> QuadVfxWeak;
54 : :
55 : : class QuadVfx {
56 : : private:
57 : : QuadVfxWeak m_This;
58 : : std::string m_Name;
59 : : QuadMeshWeak m_QuadMesh;
60 : : ShaderWeak m_VertShader;
61 : : FBOPipeLinePtr m_FBOPipeLinePtr = nullptr;
62 : : ShaderPtr m_FragShaderPtr = nullptr;
63 : : ProgramPtr 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 QuadVfxPtr createFromFile( //
72 : : const std::string& vName, //
73 : : ShaderWeak 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<QuadVfx>();
82 : 0 : res->m_This = res;
83 : 0 : if (!res->initFromFile(vName, vVertShader, vQuadMesh, vFragFile, vSx, vSy, vCountBuffers, vUseMipMapping, vMultiPass)) {
84 : 0 : res.reset();
85 : 0 : }
86 : 0 : return res;
87 : 0 : }
88 : : static QuadVfxPtr createFromCode( //
89 : : const std::string& vName, //
90 : : ShaderWeak vVertShader, //
91 : : QuadMeshWeak vQuadMesh, //
92 : : const std::string& vFragCode, //
93 : : const GLsizei& vSx, //
94 : : const GLsizei& vSy, //
95 : : const uint32_t& vCountBuffers, //
96 : : const bool vUseMipMapping, //
97 : 0 : const bool vMultiPass) { //
98 : 0 : auto res = std::make_shared<QuadVfx>();
99 : 0 : res->m_This = res;
100 : 0 : if (!res->initFromCode(vName, vVertShader, vQuadMesh, vFragCode, vSx, vSy, vCountBuffers, vUseMipMapping, vMultiPass)) {
101 : 0 : res.reset();
102 : 0 : }
103 : 0 : return res;
104 : 0 : }
105 : :
106 : : public:
107 : : QuadVfx() = default;
108 : 0 : ~QuadVfx() { unit(); }
109 : : bool initFromFile( //
110 : : const std::string& vName, //
111 : : ShaderWeak vVertShader, //
112 : : QuadMeshWeak vQuadMesh, //
113 : : const std::string& vFragFile, //
114 : : const GLsizei& vSx, //
115 : : const GLsizei& vSy, //
116 : : const uint32_t& vCountBuffers, //
117 : : const bool vUseMipMapping, //
118 : 0 : const bool vMultiPass) { //
119 : 0 : assert(!vVertShader.expired());
120 : 0 : assert(!vQuadMesh.expired());
121 : 0 : assert(!vFragFile.empty());
122 : 0 : assert(vSx > 0);
123 : 0 : assert(vSy > 0);
124 : 0 : assert(vCountBuffers > 0U);
125 : 0 : m_Name = vName;
126 : 0 : m_VertShader = vVertShader;
127 : 0 : m_QuadMesh = vQuadMesh;
128 : 0 : m_Size[0] = vSx;
129 : 0 : m_Size[1] = vSy;
130 : 0 : m_UseMipMapping = vUseMipMapping;
131 : 0 : m_MultiPass = vMultiPass;
132 : 0 : m_FBOPipeLinePtr = FBOPipeLine::create(vSx, vSy, vCountBuffers, vUseMipMapping, m_MultiPass);
133 : 0 : if (m_FBOPipeLinePtr != nullptr) {
134 : 0 : m_FragShaderPtr = ez::gl::Shader::createFromFile(vName, GL_FRAGMENT_SHADER, vFragFile);
135 : 0 : if (m_FragShaderPtr != nullptr) {
136 : 0 : m_ProgramPtr = ez::gl::Program::create(vName);
137 : 0 : if (m_ProgramPtr != nullptr) {
138 : 0 : if (m_ProgramPtr->addShader(m_VertShader)) {
139 : 0 : if (m_ProgramPtr->addShader(m_FragShaderPtr)) {
140 : 0 : return m_ProgramPtr->link();
141 : 0 : }
142 : 0 : }
143 : 0 : }
144 : 0 : }
145 : 0 : }
146 : 0 : return false;
147 : 0 : }
148 : : bool initFromCode( //
149 : : const std::string& vName, //
150 : : ShaderWeak vVertShader, //
151 : : QuadMeshWeak vQuadMesh, //
152 : : const std::string& vFragCode, //
153 : : const GLsizei& vSx, //
154 : : const GLsizei& vSy, //
155 : : const uint32_t& vCountBuffers, //
156 : : const bool vUseMipMapping, //
157 : 0 : const bool vMultiPass) { //
158 : 0 : assert(!vVertShader.expired());
159 : 0 : assert(!vQuadMesh.expired());
160 : 0 : assert(!vFragCode.empty());
161 : 0 : assert(vSx > 0);
162 : 0 : assert(vSy > 0);
163 : 0 : assert(vCountBuffers > 0U);
164 : 0 : m_Name = vName;
165 : 0 : m_VertShader = vVertShader;
166 : 0 : m_QuadMesh = vQuadMesh;
167 : 0 : m_Size[0] = vSx;
168 : 0 : m_Size[1] = vSy;
169 : 0 : m_UseMipMapping = vUseMipMapping;
170 : 0 : m_MultiPass = vMultiPass;
171 : 0 : m_FBOPipeLinePtr = FBOPipeLine::create(vSx, vSy, vCountBuffers, vUseMipMapping, m_MultiPass);
172 : 0 : if (m_FBOPipeLinePtr != nullptr) {
173 : 0 : m_FragShaderPtr = ez::gl::Shader::createFromCode(vName, GL_FRAGMENT_SHADER, vFragCode);
174 : 0 : if (m_FragShaderPtr != nullptr) {
175 : 0 : m_ProgramPtr = ez::gl::Program::create(vName);
176 : 0 : if (m_ProgramPtr != nullptr) {
177 : 0 : if (m_ProgramPtr->addShader(m_VertShader)) {
178 : 0 : if (m_ProgramPtr->addShader(m_FragShaderPtr)) {
179 : 0 : return m_ProgramPtr->link();
180 : 0 : }
181 : 0 : }
182 : 0 : }
183 : 0 : }
184 : 0 : }
185 : 0 : return false;
186 : 0 : }
187 : 0 : ProgramWeak getProgram() { return m_ProgramPtr; }
188 : 0 : const char* getLabelName() { return m_Name.c_str(); }
189 : 0 : const std::array<GLuint, 2U>& getSize() { return m_Size; }
190 : 0 : void setRenderingIterations(const GLuint vRenderingIterations) { m_RenderIterations = vRenderingIterations; }
191 : 0 : GLuint& getRenderingIterationsRef() { return m_RenderIterations; }
192 : 0 : void setRenderingPause(const bool vRenderingPause) { m_RenderingPause = vRenderingPause; }
193 : 0 : bool& getRenderingPauseRef() { return m_RenderingPause; }
194 : 0 : void setUniformPreUploadFunctor(Program::UniformPreUploadFunctor vUniformPreUploadFunctor) {
195 : 0 : assert(m_ProgramPtr != nullptr);
196 : 0 : m_ProgramPtr->setUniformPreUploadFunctor(vUniformPreUploadFunctor);
197 : 0 : }
198 : 0 : void addBufferBlock(const GLenum vShaderType, const std::string& vBufferName, const int32_t vBinding, BufferBlock** vBufferPtr) {
199 : 0 : assert(m_ProgramPtr != nullptr);
200 : 0 : m_ProgramPtr->addBufferBlock(vShaderType, vBufferName, vBinding, vBufferPtr);
201 : 0 : }
202 : : void addUniformFloat(
203 : : const GLenum vShaderType,
204 : : const std::string& vUniformName,
205 : : float* vUniformPtr,
206 : : const GLuint vCountChannels,
207 : : const GLuint vCountElements = 1U,
208 : : const bool vShowWidget = true,
209 : 0 : const Program::UniformWidgetFunctor& vWidgetFunctor = nullptr) {
210 : 0 : assert(m_ProgramPtr != nullptr);
211 : 0 : m_ProgramPtr->addUniformFloat(vShaderType, vUniformName, vUniformPtr, vCountChannels, vCountElements, vShowWidget, vWidgetFunctor);
212 : 0 : }
213 : 0 : void setUniformFloatDatas(const GLenum vShaderType, const std::string& vUniformName, float* vUniformPtr) {
214 : 0 : assert(m_ProgramPtr != nullptr);
215 : 0 : m_ProgramPtr->setUniformFloatDatas(vShaderType, vUniformName, vUniformPtr);
216 : 0 : }
217 : : void addUniformInt(
218 : : const GLenum vShaderType,
219 : : const std::string& vUniformName,
220 : : int32_t* vUniformPtr,
221 : : const GLuint vCountChannels,
222 : : const GLuint vCountElements = 1U,
223 : : const bool vShowWidget = true,
224 : 0 : const Program::UniformWidgetFunctor& vWidgetFunctor = nullptr) {
225 : 0 : assert(m_ProgramPtr != nullptr);
226 : 0 : m_ProgramPtr->addUniformInt(vShaderType, vUniformName, vUniformPtr, vCountChannels, vCountElements, vShowWidget, vWidgetFunctor);
227 : 0 : }
228 : 0 : void setUniformIntDatas(const GLenum vShaderType, const std::string& vUniformName, int32_t* vUniformPtr) {
229 : 0 : assert(m_ProgramPtr != nullptr);
230 : 0 : m_ProgramPtr->setUniformIntDatas(vShaderType, vUniformName, vUniformPtr);
231 : 0 : }
232 : : void addUniformUInt(
233 : : const GLenum vShaderType,
234 : : const std::string& vUniformName,
235 : : uint32_t* vUniformPtr,
236 : : const GLuint vCountChannels,
237 : : const GLuint vCountElements = 1U,
238 : : const bool vShowWidget = true,
239 : 0 : const Program::UniformWidgetFunctor& vWidgetFunctor = nullptr) {
240 : 0 : assert(m_ProgramPtr != nullptr);
241 : 0 : m_ProgramPtr->addUniformUInt(vShaderType, vUniformName, vUniformPtr, vCountChannels, vCountElements, vShowWidget, vWidgetFunctor);
242 : 0 : }
243 : 0 : void setUniformUIntDatas(const GLenum vShaderType, const std::string& vUniformName, uint32_t* vUniformPtr) {
244 : 0 : assert(m_ProgramPtr != nullptr);
245 : 0 : m_ProgramPtr->setUniformUIntDatas(vShaderType, vUniformName, vUniformPtr);
246 : 0 : }
247 : 0 : void addUniformSampler2D(const GLenum vShaderType, const std::string& vUniformName, uint32_t* vSampler2DPtr, const bool vShowWidget = true) {
248 : 0 : assert(m_ProgramPtr != nullptr);
249 : 0 : m_ProgramPtr->addUniformSampler2D(vShaderType, vUniformName, vSampler2DPtr, vShowWidget);
250 : 0 : }
251 : 0 : void finalizeBeforeRendering() {
252 : 0 : assert(m_ProgramPtr != nullptr);
253 : 0 : m_ProgramPtr->locateUniforms();
254 : 0 : }
255 : 0 : bool resize(const GLsizei& vSx, const GLsizei vSy) {
256 : 0 : assert(m_FBOPipeLinePtr != nullptr);
257 : 0 : if (m_FBOPipeLinePtr->resize(vSx, vSy)) {
258 : 0 : m_Size[0] = vSx;
259 : 0 : m_Size[1] = vSy;
260 : 0 : return true;
261 : 0 : }
262 : 0 : return false;
263 : 0 : }
264 : 0 : void clearBuffers(const std::array<float, 4U>& vColor) {
265 : 0 : assert(m_FBOPipeLinePtr != nullptr);
266 : 0 : m_FBOPipeLinePtr->clearBuffer(vColor);
267 : 0 : }
268 : 0 : void render(const ez::fvec2& vPos = {}) {
269 : 0 : if (m_RenderingPause) {
270 : 0 : return;
271 : 0 : }
272 : 0 : #ifdef PROFILER_SCOPED
273 : 0 : auto name_c_str = m_Name.c_str(); // remvoe some warnings
274 : 0 : PROFILER_SCOPED("VFX", "Render %s", name_c_str);
275 : 0 : #endif
276 : 0 : auto quad_ptr = m_QuadMesh.lock();
277 : 0 : assert(quad_ptr != nullptr);
278 : 0 : assert(m_FBOPipeLinePtr != nullptr);
279 : 0 : assert(m_ProgramPtr != nullptr);
280 : 0 : for (GLuint idx = 0; idx < m_RenderIterations; ++idx) {
281 : 0 : #ifdef PROFILER_SCOPED
282 : 0 : PROFILER_SCOPED("VFX", "Iter %i", idx);
283 : 0 : #endif
284 : 0 : if (m_FBOPipeLinePtr->bind()) {
285 : 0 : if (m_ProgramPtr->use()) {
286 : 0 : m_ProgramPtr->uploadUniforms(m_FBOPipeLinePtr);
287 : 0 : m_FBOPipeLinePtr->selectBuffers();
288 : 0 : {
289 : 0 : #ifdef PROFILER_SCOPED
290 : 0 : PROFILER_SCOPED("Opengl", "glViewport");
291 : 0 : #endif
292 : 0 : glViewport(vPos.x, vPos.y, m_Size[0], m_Size[1]);
293 : 0 : }
294 : 0 : quad_ptr->render(GL_TRIANGLES);
295 : 0 : m_ProgramPtr->unuse();
296 : 0 : }
297 : 0 : m_FBOPipeLinePtr->updateMipMaping();
298 : 0 : m_FBOPipeLinePtr->unbind();
299 : 0 : }
300 : 0 : }
301 : 0 : }
302 : 0 : GLuint getTextureId(const size_t& vBufferIdx = 0U) {
303 : 0 : assert(m_FBOPipeLinePtr != nullptr);
304 : 0 : auto front_fbo_ptr = m_FBOPipeLinePtr->getFrontFBO().lock();
305 : 0 : if (front_fbo_ptr != nullptr) {
306 : 0 : return front_fbo_ptr->getTextureId(vBufferIdx);
307 : 0 : }
308 : 0 : return 0U;
309 : 0 : }
310 : 0 : FBOWeak getFrontFBO() {
311 : 0 : assert(m_FBOPipeLinePtr != nullptr);
312 : 0 : return m_FBOPipeLinePtr->getFrontFBO();
313 : 0 : }
314 : :
315 : : #ifdef IMGUI_INCLUDE
316 : : bool drawImGuiThumbnail(const float& vSx, const float& vSy, const float& vScaleInv, const bool vUseButton) {
317 : : assert(m_FBOPipeLinePtr != nullptr);
318 : : auto front_fbo_ptr = m_FBOPipeLinePtr->getFrontFBO().lock();
319 : : if (front_fbo_ptr != nullptr) {
320 : : const auto texId = front_fbo_ptr->getTextureId();
321 : : if (texId > 0U) {
322 : : if (vUseButton) {
323 : : return ImGui::ImageButton(m_Name.c_str(), (ImTextureID)(size_t)texId, ImVec2(vSx, vSy), ImVec2(0, vScaleInv), ImVec2(vScaleInv, 0));
324 : : } else {
325 : : ImGui::Image((ImTextureID)(size_t)texId, ImVec2(vSx, vSy), ImVec2(0, vScaleInv), ImVec2(vScaleInv, 0));
326 : : }
327 : : }
328 : : }
329 : : return false;
330 : : }
331 : : void drawUniformWidgets() {
332 : : assert(m_ProgramPtr != nullptr);
333 : : m_ProgramPtr->drawUniformWidgets();
334 : : }
335 : : #endif
336 : 0 : void unit() {
337 : 0 : m_ProgramPtr.reset();
338 : 0 : m_FragShaderPtr.reset();
339 : 0 : m_FBOPipeLinePtr.reset();
340 : 0 : }
341 : : };
342 : :
343 : : } // namespace gl
344 : : } // namespace ez
|