The prototype of Zen Zoom. Made on ubuntu, I guess.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 

152 lines
3.7 KiB

#ifndef SHADER_H
#define SHADER_H
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <map>
#include <iterator>
#include <GL/glew.h>
#include <GL/freeglut.h>
class shader {
GLuint program;
std::map<GLenum, GLuint> shaders;
public:
shader(std::string vertex_shader_filename, std::string fragment_shader_filename) :
program(0), shaders() {
program = glCreateProgram();
if(program == 0) {
throw std::runtime_error("Program couldn't be created");
}
{
std::ifstream vertex_shader(vertex_shader_filename);
if(!vertex_shader)
throw std::runtime_error(vertex_shader_filename + " couldn't be opened");
read_shader(vertex_shader, GL_VERTEX_SHADER);
}
{
std::ifstream fragment_shader(fragment_shader_filename);
if(!fragment_shader)
throw std::runtime_error(fragment_shader_filename + " couldn't be opened");
read_shader(fragment_shader, GL_FRAGMENT_SHADER);
}
link_program();
}
~shader(){
begin();
for(auto & it : shaders){
GLuint shader = it.second;
glDetachShader(program, shader);
glDeleteShader(shader);
}
glDeleteProgram(program);
end();
}
void begin() {
glUseProgram(program);
}
void end() {
glUseProgram(0);
}
void set_uniform(char const* name, float x) const {
glUniform1f(glGetUniformLocation(program, name), x);
}
void set_uniform(char const* name, float x, float y) const {
glUniform2f(glGetUniformLocation(program, name), x, y);
}
void set_uniform(char const* name, float x, float y, float z) const {
glUniform3f(glGetUniformLocation(program, name), x, y, z);
}
void set_uniform(char const* name, float x, float y, float z, float w) const {
glUniform4f(glGetUniformLocation(program, name), x, y, z, w);
}
void set_uniform(char const* name, int x) const {
glUniform1i(glGetUniformLocation(program, name), x);
}
void set_uniform(char const* name, int x, int y) const {
glUniform2i(glGetUniformLocation(program, name), x, y);
}
void set_uniform(char const* name, int x, int y, int z) const {
glUniform3i(glGetUniformLocation(program, name), x, y, z);
}
void set_uniform(char const* name, int x, int y, int z, int w) const {
glUniform4i(glGetUniformLocation(program, name), x, y, z, w);
}
void set_texture(const char* name, GLenum target, GLuint tex, int textureLocation) const {
glActiveTexture(GL_TEXTURE0 + textureLocation);
glBindTexture(target, tex);
set_uniform(name, textureLocation);
}
private:
void read_shader(std::istream& file, GLenum type) {
// get the c-string
std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
const char* sptr = buffer.c_str();
int ssize = buffer.size();
// create and compile shader
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &sptr, &ssize);
glCompileShader(shader);
// check compile status
GLint status = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE || shader == 0) {
GLsizei infoLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
char* infoBuffer = new GLchar[infoLength];
glGetShaderInfoLog(shader, infoLength, &infoLength, infoBuffer);
std::cerr << buffer << std::endl;
std::cerr << "shader reports:\n" << infoBuffer << std::endl;
delete [] infoBuffer;
throw std::runtime_error("Shader failed to compile");
}
// put it in tha map
shaders[type] = shader;
}
void link_program() {
// attach all shaders
for(auto & it : shaders) {
GLuint shader = it.second;
glAttachShader(program, shader);
}
// link
glLinkProgram(program);
// check link status
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(status == GL_FALSE) {
throw std::runtime_error("Shader failed to link");
}
}
};
#endif // SHADER_H