Skip to main content

LegacyOpenGLShader.ixx File

OpenGL implementation of shader program management. More...

Included Headers

#include <glad/gl.h> #include <format> #include <stdexcept> #include <string> #include <helios/helios_config.h> #include <helios.rendering.shader.UniformSemantics> #include <helios.rendering.shader.UniformValueMap> #include <helios.ext.opengl.rendering.shader.OpenGLUniformLocationMap> #include <helios.util.io.StringFileReader> #include <helios.rendering.shader.Shader>

Namespaces Index

namespacehelios
namespaceext

Platform-specific extensions and backend implementations. More...

namespaceopengl

OpenGL-specific implementations. More...

namespacerendering

OpenGL rendering implementations. More...

namespaceshader

OpenGL shader implementations. More...

Classes Index

classLegacyOpenGLShader

An OpenGL-specific implementation of a Shader program, consisting of a vertex and a fragment shader. More...

Description

OpenGL implementation of shader program management.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file LegacyOpenGLShader.ixx
3 * @brief OpenGL implementation of shader program management.
4 */
5module;
6
7#include <glad/gl.h>
8#include <format>
9#include <stdexcept>
10#include <string>
11#include <helios/helios_config.h>
12
13export module helios.ext.opengl.rendering.shader.LegacyOpenGLShader;
14
15import helios.rendering.shader.Shader;
16
17import helios.util.io.StringFileReader;
18import helios.ext.opengl.rendering.shader.OpenGLUniformLocationMap;
19import helios.rendering.shader.UniformSemantics;
20import helios.rendering.shader.UniformValueMap;
21
22
24
25 /**
26 * @brief An OpenGL-specific implementation of a Shader program,
27 * consisting of a vertex and a fragment shader.
28 *
29 * This class manages the lifecycle of the Shaders. Source files are
30 * getting loaded via a StringFileReader and immediately compiled after loading.
31 * Any occupied memory for source-files and file-paths to the shader is being cleared
32 * once compilation succeeded and are not guaranteed to persist the compilation process.
33 *
34 * @deprecated use OpenGLShader
35 */
37
38 private:
39 /**
40 * @brief Source of the shader. Not guaranteed to be persisted
41 * once compilation was successful.
42 */
43 std::string vertexShaderSource_;
44
45
46 /**
47 * @brief Source of the shader. Not guaranteed to be persisted
48 * once compilation was successful.
49 */
50 std::string fragmentShaderSource_;
51
52 /**
53 * @brief Loads the specified vertex and fragment shader.
54 *
55 * @return true if loading succeeded, otherwise false.
56 *
57 * @throws if loading the specified files failed.
58 */
59 void load(
60 const std::string& vertexShaderPath,
61 const std::string& fragmentShaderPath,
62 const helios::util::io::StringFileReader& stringFileReader
63 ) {
64 logger_.info(std::format("Loading shader from {0}, {1}", vertexShaderPath, fragmentShaderPath));
65 if (!stringFileReader.readInto(fragmentShaderPath, fragmentShaderSource_) ||
66 !stringFileReader.readInto(vertexShaderPath, vertexShaderSource_)) {
67 logger_.error("Could not load shader");
68 throw std::runtime_error("Could not load shader");
69 }
70 }
71
72
73 /**
74 * @brief Compiles the vertex and fragment shader represented by this instance.
75 *
76 * @return true if compilation succeeded, otherwise false.
77 *
78 * @throws if compilation failed.
79 */
80 void compile() {
81 if (progId_ != 0) {
82 logger_.warn("Shader already compiled");
83 return;
84 }
85
86 const GLchar* vertexSrc = vertexShaderSource_.c_str();
87 const GLchar* fragmentSrc = fragmentShaderSource_.c_str();
88
89 const unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
90 glShaderSource(vertexShader, 1, &vertexSrc, nullptr);
91 glCompileShader(vertexShader);
92
93 const unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
94 glShaderSource(fragmentShader, 1, &fragmentSrc, nullptr);
95 glCompileShader(fragmentShader);
96
97
98 int success;
99 char infoLog[512];
100 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
101
102 if (!success) {
103 glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
104
105 logger_.error("VERTEX::COMPILATION_FAILED " + static_cast<std::string>(infoLog));
106 throw std::runtime_error("Vertex Shader Compilation failed.");
107 }
108
109 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
110 if (!success) {
111 glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
112 logger_.error("SHADER::FRAGMENT::COMPILATION_FAILED " + static_cast<std::string>(infoLog));
113 throw std::runtime_error("Fragment Shader Compilation failed.");
114 }
115
116 progId_ = glCreateProgram();
117
118 glAttachShader(progId_, vertexShader);
119 glAttachShader(progId_, fragmentShader);
120 glLinkProgram(progId_);
121
122 glGetProgramiv(progId_, GL_LINK_STATUS, &success);
123 if (!success) {
124 glGetProgramInfoLog(progId_, 512, nullptr, infoLog);
125 logger_.error("PROGRAM_LINKING_FAILED " + static_cast<std::string>(infoLog));
126 throw std::runtime_error("Program linking failed.");
127 }
128
129 glDeleteShader(vertexShader);
130 glDeleteShader(fragmentShader);
131
132 vertexShaderSource_.clear();
133 vertexShaderSource_.shrink_to_fit();
134 fragmentShaderSource_.clear();
135 fragmentShaderSource_.shrink_to_fit();
136
137 logger_.info("Shader loaded and linked");
138 }
139
140
141 protected:
142 /**
143 * @brief The program id as assigned by the underlying rendering backend.
144 */
145 unsigned int progId_ = 0;
146
147 /**
148 * @brief A unique pointer to the OpenGLUniformLocationMap this shader uses.
149 */
150 std::unique_ptr<const OpenGLUniformLocationMap> uniformLocationMap_ = nullptr;
151
152 public:
153 /**
154 * @brief Rule of three.
155 * @see https://wikis.khronos.org/opengl/Common_Mistakes#RAII_and_hidden_destructor_calls
156 * @see https://en.cppreference.com/w/cpp/language/rule_of_three.html
157 *
158 * Prevent copying.
159 */
162
163
164 /**
165 * @brief Creates and initializes this LegacyOpenGLShader.
166 * An instance of this class is guaranteed to have a progId_ != 0,
167 * hence shader-files where successfully loaded and compiled, ready to be used.
168 *
169 * @param vertexShaderPath The path to the vertex shader.
170 * @param fragmentShaderPath The path to the fragment shader.
171 * @param stringFileReader The StringFileReader used for loading the shader source files.
172 *
173 * @throws if creating this shader failed.
174 */
176 const std::string& vertexShaderPath,
177 const std::string& fragmentShaderPath,
178 const helios::util::io::StringFileReader& stringFileReader
179 ) {
180 try {
181 load(vertexShaderPath, fragmentShaderPath, stringFileReader);
182 compile();
183 } catch (std::runtime_error& e) {
184 logger_.error("Could not initialize shader");
185 throw std::runtime_error("Could not initialize shader");
186 }
187 }
188
189
190 /**
191 * @brief Activates this LegacyOpenGLShader for subsequent draw calls.
192 * This implementation calls `glUseProgram` with the `progId_` received after
193 * compilation.
194 *
195 * @see https://registry.khronos.org/OpenGL-Refpages/gl4/html/glUseProgram.xhtml
196 */
197 void use() const noexcept override {
198 if (!progId_) {
199 logger_.error("Cannot use shader, progId_ is invalid");
200 }
201 glUseProgram(progId_);
202 }
203
204 /**
205 * @brief Deletes the program object upon destruction of this instance.
206 *
207 * @see https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDeleteProgram.xhtml
208 */
210 if (progId_ != 0) {
211 glDeleteProgram(progId_);
212 }
213 }
214
215 /**
216 * @brief Sets the OpenGLUniformLocationMap for this LegacyOpenGLShader.
217 * Ownership is transferred to this instance.
218 *
219 * @param uniformLocationMap The OpenGLUniformMap providing the mappings for the uniforms
220 * of the underlying GLSL shader.
221 */
223 std::unique_ptr<const OpenGLUniformLocationMap> uniformLocationMap) noexcept {
224 uniformLocationMap_ = std::move(uniformLocationMap);
225 }
226
227 /**
228 * @brief Returns the uniform location for the uniform represented by the specified
229 * UniformSemantics.
230 *
231 * @param uniformSemantics The `UniformSemantics` identifier.
232 *
233 * @return The integer representing the uniform variable location in the shader, or
234 * -1 if no location map was registered with this shader or if the uniform with the
235 * specified semantics was not found.
236 */
237 [[nodiscard]] int uniformLocation(
238 helios::rendering::shader::UniformSemantics uniformSemantics) const noexcept {
240 return uniformLocationMap_->get(uniformSemantics);
241 }
242
243 return -1;
244 }
245
246 /**
247 * @copydoc helios::rendering::shader::Shader::applyUniformValues()
248 */
250 const helios::rendering::shader::UniformValueMap& uniformValueMap) const noexcept override {
251
252 if (const auto viewMatrixUniform = uniformLocation(helios::rendering::shader::UniformSemantics::ViewMatrix); viewMatrixUniform != -1) {
253 if (const auto* mat4f_ptr = uniformValueMap.mat4f_ptr(helios::rendering::shader::UniformSemantics::ViewMatrix)) {
254 glUniformMatrix4fv(viewMatrixUniform, 1, false, mat4f_ptr);
255 }
256 }
257
258 if (const auto projectionMatrixUniform = uniformLocation(helios::rendering::shader::UniformSemantics::ProjectionMatrix); projectionMatrixUniform != -1) {
259 if (const auto* mat4f_ptr = uniformValueMap.mat4f_ptr(helios::rendering::shader::UniformSemantics::ProjectionMatrix)) {
260 glUniformMatrix4fv(projectionMatrixUniform, 1, false, mat4f_ptr);
261 }
262 }
263
264 if (const auto modelMatrixUniform = uniformLocation(helios::rendering::shader::UniformSemantics::ModelMatrix); modelMatrixUniform != -1) {
265 if (const auto* mat4f_ptr = uniformValueMap.mat4f_ptr(helios::rendering::shader::UniformSemantics::ModelMatrix)) {
266 glUniformMatrix4fv(modelMatrixUniform, 1, false, mat4f_ptr);
267 }
268 }
269 if (const auto materialBaseColorUniform = uniformLocation(helios::rendering::shader::UniformSemantics::MaterialBaseColor); materialBaseColorUniform != -1) {
270 if (const auto* vec4f_ptr = uniformValueMap.vec4f_ptr(helios::rendering::shader::UniformSemantics::MaterialBaseColor)) {
271 glUniform4fv(materialBaseColorUniform, 1, vec4f_ptr);
272 }
273 }
274
275 // texture
276 if (const auto textColorUniform = uniformLocation(helios::rendering::shader::UniformSemantics::TextColor); textColorUniform != -1) {
277 if (const auto* vec4f_ptr = uniformValueMap.vec4f_ptr(helios::rendering::shader::UniformSemantics::TextColor)) {
278 glUniform4fv(textColorUniform, 1, vec4f_ptr);
279 }
280 }
281 if (const auto textTextureUniform = uniformLocation(helios::rendering::shader::UniformSemantics::TextTexture); textTextureUniform != -1) {
282 if (const auto* int_ptr = uniformValueMap.int_ptr(helios::rendering::shader::UniformSemantics::TextTexture)) {
283 glUniform1i(textTextureUniform, *int_ptr);
284 }
285 }
286 }
287
288 };
289}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.