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 : : #include "ezGL.hpp"
31 : : #include <map>
32 : : #include <memory>
33 : : #include <string>
34 : : #include <cassert>
35 : :
36 : : namespace ez {
37 : : namespace gl {
38 : :
39 : : class ShaderAuto;
40 : : typedef std::shared_ptr<ShaderAuto> ShaderAutoPtr;
41 : : typedef std::weak_ptr<ShaderAuto> ShaderAutoWeak;
42 : :
43 : : class ShaderAuto {
44 : : private:
45 : : ShaderAutoWeak m_This;
46 : : GLuint m_ShaderId = 0U;
47 : : std::string m_ShaderName;
48 : : GLenum m_ShaderType = 0;
49 : : UniformStrings m_UniformStrings;
50 : :
51 : : public:
52 : 0 : static ShaderAutoPtr createFromFile(const std::string& vShaderName, const GLenum vShaderType, const std::string& vFile) {
53 : 0 : auto res = std::make_shared<ShaderAuto>();
54 : 0 : res->m_This = res;
55 : 0 : if (!res->initFromFile(vShaderName, vShaderType, vFile)) {
56 : 0 : res.reset();
57 : 0 : }
58 : 0 : return res;
59 : 0 : }
60 : 0 : static ShaderAutoPtr createFromCode(const std::string& vShaderName, const GLenum vShaderType, const std::string& vCode) {
61 : 0 : auto res = std::make_shared<ShaderAuto>();
62 : 0 : res->m_This = res;
63 : 0 : if (!res->initFromCode(vShaderName, vShaderType, vCode)) {
64 : 0 : res.reset();
65 : 0 : }
66 : 0 : return res;
67 : 0 : }
68 : :
69 : : public:
70 : : ShaderAuto() = default;
71 : 0 : ~ShaderAuto() {
72 : 0 : unit();
73 : 0 : }
74 : :
75 : 0 : bool initFromFile(const std::string& vShaderName, const GLenum vShaderType, const std::string& vFile) {
76 : 0 : assert(!vShaderName.empty());
77 : 0 : assert(!vFile.empty());
78 : 0 : assert(vShaderType > 0);
79 : 0 : const auto& code = getCodeFromFile(vFile);
80 : 0 : return initFromCode(vShaderName, vShaderType, code);
81 : 0 : }
82 : :
83 : 0 : bool initFromCode(const std::string& vShaderName, const GLenum vShaderType, const std::string& vCode) {
84 : 0 : bool res = false;
85 : 0 : assert(!vShaderName.empty());
86 : 0 : assert(!vCode.empty());
87 : 0 : assert(vShaderType > 0);
88 : 0 : m_ShaderName = vShaderName;
89 : 0 : m_ShaderType = vShaderType;
90 : 0 : m_ShaderId = glCreateShader((GLenum)vShaderType);
91 : 0 : CheckGLErrors;
92 : 0 : if (m_ShaderId > 0U) {
93 : 0 : const auto code = m_UniformStrings.parse_and_filter_code(vCode);
94 : 0 : const GLchar* sources = code.c_str();
95 : 0 : glShaderSource(m_ShaderId, 1U, &sources, nullptr);
96 : 0 : CheckGLErrors;
97 : 0 : glCompileShader(m_ShaderId);
98 : 0 : CheckGLErrors;
99 : 0 : glFinish();
100 : 0 : GLint compiled = 0;
101 : 0 : glGetShaderiv(m_ShaderId, GL_COMPILE_STATUS, &compiled);
102 : 0 : CheckGLErrors;
103 : 0 : if (!compiled) {
104 : 0 : printShaderLogs(vShaderName, "Errors");
105 : 0 : res = false;
106 : 0 : } else {
107 : 0 : printShaderLogs(vShaderName, "Warnings");
108 : 0 : res = true;
109 : 0 : }
110 : 0 : }
111 : 0 : return res;
112 : 0 : }
113 : 0 : void unit() {
114 : 0 : if (m_ShaderId > 0U) {
115 : 0 : glDeleteShader(m_ShaderId);
116 : 0 : CheckGLErrors;
117 : 0 : m_ShaderId = 0U;
118 : 0 : }
119 : 0 : }
120 : 0 : const std::string& getName() {
121 : 0 : return m_ShaderName;
122 : 0 : }
123 : 0 : GLuint getShaderId() {
124 : 0 : return m_ShaderId;
125 : 0 : }
126 : :
127 : : private:
128 : 0 : std::string getCodeFromFile(const std::string& vFile) {
129 : 0 : assert(!vFile.empty());
130 : 0 : std::string res;
131 : 0 : std::ifstream docFile(vFile, std::ios::in);
132 : 0 : if (docFile.is_open()) {
133 : 0 : std::stringstream strStream;
134 : 0 : strStream << docFile.rdbuf(); // read the file
135 : 0 : res = strStream.str();
136 : 0 : docFile.close();
137 : 0 : }
138 : 0 : return res;
139 : 0 : }
140 : 0 : void printShaderLogs(const std::string& vShaderName, const std::string& vLogTypes) {
141 : 0 : assert(!vShaderName.empty());
142 : 0 : assert(!vLogTypes.empty());
143 : 0 : if (m_ShaderId > 0U) {
144 : 0 : GLint infoLen = 0;
145 : 0 : glGetShaderiv(m_ShaderId, GL_INFO_LOG_LENGTH, &infoLen);
146 : 0 : CheckGLErrors;
147 : 0 : if (infoLen > 1) {
148 : 0 : char* infoLog = new char[infoLen];
149 : 0 : glGetShaderInfoLog(m_ShaderId, infoLen, nullptr, infoLog);
150 : 0 : CheckGLErrors;
151 : 0 : LogVarLightInfo("#### SHADER %s ####", vShaderName.c_str());
152 : 0 : LogVarLightInfo("%s : %s", vLogTypes.c_str(), infoLog);
153 : 0 : delete[] infoLog;
154 : 0 : }
155 : 0 : }
156 : 0 : }
157 : : };
158 : :
159 : : } // namespace gl
160 : : } // namespace ez
|