Platformer in OpenGL
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 

226 řádky
6.2 KiB

/**
* Shader.cpp
* Contributors:
* * Arthur Sonzogni (author)
* Licence:
* * MIT
*/
#include "Shader.hpp"
#include <cstdlib>
#include <fstream>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
#include <stdexcept>
#include <vector>
using namespace std;
using namespace glm;
// file reading
void getFileContents(const char* filename, vector<char>& buffer) {
ifstream file(filename, ios_base::binary);
if (file) {
file.seekg(0, ios_base::end);
streamsize size = file.tellg();
if (size > 0) {
file.seekg(0, ios_base::beg);
buffer.resize(static_cast<size_t>(size));
file.read(&buffer[0], size);
}
buffer.push_back('\0');
} else {
throw std::invalid_argument(string("The file ") + filename +
" doesn't exists");
}
}
Shader::Shader(const std::string& filename, GLenum type) {
// file loading
vector<char> fileContent;
getFileContents(filename.c_str(), fileContent);
// creation
handle = glCreateShader(type);
if (handle == 0)
throw std::runtime_error("[Error] Impossible to create a new Shader");
// code source assignation
const char* shaderText(&fileContent[0]);
glShaderSource(handle, 1, (const GLchar**)&shaderText, NULL);
// compilation
glCompileShader(handle);
// compilation check
GLint compile_status;
glGetShaderiv(handle, GL_COMPILE_STATUS, &compile_status);
if (compile_status != GL_TRUE) {
GLsizei logsize = 0;
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &logsize);
char* log = new char[logsize + 1];
glGetShaderInfoLog(handle, logsize, &logsize, log);
cout << "[Error] compilation error: " << filename << endl;
cout << log << endl;
exit(EXIT_FAILURE);
} else {
cout << "[Info] Shader " << filename << " compiled successfully" << endl;
}
}
GLuint Shader::getHandle() const {
return handle;
}
Shader::~Shader() {}
ShaderProgram::ShaderProgram() {
handle = glCreateProgram();
if (!handle)
throw std::runtime_error("Impossible to create a new shader program");
}
ShaderProgram::ShaderProgram(std::initializer_list<Shader> shaderList)
: ShaderProgram() {
for (auto& s : shaderList)
glAttachShader(handle, s.getHandle());
link();
}
void ShaderProgram::link() {
glLinkProgram(handle);
GLint result;
glGetProgramiv(handle, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
cout << "[Error] linkage error" << endl;
GLsizei logsize = 0;
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &logsize);
char* log = new char[logsize];
glGetProgramInfoLog(handle, logsize, &logsize, log);
cout << log << endl;
}
}
GLint ShaderProgram::uniform(const std::string& name) {
auto it = uniforms.find(name);
if (it == uniforms.end()) {
// uniform that is not referenced
GLint r = glGetUniformLocation(handle, name.c_str());
if (r == GL_INVALID_OPERATION || r < 0)
cout << "[Error] uniform " << name << " doesn't exist in program" << endl;
// add it anyways
uniforms[name] = r;
return r;
} else
return it->second;
}
GLint ShaderProgram::attribute(const std::string& name) {
GLint attrib = glGetAttribLocation(handle, name.c_str());
if (attrib == GL_INVALID_OPERATION || attrib < 0)
cout << "[Error] Attribute " << name << " doesn't exist in program" << endl;
return attrib;
}
void ShaderProgram::setAttribute(const std::string& name,
GLint size,
GLsizei stride,
GLuint offset,
GLboolean normalize,
GLenum type) {
GLint loc = attribute(name);
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, size, type, normalize, stride,
reinterpret_cast<void*>(offset));
}
void ShaderProgram::setAttribute(const std::string& name,
GLint size,
GLsizei stride,
GLuint offset,
GLboolean normalize) {
setAttribute(name, size, stride, offset, normalize, GL_FLOAT);
}
void ShaderProgram::setAttribute(const std::string& name,
GLint size,
GLsizei stride,
GLuint offset,
GLenum type) {
setAttribute(name, size, stride, offset, false, type);
}
void ShaderProgram::setAttribute(const std::string& name,
GLint size,
GLsizei stride,
GLuint offset) {
setAttribute(name, size, stride, offset, false, GL_FLOAT);
}
void ShaderProgram::setUniform(const std::string& name,
float x,
float y,
float z) {
glUniform3f(uniform(name), x, y, z);
}
void ShaderProgram::setUniform(const std::string& name, const vec3& v) {
glUniform3fv(uniform(name), 1, value_ptr(v));
}
void ShaderProgram::setUniform(const std::string& name, const dvec3& v) {
glUniform3dv(uniform(name), 1, value_ptr(v));
}
void ShaderProgram::setUniform(const std::string& name, const vec4& v) {
glUniform4fv(uniform(name), 1, value_ptr(v));
}
void ShaderProgram::setUniform(const std::string& name, const dvec4& v) {
glUniform4dv(uniform(name), 1, value_ptr(v));
}
void ShaderProgram::setUniform(const std::string& name, const dmat4& m) {
glUniformMatrix4dv(uniform(name), 1, GL_FALSE, value_ptr(m));
}
void ShaderProgram::setUniform(const std::string& name, const mat4& m) {
glUniformMatrix4fv(uniform(name), 1, GL_FALSE, value_ptr(m));
}
void ShaderProgram::setUniform(const std::string& name, const mat3& m) {
glUniformMatrix3fv(uniform(name), 1, GL_FALSE, value_ptr(m));
}
void ShaderProgram::setUniform(const std::string& name, float val) {
glUniform1f(uniform(name), val);
}
void ShaderProgram::setUniform(const std::string& name, int val) {
glUniform1i(uniform(name), val);
}
ShaderProgram::~ShaderProgram() {
// glDeleteProgram(handle);
}
void ShaderProgram::use() const {
glUseProgram(handle);
}
void ShaderProgram::unuse() const {
glUseProgram(0);
}
GLuint ShaderProgram::getHandle() const {
return handle;
}