Skip to content

Commit e4ca7d0

Browse files
committed
Update shader code to be correct #209
1 parent 7329fe6 commit e4ca7d0

File tree

3 files changed

+139
-91
lines changed

3 files changed

+139
-91
lines changed

CMakeLists.txt

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,8 @@ function (include_dirs target)
3434
)
3535
endfunction(include_dirs)
3636

37-
function (link_exe target)
38-
target_link_libraries(${target}
39-
ob-common
40-
ob-client
41-
ob-server
42-
glad
43-
enet
44-
${CMAKE_DL_LIBS}
45-
)
46-
endfunction(link_exe)
47-
48-
4937
find_package(glm CONFIG REQUIRED)
50-
find_package(lua CONFIG REQUIRED)
38+
find_package(lua REQUIRED)
5139
find_package(SFML COMPONENTS system audio network window graphics CONFIG REQUIRED)
5240
find_package(imgui CONFIG REQUIRED)
5341

@@ -66,6 +54,8 @@ add_executable(${PROJECT_NAME}
6654
target_include_directories(${PROJECT_NAME}
6755
PRIVATE
6856
${CMAKE_CURRENT_SOURCE_DIR}/src/server/
57+
${LUA_INCLUDE_DIR}
58+
6959
)
7060

7161
target_include_directories(ob-common
@@ -104,6 +94,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
10494
glm::glm
10595
# imgui_sfml
10696
glad
97+
${LUA_LIBRARIES}
10798
)
10899

109100
target_include_directories(ob-client

src/client/gl/shader.cpp

Lines changed: 118 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,81 +5,83 @@
55

66
#include <iostream>
77

8-
namespace {
9-
class shader_compilation_error : public std::runtime_error {
10-
public:
11-
shader_compilation_error(const std::string& err)
12-
: std::runtime_error(err)
13-
{
14-
}
15-
};
16-
class shader_linkage_error : public std::runtime_error {
17-
public:
18-
shader_linkage_error(const std::string& err)
19-
: std::runtime_error(err)
20-
{
21-
}
22-
};
23-
GLuint compileShader(const std::string_view source, GLenum shaderType)
8+
namespace
9+
{
10+
enum class IVParameter
2411
{
25-
auto shaderID = glCheck(glCreateShader(shaderType));
26-
27-
const GLchar* const shaderSourcePtr = source.data();
28-
const GLint shaderSourceLength = source.length();
29-
glCheck(glShaderSource(shaderID, 1, &shaderSourcePtr, &shaderSourceLength));
30-
glCheck(glCompileShader(shaderID));
31-
32-
GLint logLength;
12+
CompileStatus = GL_COMPILE_STATUS,
13+
LinkStatus = GL_LINK_STATUS
14+
};
3315

34-
glCheck(glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength));
35-
if (logLength) {
36-
std::string infoLog(logLength, 0);
37-
glCheck(glGetShaderInfoLog(shaderID, logLength, nullptr, infoLog.data()));
16+
[[nodiscard]] constexpr auto to_string(IVParameter param)
17+
{
18+
switch (param)
19+
{
20+
case IVParameter::CompileStatus:
21+
return "compile";
3822

39-
throw shader_compilation_error(infoLog);
23+
case IVParameter::LinkStatus:
24+
return "link";
4025
}
41-
42-
return shaderID;
26+
return "ShouldNeverGetHere";
4327
}
4428

45-
GLuint linkProgram(GLuint vertexShaderID, GLuint fragmentShaderID)
29+
template <IVParameter parameter>
30+
[[nodiscard]] auto verify_shader(GLuint shader)
4631
{
47-
auto id = glCheck(glCreateProgram());
48-
49-
glCheck(glAttachShader(id, vertexShaderID));
50-
glCheck(glAttachShader(id, fragmentShaderID));
51-
52-
glCheck(glLinkProgram(id));
53-
54-
glCheck(glDetachShader(id, fragmentShaderID));
55-
glCheck(glDetachShader(id, vertexShaderID));
56-
57-
GLint logLength;
58-
59-
glCheck(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &logLength));
60-
if (logLength) {
61-
std::string infoLog(logLength, 0);
62-
glCheck(glGetProgramInfoLog(id, logLength, nullptr, infoLog.data()));
63-
throw shader_linkage_error(infoLog);
32+
// Verify
33+
GLint status = 0;
34+
if constexpr (parameter == IVParameter::CompileStatus)
35+
{
36+
glGetShaderiv(shader, static_cast<GLenum>(parameter), &status);
37+
}
38+
else if constexpr (parameter == IVParameter::LinkStatus)
39+
{
40+
glGetProgramiv(shader, static_cast<GLenum>(parameter), &status);
41+
}
42+
else
43+
{
44+
std::println(std::cerr, "Unkown verify type for action '{}'.", to_string(parameter));
6445
}
6546

66-
return id;
67-
}
68-
69-
struct ShaderStage {
70-
const GLuint shaderID;
71-
ShaderStage(const std::string_view shaderPath, const GLenum shaderType)
72-
: shaderID(compileShader(loadFileContents(shaderPath), shaderType))
47+
if (status == GL_FALSE)
7348
{
49+
GLsizei length;
50+
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
51+
52+
if constexpr (parameter == IVParameter::CompileStatus)
53+
{
54+
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
55+
}
56+
else if constexpr (parameter == IVParameter::LinkStatus)
57+
{
58+
glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &length);
59+
}
60+
std::string buffer(1024, ' ');
61+
glGetShaderInfoLog(shader, 1024, NULL, buffer.data());
62+
std::println(std::cerr, "Failed to {} shader. Error: {}", to_string(parameter), buffer);
63+
return false;
7464
}
75-
~ShaderStage()
65+
return true;
66+
}
67+
68+
[[nodiscard]] GLuint compile_shader(const char* source, GLuint shader_type)
69+
{
70+
GLuint shader = glCreateShader(shader_type);
71+
glShaderSource(shader, 1, (const GLchar* const*)&source, nullptr);
72+
glCompileShader(shader);
73+
74+
if (!verify_shader<IVParameter::CompileStatus>(shader))
7675
{
77-
glCheck(glDeleteShader(shaderID));
76+
return 0;
7877
}
79-
};
78+
return shader;
79+
}
80+
8081
} // namespace
8182

82-
namespace gl {
83+
namespace gl
84+
{
8385

8486
Shader::~Shader()
8587
{
@@ -99,29 +101,72 @@ namespace gl {
99101
return *this;
100102
}
101103

102-
void Shader::create(const std::string_view vertexFile,
103-
const std::string_view fragmentFile)
104+
bool Shader::create(const std::string_view vertexFile, const std::string_view fragmentFile)
104105
{
105106
glCheck(glUseProgram(0));
106107
const std::string vertFileFull("assets/shaders/" + std::string(vertexFile) +
107108
"_vertex.glsl");
108109
const std::string fragFileFull("assets/shaders/" + std::string(fragmentFile) +
109110
"_fragment.glsl");
110111

111-
try {
112-
const ShaderStage vertexShader(vertFileFull, GL_VERTEX_SHADER);
113-
const ShaderStage fragmentShader(fragFileFull, GL_FRAGMENT_SHADER);
114-
m_handle = linkProgram(vertexShader.shaderID, fragmentShader.shaderID);
112+
return loadStage(vertFileFull, ShaderType::Vertex) &&
113+
loadStage(fragFileFull, ShaderType::Fragment) && linkStages();
114+
}
115+
116+
bool Shader::loadStage(const std::string_view file_path, ShaderType shader_type)
117+
{
118+
// Load the files into strings and verify
119+
auto source = loadFileContents(file_path);
120+
if (source.length() == 0)
121+
{
122+
return false;
123+
}
124+
125+
GLuint shader = compile_shader(source.c_str(), static_cast<GLenum>(shader_type));
126+
if (!shader)
127+
{
128+
return false;
129+
}
130+
m_stages.push_back(shader);
131+
132+
return true;
133+
}
134+
135+
bool Shader::linkStages()
136+
{
137+
// Link the shaders together and verify the link status
138+
m_handle = glCreateProgram();
139+
for (auto stage : m_stages)
140+
{
141+
glAttachShader(m_handle, stage);
115142
}
116-
catch (const shader_compilation_error& e) {
117-
throw std::runtime_error("Shader " + vertFileFull + " failed to compile:\n" +
118-
e.what());
143+
glLinkProgram(m_handle);
144+
145+
if (!verify_shader<IVParameter::LinkStatus>(m_handle))
146+
{
147+
std::println(std::cerr, "Failed to link shader.");
148+
149+
return false;
119150
}
120-
catch (const shader_linkage_error& e) {
121-
throw std::runtime_error("Linking failed for shaders " + vertFileFull +
122-
" and " + fragFileFull + ", with reason:\n" +
123-
e.what());
151+
glValidateProgram(m_handle);
152+
153+
int status = 0;
154+
glGetProgramiv(m_handle, GL_VALIDATE_STATUS, &status);
155+
if (status == GL_FALSE)
156+
{
157+
std::println(std::cerr, "Failed to validate shader program.");
158+
return false;
159+
}
160+
161+
// Delete the temporary shaders
162+
for (auto& shader : m_stages)
163+
{
164+
glDeleteShader(shader);
124165
}
166+
m_stages.clear();
167+
m_stages.shrink_to_fit();
168+
169+
return true;
125170
}
126171

127172
void Shader::destroy()

src/client/gl/shader.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,33 @@
22

33
#include <glad/glad.h>
44
#include <string>
5+
#include <vector>
56
#include <string_view>
67

78
#include <glm/gtc/matrix_transform.hpp>
89
#include <glm/gtc/type_ptr.hpp>
910

10-
namespace gl {
11+
namespace gl
12+
{
1113
/**
1214
* @brief A uniform location in a shader
1315
*/
14-
struct UniformLocation final {
16+
struct UniformLocation final
17+
{
1518
GLuint ptr = 0;
1619
};
1720

1821
/**
1922
* @brief Wrapper for a OpenGL shder object
2023
*/
21-
class Shader final {
24+
class Shader final
25+
{
26+
enum class ShaderType
27+
{
28+
Vertex = GL_VERTEX_SHADER,
29+
Fragment = GL_FRAGMENT_SHADER,
30+
};
31+
2232
public:
2333
Shader() = default;
2434
~Shader();
@@ -29,15 +39,17 @@ namespace gl {
2939
Shader(const Shader&) = delete;
3040
Shader& operator=(const Shader&) = delete;
3141

32-
void create(const std::string_view vertexFile,
33-
const std::string_view fragmentFile);
42+
bool create(const std::string_view vertexFile, const std::string_view fragmentFile);
3443
void destroy();
3544
void bind() const;
3645

3746
UniformLocation getUniformLocation(const char* name);
3847

3948
private:
49+
bool loadStage(const std::string_view file, ShaderType shader_type);
50+
bool linkStages();
4051
GLuint m_handle = 0;
52+
std::vector<GLuint> m_stages;
4153
};
4254

4355
// Functons for shaders

0 commit comments

Comments
 (0)