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