Skip to main content

OpenGLShader.ixx File

OpenGL implementation of shader program management. More...

Included Headers

#include <cassert> #include <format> #include <glad/gl.h> #include <helios/helios_config.h> #include <optional> #include <stdexcept> #include <string> #include <helios.rendering.shader.UniformValueMap> #include <helios.ext.opengl.rendering.shader.OpenGLUniformLocationMap> #include <helios.rendering.shader.UniformSemantics> #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

classOpenGLShader

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

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.