Skip to content

Instantly share code, notes, and snippets.

@untodesu
Created January 23, 2020 09:43
Show Gist options
  • Save untodesu/60e7adbdd6d2c4e19567319d88018b32 to your computer and use it in GitHub Desktop.
Save untodesu/60e7adbdd6d2c4e19567319d88018b32 to your computer and use it in GitHub Desktop.
GLSL
//-----------------------------------------------------------------------------
// /src/engine/gfx/glsl.cpp
// The GLSL Shader Helper functions & classes
//-----------------------------------------------------------------------------
#include <string> // std::string
#include <fstream> // std::ifstream
#include <sstream> // std::stringstream
#include <glm/gtc/type_ptr.hpp>
#include "gfx/glsl.h"
using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::mat4;
//-----------------------------------------------------------------------------
// CShader::CShader
// Constructor
//-----------------------------------------------------------------------------
CShader::CShader(void) : m_linked(false)
{
m_program = glCreateProgram();
}
//-----------------------------------------------------------------------------
// CShader::~CShader
// Destructor
//-----------------------------------------------------------------------------
CShader::~CShader(void)
{
glDeleteProgram(m_program);
}
//-----------------------------------------------------------------------------
// CShader::IsValid
// Shader status
//-----------------------------------------------------------------------------
bool CShader::IsValid(void) const
{
return m_linked;
}
//-----------------------------------------------------------------------------
// CShader::GetProgram
// Gets GL handle of shader
//-----------------------------------------------------------------------------
GLuint CShader::GetProgram(void) const
{
return m_program;
}
//-----------------------------------------------------------------------------
// CShader::CompileFile_V
// Compiles vertex shader
//-----------------------------------------------------------------------------
bool CShader::CompileFile_V(const char *shaderFile)
{
std::ifstream file(shaderFile, std::ios::in);
if(!file.is_open()) {
printf("CShader: Couldn't open %s\n", shaderFile);
return false;
}
// Read file to string
std::stringstream ss;
ss << file.rdbuf();
file.close();
const char *src = ss.str().c_str();
// create new shader
GLuint shader = glCreateShader(GL_VERTEX_SHADER);
// Try to compile the shader
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
// check for errors
GLint success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success) {
GLint logLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);
char *message = new char[logLen + 1];
message[logLen] = '\0';
glGetShaderInfoLog(shader, logLen, nullptr, message);
printf("CShader(%s): %s\n", shaderFile, message);
delete[] message;
glDeleteShader(shader);
return false;
}
m_vsQueue.push_back(shader);
return true;
}
//-----------------------------------------------------------------------------
// CShader::CompileFile_F
// Compiles vertex shader
//-----------------------------------------------------------------------------
bool CShader::CompileFile_F(const char *shaderFile)
{
std::ifstream file(shaderFile, std::ios::in);
if(!file.is_open()) {
printf("CShader: Couldn't open %s\n", shaderFile);
return false;
}
// Read file to string
std::stringstream ss;
ss << file.rdbuf();
file.close();
const char *src = ss.str().c_str();
// create new shader
GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
// Try to compile the shader
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
// check for errors
GLint success = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success) {
GLint logLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLen);
char *message = new char[logLen + 1];
message[logLen] = '\0';
glGetShaderInfoLog(shader, logLen, nullptr, message);
printf("CShader(%s): %s\n", shaderFile, message);
delete[] message;
glDeleteShader(shader);
return false;
}
m_fsQueue.push_back(shader);
return true;
}
//-----------------------------------------------------------------------------
// CShader::LinkProgram
// GLSL shader program link, clears shader queue, can be done once
//-----------------------------------------------------------------------------
bool CShader::LinkProgram(void)
{
if(m_linked) {
printf("CShader: Already linked!\n");
return false;
}
// Attach shaders
for(const GLuint &shader : m_vsQueue) {
glAttachShader(m_program, shader);
}
for(const GLuint &shader : m_fsQueue) {
glAttachShader(m_program, shader);
}
// Try to link the program
glLinkProgram(m_program);
bool status = true;
// Log some info
GLint success = 0;
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
if(!success) {
GLint logLen = 0;
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &logLen);
char *message = new char[logLen + 1];
message[logLen] = '\0';
glGetProgramInfoLog(m_program, logLen, nullptr, message);
printf("CShader: %s\n", message);
delete[] message;
status = false;
}
// Clear queues
for(GLuint &shader : m_vsQueue) {
glDeleteShader(shader);
shader = 0;
}
for(GLuint &shader : m_fsQueue) {
glDeleteShader(shader);
shader = 0;
}
m_vsQueue.clear();
m_fsQueue.clear();
return status;
}
//-----------------------------------------------------------------------------
// CShader::UseProgram
//
//-----------------------------------------------------------------------------
void CShader::UseProgram(void)
{
glUseProgram(m_program);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// int value, usually as sampler2D
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const int value)
{
glUniform1i(glGetUniformLocation(m_program, name), value);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// float value
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const float value)
{
glUniform1f(glGetUniformLocation(m_program, name), value);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// double value, usually time and frame delta
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const double value)
{
glUniform1d(glGetUniformLocation(m_program, name), value);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// glm::vec2
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const vec2 &value)
{
glUniform2f(glGetUniformLocation(m_program, name), value.x, value.y);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// glm::vec3
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const vec3 &value)
{
glUniform3f(glGetUniformLocation(m_program, name), value.x, value.y, value.z);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// vec4
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const vec4 &value)
{
glUniform4f(glGetUniformLocation(m_program, name), value.x, value.y, value.z, value.w);
}
//-----------------------------------------------------------------------------
// CShader::SetUniform
// 4x4 matrix
//-----------------------------------------------------------------------------
void CShader::SetUniform(const char *name, const mat4 &value)
{
const float *ptr = glm::value_ptr(value);
glUniformMatrix4fv(glGetUniformLocation(m_program, name), 1, false, ptr);
}
//-----------------------------------------------------------------------------
// /src/engine/gfx/glsl.h
// The GLSL Shader Helper functions & classes
//-----------------------------------------------------------------------------
#ifndef GLSL_H
#define GLSL_H
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <vector> // std::vector
//-----------------------------------------------------------------------------
// sampler2D
// GLSL type
//-----------------------------------------------------------------------------
using sampler2D = GLint;
//-----------------------------------------------------------------------------
// CShader
// Abstraction level for shader compilation
//-----------------------------------------------------------------------------
class CShader {
private:
GLuint m_program;
std::vector<GLuint> m_vsQueue;
std::vector<GLuint> m_fsQueue;
bool m_linked;
public:
CShader(void);
~CShader(void);
bool IsValid(void) const;
GLuint GetProgram(void) const;
bool CompileFile_V(const char *shaderFile);
bool CompileFile_F(const char *shaderFile);
bool LinkProgram(void);
void UseProgram(void);
void SetUniform(const char *name, const int value);
void SetUniform(const char *name, const float value);
void SetUniform(const char *name, const double value);
void SetUniform(const char *name, const glm::vec2 &value);
void SetUniform(const char *name, const glm::vec3 &value);
void SetUniform(const char *name, const glm::vec4 &value);
void SetUniform(const char *name, const glm::mat4 &value);
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment