refactoring loading shaders

This commit is contained in:
Selim Mustafaev 2016-05-07 20:20:59 +03:00
parent 61fe295753
commit b27321336b
7 changed files with 146 additions and 67 deletions

View File

@ -1,5 +1,6 @@
#include "OGL.h" #include "OGL.h"
#include "Camera.h" #include "Camera.h"
#include "utils.h"
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
@ -122,6 +123,11 @@ void OGL::init() {
throw new std::runtime_error(errMsg); throw new std::runtime_error(errMsg);
} }
// even successful call to glewInit() may cause setting global error GL_INVALID_ENUM,
// so we need clear it in order to use glGetError() later
// https://www.opengl.org/wiki/OpenGL_Loading_Library#GLEW_.28OpenGL_Extension_Wrangler.29
utils::clearGLError();
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClearDepth(1.0); glClearDepth(1.0);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);

61
src/Shaders/Shader.cpp Normal file
View File

@ -0,0 +1,61 @@
#include "Shader.h"
#include "../utils.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <memory>
Shader::Shader(GLenum type, const std::string& path): _path(path), _type(type), _shader(0) {
}
void Shader::compile() {
std::ifstream is(_path, std::ios::binary);
if(is) {
std::ostringstream ss;
ss << is.rdbuf();
std::string text = ss.str();
_shader = glCreateShader(_type);
utils::throwIfGLError("error creating shader");
const GLchar* textBuffer = text.c_str();
glShaderSource(_shader, 1, &textBuffer, nullptr);
utils::throwIfGLError("error setting shader source");
glCompileShader(_shader);
utils::throwIfGLError("error compiling shader");
GLint success = GL_TRUE;
glGetShaderiv(_shader, GL_COMPILE_STATUS, &success);
if(success == GL_FALSE) {
logCompileError();
throw std::runtime_error("error compiling shader: " + _path);
}
} else {
throw std::runtime_error("error opening file: " + _path);
}
}
Shader::operator GLuint() const {
return _shader;
}
Shader::~Shader() {
glDeleteShader(_shader);
}
void Shader::logCompileError() {
std::cout << "shader: " << _shader << std::endl;
GLint logSize = 0;
glGetShaderiv(_shader, GL_INFO_LOG_LENGTH, &logSize);
std::cout << "log length: " << logSize << std::endl;
auto log = std::make_unique<GLchar[]>(logSize);
memset(log.get(), 0, (size_t)logSize);
glGetShaderInfoLog(_shader, logSize, &logSize, log.get());
std::cout << "log: " << log.get() << std::endl;
}

23
src/Shaders/Shader.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef GLTEST_SHADER_H
#define GLTEST_SHADER_H
#include <string>
#include <GL/glew.h>
class Shader {
private:
std::string _path;
GLenum _type;
GLuint _shader;
public:
Shader(GLenum type, const std::string& path);
void compile();
operator GLuint() const;
~Shader();
private:
void logCompileError();
};
#endif //GLTEST_SHADER_H

View File

@ -1,52 +1,27 @@
#include <iostream> #include <iostream>
#include <cstring> #include <cstring>
#include "ShaderProgram.h" #include "ShaderProgram.h"
#include "Shader.h"
#include "../utils.h"
ShaderProgram::ShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath) { ShaderProgram::ShaderProgram(const std::string& vertexShaderPath, const std::string& fragmentShaderPath) {
FILE* f = fopen(vertexShaderPath, "rb"); Shader vShader(GL_VERTEX_SHADER, vertexShaderPath);
fseek(f, 0, SEEK_END); Shader fShader(GL_FRAGMENT_SHADER, fragmentShaderPath);
long fsize = ftell(f);
fseek(f, 0, SEEK_SET);
_vertexShaderText = new char[fsize + 1];
fread(_vertexShaderText, fsize, 1, f);
fclose(f);
_vertexShaderText[fsize] = 0;
_vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertexShader, 1, (const GLchar**)&_vertexShaderText, nullptr);
glCompileShader(_vertexShader);
GLint success = GL_TRUE;
glGetShaderiv(_vertexShader, GL_COMPILE_STATUS, &success);
if(success == GL_FALSE) {
std::cout << "error compilling vertex shader" << std::endl;
logCompileError(_vertexShader);
}
f = fopen(fragmentShaderPath, "rb");
fseek(f, 0, SEEK_END);
fsize = ftell(f);
fseek(f, 0, SEEK_SET);
_fragmentShaderText = new char[fsize + 1];
fread(_fragmentShaderText, fsize, 1, f);
fclose(f);
_fragmentShaderText[fsize] = 0;
_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragmentShader, 1,(const GLchar**)&_fragmentShaderText, nullptr);
glCompileShader(_fragmentShader);
glGetShaderiv(_fragmentShader, GL_COMPILE_STATUS, &success);
if(success == GL_FALSE) {
std::cout << "error compilling fragment shader" << std::endl;
logCompileError(_fragmentShader);
}
vShader.compile();
fShader.compile();
_program = glCreateProgram(); _program = glCreateProgram();
glAttachShader(_program, _vertexShader); if(_program == 0) {
glAttachShader(_program, _fragmentShader); throw std::runtime_error("error creating shader program");
}
glAttachShader(_program, vShader);
utils::throwIfGLError("error attaching vertex shader to program");
glAttachShader(_program, fShader);
utils::throwIfGLError("error attaching fragment shader to program");
glLinkProgram(_program); glLinkProgram(_program);
utils::throwIfGLError("error linking program");
} }
void ShaderProgram::use() const { void ShaderProgram::use() const {
@ -54,26 +29,8 @@ void ShaderProgram::use() const {
} }
ShaderProgram::~ShaderProgram() { ShaderProgram::~ShaderProgram() {
delete[] _vertexShaderText;
delete[] _fragmentShaderText;
glDeleteShader(_vertexShader);
glDeleteShader(_fragmentShader);
} }
ShaderProgram::operator GLuint() const { ShaderProgram::operator GLuint() const {
return _program; return _program;
} }
void ShaderProgram::logCompileError(GLuint shader) {
std::cout << "shader: " << shader << std::endl;
GLint logSize = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize);
std::cout << "log length: " << logSize << std::endl;
GLchar* log = new GLchar[logSize];
memset(log, 0, (size_t)logSize);
glGetShaderInfoLog(shader, logSize, &logSize, log);
std::cout << "log: " << log << std::endl;
}

View File

@ -8,19 +8,12 @@
class ShaderProgram { class ShaderProgram {
private: private:
GLuint _program; GLuint _program;
GLuint _vertexShader;
GLuint _fragmentShader;
char* _vertexShaderText;
char* _fragmentShaderText;
public: public:
ShaderProgram(const char* vertexShaderPath, const char* fragmentShaderPath); ShaderProgram(const std::string& vertexShaderPath, const std::string& fragmentShaderPath);
void use() const; void use() const;
operator GLuint() const; operator GLuint() const;
~ShaderProgram(); ~ShaderProgram();
private:
void logCompileError(GLuint shader);
}; };

28
src/utils.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "utils.h"
#include <GL/glew.h>
#include <stdexcept>
namespace utils {
void throwIfGLError(const std::string& msg) {
std::string err;
while(true) {
GLenum error = glGetError();
if(error != GL_NO_ERROR) {
const char* errorStr = (const char*)gluErrorString(error);
if(errorStr) {
err += std::string(errorStr) + "\n";
}
} else {
break;
}
}
if(!err.empty()) {
throw std::runtime_error(msg + ": " + err);
}
}
void clearGLError() {
while(glGetError() != GL_NO_ERROR);
}
}

11
src/utils.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef GLTEST_UTILS_H
#define GLTEST_UTILS_H
#include <string>
namespace utils {
void throwIfGLError(const std::string& msg);
void clearGLError();
}
#endif //GLTEST_UTILS_H