Skip to content

Commit

Permalink
Update shader code to be correct #209
Browse files Browse the repository at this point in the history
  • Loading branch information
Hopson97 committed Jan 14, 2025
1 parent 7329fe6 commit e4ca7d0
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 91 deletions.
17 changes: 4 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,8 @@ function (include_dirs target)
)
endfunction(include_dirs)

function (link_exe target)
target_link_libraries(${target}
ob-common
ob-client
ob-server
glad
enet
${CMAKE_DL_LIBS}
)
endfunction(link_exe)


find_package(glm CONFIG REQUIRED)
find_package(lua CONFIG REQUIRED)
find_package(lua REQUIRED)
find_package(SFML COMPONENTS system audio network window graphics CONFIG REQUIRED)
find_package(imgui CONFIG REQUIRED)

Expand All @@ -66,6 +54,8 @@ add_executable(${PROJECT_NAME}
target_include_directories(${PROJECT_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/server/
${LUA_INCLUDE_DIR}

)

target_include_directories(ob-common
Expand Down Expand Up @@ -104,6 +94,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
glm::glm
# imgui_sfml
glad
${LUA_LIBRARIES}
)

target_include_directories(ob-client
Expand Down
191 changes: 118 additions & 73 deletions src/client/gl/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,81 +5,83 @@

#include <iostream>

namespace {
class shader_compilation_error : public std::runtime_error {
public:
shader_compilation_error(const std::string& err)
: std::runtime_error(err)
{
}
};
class shader_linkage_error : public std::runtime_error {
public:
shader_linkage_error(const std::string& err)
: std::runtime_error(err)
{
}
};
GLuint compileShader(const std::string_view source, GLenum shaderType)
namespace
{
enum class IVParameter
{
auto shaderID = glCheck(glCreateShader(shaderType));

const GLchar* const shaderSourcePtr = source.data();
const GLint shaderSourceLength = source.length();
glCheck(glShaderSource(shaderID, 1, &shaderSourcePtr, &shaderSourceLength));
glCheck(glCompileShader(shaderID));

GLint logLength;
CompileStatus = GL_COMPILE_STATUS,
LinkStatus = GL_LINK_STATUS
};

glCheck(glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength));
if (logLength) {
std::string infoLog(logLength, 0);
glCheck(glGetShaderInfoLog(shaderID, logLength, nullptr, infoLog.data()));
[[nodiscard]] constexpr auto to_string(IVParameter param)
{
switch (param)
{
case IVParameter::CompileStatus:
return "compile";

throw shader_compilation_error(infoLog);
case IVParameter::LinkStatus:
return "link";
}

return shaderID;
return "ShouldNeverGetHere";
}

GLuint linkProgram(GLuint vertexShaderID, GLuint fragmentShaderID)
template <IVParameter parameter>
[[nodiscard]] auto verify_shader(GLuint shader)
{
auto id = glCheck(glCreateProgram());

glCheck(glAttachShader(id, vertexShaderID));
glCheck(glAttachShader(id, fragmentShaderID));

glCheck(glLinkProgram(id));

glCheck(glDetachShader(id, fragmentShaderID));
glCheck(glDetachShader(id, vertexShaderID));

GLint logLength;

glCheck(glGetProgramiv(id, GL_INFO_LOG_LENGTH, &logLength));
if (logLength) {
std::string infoLog(logLength, 0);
glCheck(glGetProgramInfoLog(id, logLength, nullptr, infoLog.data()));
throw shader_linkage_error(infoLog);
// Verify
GLint status = 0;
if constexpr (parameter == IVParameter::CompileStatus)
{
glGetShaderiv(shader, static_cast<GLenum>(parameter), &status);
}
else if constexpr (parameter == IVParameter::LinkStatus)
{
glGetProgramiv(shader, static_cast<GLenum>(parameter), &status);
}
else
{
std::println(std::cerr, "Unkown verify type for action '{}'.", to_string(parameter));
}

return id;
}

struct ShaderStage {
const GLuint shaderID;
ShaderStage(const std::string_view shaderPath, const GLenum shaderType)
: shaderID(compileShader(loadFileContents(shaderPath), shaderType))
if (status == GL_FALSE)
{
GLsizei length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);

if constexpr (parameter == IVParameter::CompileStatus)
{
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
}
else if constexpr (parameter == IVParameter::LinkStatus)
{
glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &length);
}
std::string buffer(1024, ' ');
glGetShaderInfoLog(shader, 1024, NULL, buffer.data());
std::println(std::cerr, "Failed to {} shader. Error: {}", to_string(parameter), buffer);
return false;
}
~ShaderStage()
return true;
}

[[nodiscard]] GLuint compile_shader(const char* source, GLuint shader_type)
{
GLuint shader = glCreateShader(shader_type);
glShaderSource(shader, 1, (const GLchar* const*)&source, nullptr);
glCompileShader(shader);

if (!verify_shader<IVParameter::CompileStatus>(shader))
{
glCheck(glDeleteShader(shaderID));
return 0;
}
};
return shader;
}

} // namespace

namespace gl {
namespace gl
{

Shader::~Shader()
{
Expand All @@ -99,29 +101,72 @@ namespace gl {
return *this;
}

void Shader::create(const std::string_view vertexFile,
const std::string_view fragmentFile)
bool Shader::create(const std::string_view vertexFile, const std::string_view fragmentFile)
{
glCheck(glUseProgram(0));
const std::string vertFileFull("assets/shaders/" + std::string(vertexFile) +
"_vertex.glsl");
const std::string fragFileFull("assets/shaders/" + std::string(fragmentFile) +
"_fragment.glsl");

try {
const ShaderStage vertexShader(vertFileFull, GL_VERTEX_SHADER);
const ShaderStage fragmentShader(fragFileFull, GL_FRAGMENT_SHADER);
m_handle = linkProgram(vertexShader.shaderID, fragmentShader.shaderID);
return loadStage(vertFileFull, ShaderType::Vertex) &&
loadStage(fragFileFull, ShaderType::Fragment) && linkStages();
}

bool Shader::loadStage(const std::string_view file_path, ShaderType shader_type)
{
// Load the files into strings and verify
auto source = loadFileContents(file_path);
if (source.length() == 0)
{
return false;
}

GLuint shader = compile_shader(source.c_str(), static_cast<GLenum>(shader_type));
if (!shader)
{
return false;
}
m_stages.push_back(shader);

return true;
}

bool Shader::linkStages()
{
// Link the shaders together and verify the link status
m_handle = glCreateProgram();
for (auto stage : m_stages)
{
glAttachShader(m_handle, stage);
}
catch (const shader_compilation_error& e) {
throw std::runtime_error("Shader " + vertFileFull + " failed to compile:\n" +
e.what());
glLinkProgram(m_handle);

if (!verify_shader<IVParameter::LinkStatus>(m_handle))
{
std::println(std::cerr, "Failed to link shader.");

return false;
}
catch (const shader_linkage_error& e) {
throw std::runtime_error("Linking failed for shaders " + vertFileFull +
" and " + fragFileFull + ", with reason:\n" +
e.what());
glValidateProgram(m_handle);

int status = 0;
glGetProgramiv(m_handle, GL_VALIDATE_STATUS, &status);
if (status == GL_FALSE)
{
std::println(std::cerr, "Failed to validate shader program.");
return false;
}

// Delete the temporary shaders
for (auto& shader : m_stages)
{
glDeleteShader(shader);
}
m_stages.clear();
m_stages.shrink_to_fit();

return true;
}

void Shader::destroy()
Expand Down
22 changes: 17 additions & 5 deletions src/client/gl/shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,33 @@

#include <glad/glad.h>
#include <string>
#include <vector>
#include <string_view>

#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

namespace gl {
namespace gl
{
/**
* @brief A uniform location in a shader
*/
struct UniformLocation final {
struct UniformLocation final
{
GLuint ptr = 0;
};

/**
* @brief Wrapper for a OpenGL shder object
*/
class Shader final {
class Shader final
{
enum class ShaderType
{
Vertex = GL_VERTEX_SHADER,
Fragment = GL_FRAGMENT_SHADER,
};

public:
Shader() = default;
~Shader();
Expand All @@ -29,15 +39,17 @@ namespace gl {
Shader(const Shader&) = delete;
Shader& operator=(const Shader&) = delete;

void create(const std::string_view vertexFile,
const std::string_view fragmentFile);
bool create(const std::string_view vertexFile, const std::string_view fragmentFile);
void destroy();
void bind() const;

UniformLocation getUniformLocation(const char* name);

private:
bool loadStage(const std::string_view file, ShaderType shader_type);
bool linkStages();
GLuint m_handle = 0;
std::vector<GLuint> m_stages;
};

// Functons for shaders
Expand Down

0 comments on commit e4ca7d0

Please sign in to comment.