diff options
| author | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
|---|---|---|
| committer | Ethan Morgan <ethan@gweithio.com> | 2026-02-14 16:44:06 +0000 |
| commit | 54409423f767d8b1cf30cb7d0efca6b4ca138823 (patch) | |
| tree | d915ac7828703ce4b963efdd9728a1777ba18c1e /apps/openmb/renderer/Shader.cpp | |
Diffstat (limited to 'apps/openmb/renderer/Shader.cpp')
| -rw-r--r-- | apps/openmb/renderer/Shader.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/apps/openmb/renderer/Shader.cpp b/apps/openmb/renderer/Shader.cpp new file mode 100644 index 0000000..a7c94e6 --- /dev/null +++ b/apps/openmb/renderer/Shader.cpp @@ -0,0 +1,137 @@ +#include "Shader.hpp" + +#define GLFW_INCLUDE_NONE +#include <GLFW/glfw3.h> +#ifdef __APPLE__ +#include <OpenGL/gl3.h> +#endif +#include <fstream> +#include <iostream> +#include <sstream> + +namespace renderer { +Shader::Shader () : mID( 0 ) {} + +Shader::~Shader () { + if( mID ) { + glDeleteProgram( mID ); + } +} + +bool Shader::fromSource ( const std::string& vertexSrc, const std::string& fragmentSrc ) { + return compileShader( vertexSrc.c_str(), fragmentSrc.c_str() ); +} + +bool Shader::fromFiles ( const std::string& vertexPath, const std::string& fragmentPath ) { + std::string vs = readFile( vertexPath ); + std::string fs = readFile( fragmentPath ); + if( vs.empty() || fs.empty() ) { + return false; + } + return compileShader( vs.c_str(), fs.c_str() ); +} + +void Shader::use () const { + glUseProgram( mID ); +} + +unsigned int Shader::id () const { + return mID; +} + +void Shader::setInt ( const std::string& name, int value ) const { + glUniform1i( glGetUniformLocation( mID, name.c_str() ), value ); +} + +void Shader::setFloat ( const std::string& name, float value ) const { + glUniform1f( glGetUniformLocation( mID, name.c_str() ), value ); +} + +void Shader::setVec3 ( const std::string& name, const glm::vec3& v ) const { + glUniform3f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y, v.z ); +} + +void Shader::setVec2 ( const std::string& name, const glm::vec2& v ) const { + glUniform2f( glGetUniformLocation( mID, name.c_str() ), v.x, v.y ); +} + +void Shader::setMat4 ( const std::string& name, const glm::mat4& m ) const { + glUniformMatrix4fv( glGetUniformLocation( mID, name.c_str() ), 1, GL_FALSE, &m[0][0] ); +} + +bool Shader::compileShader ( const char* vSrc, const char* fSrc ) { + GLuint vert = glCreateShader( GL_VERTEX_SHADER ); + glShaderSource( vert, 1, &vSrc, nullptr ); + glCompileShader( vert ); + + GLint success = 0; + glGetShaderiv( vert, GL_COMPILE_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetShaderiv( vert, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetShaderInfoLog( vert, len, &len, &log[0] ); + std::cerr << "Vertex shader compile error:\n" + << log << std::endl; + std::cerr << "[Shader] Vertex shader ID = " << vert << std::endl; + glDeleteShader( vert ); + return false; + } + + GLuint frag = glCreateShader( GL_FRAGMENT_SHADER ); + + glShaderSource( frag, 1, &fSrc, nullptr ); + glCompileShader( frag ); + + glGetShaderiv( frag, GL_COMPILE_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetShaderiv( frag, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetShaderInfoLog( frag, len, &len, &log[0] ); + std::cerr << "Fragment shader compile error:\n" + << log << std::endl; + glDeleteShader( frag ); + glDeleteShader( vert ); + return false; + } + + mID = glCreateProgram(); + glAttachShader( mID, vert ); + glAttachShader( mID, frag ); + glLinkProgram( mID ); + + glGetProgramiv( mID, GL_LINK_STATUS, &success ); + if( success == GL_FALSE ) { + GLint len = 0; + glGetProgramiv( mID, GL_INFO_LOG_LENGTH, &len ); + std::string log( len, '\0' ); + glGetProgramInfoLog( mID, len, &len, &log[0] ); + std::cerr << "Shader link error:\n" + << log << std::endl; + glDeleteProgram( mID ); + mID = 0; + glDeleteShader( vert ); + glDeleteShader( frag ); + return false; + } + + glDetachShader( mID, vert ); + glDetachShader( mID, frag ); + glDeleteShader( vert ); + glDeleteShader( frag ); + + return true; +} + +std::string Shader::readFile ( const std::string& path ) const { + std::ifstream in( path ); + if( !in ) { + return std::string(); + } + std::stringstream ss; + ss << in.rdbuf(); + return ss.str(); +} + +} // namespace renderer |