231 lines
5.4 KiB
C++
231 lines
5.4 KiB
C++
#include <opengl-playground/openglshader.hpp>
|
|
#include <opengl-playground/globalcanvassettings.hpp>
|
|
#include <string.h>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
OpenGlShaderProgram::OpenGlShaderProgram(std::string vertex_file, std::string geometry_file, std::string fragment_file)
|
|
{
|
|
this->vertex_file = vertex_file;
|
|
this->geometry_file = geometry_file;
|
|
this->fragment_file = fragment_file;
|
|
this->compiled = false;
|
|
}
|
|
|
|
OpenGlShaderProgram::~OpenGlShaderProgram()
|
|
{
|
|
this->unload();
|
|
}
|
|
|
|
std::string load_shader_program_from_file(std::string &file_name)
|
|
{
|
|
std::ifstream ifs(file_name);
|
|
std::string file_content((std::istreambuf_iterator<char>(ifs)),
|
|
(std::istreambuf_iterator<char>()));
|
|
|
|
return file_content;
|
|
}
|
|
|
|
int OpenGlShaderProgram::compile()
|
|
{
|
|
int ret_code = 0;
|
|
int success;
|
|
char info_log[512];
|
|
unsigned int vertex_shader, geometry_shader, fragment_shader;
|
|
bool vertex_b = false, geo_b = false, frag_b = false;
|
|
std::string src_code;
|
|
const char *c_string;
|
|
|
|
if (this->compiled) {
|
|
glDeleteProgram(shader_program);
|
|
this->compiled = false;
|
|
}
|
|
|
|
this->shader_program = glCreateProgram();
|
|
|
|
if (!vertex_file.empty()) {
|
|
vertex_b = true;
|
|
|
|
src_code = load_shader_program_from_file(this->vertex_file);
|
|
c_string = src_code.c_str();
|
|
|
|
/* Compile the vertex shader */
|
|
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(vertex_shader, 1, &c_string, NULL);
|
|
glCompileShader(vertex_shader);
|
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
|
|
|
|
if (!success) {
|
|
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
|
|
printf("Error in vertex shader: %s\n", info_log);
|
|
ret_code = -1;
|
|
goto delete_vertex;
|
|
}
|
|
|
|
glAttachShader(this->shader_program, vertex_shader);
|
|
} else
|
|
printf("Empty\n");
|
|
|
|
if (!this->geometry_file.empty()) {
|
|
geo_b = true;
|
|
|
|
src_code = load_shader_program_from_file(this->geometry_file);
|
|
c_string = src_code.c_str();
|
|
|
|
/* Compile the vertex shader */
|
|
geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);
|
|
glShaderSource(geometry_shader, 1, &c_string, NULL);
|
|
glCompileShader(geometry_shader);
|
|
glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &success);
|
|
|
|
if (!success) {
|
|
glGetShaderInfoLog(geometry_shader, 512, NULL, info_log);
|
|
fprintf(stderr, "%s\n", info_log);
|
|
ret_code = -1;
|
|
goto delete_geo;
|
|
}
|
|
|
|
glAttachShader(this->shader_program, geometry_shader);
|
|
|
|
}
|
|
|
|
if (!this->fragment_file.empty()) {
|
|
frag_b = true;
|
|
|
|
src_code = load_shader_program_from_file(this->fragment_file);
|
|
c_string = src_code.c_str();
|
|
|
|
/* Compile the vertex shader */
|
|
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(fragment_shader, 1, &c_string, NULL);
|
|
glCompileShader(fragment_shader);
|
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
|
|
|
|
if (!success) {
|
|
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
|
|
fprintf(stderr, "%s\n", info_log);
|
|
ret_code = -1;
|
|
goto delete_frag;
|
|
}
|
|
|
|
glAttachShader(this->shader_program, fragment_shader);
|
|
}
|
|
|
|
glLinkProgram(this->shader_program);
|
|
|
|
glGetShaderiv(this->shader_program, GL_LINK_STATUS, &success);
|
|
if (!success) {
|
|
glGetShaderInfoLog(this->shader_program, 512, NULL, info_log);
|
|
printf("%s\n", info_log);
|
|
ret_code = -2;
|
|
}
|
|
|
|
this->compiled = true;
|
|
|
|
delete_frag:
|
|
if (frag_b)
|
|
glDeleteShader(fragment_shader);
|
|
delete_geo:
|
|
if (geo_b)
|
|
glDeleteShader(geometry_shader);
|
|
delete_vertex:
|
|
if (vertex_b)
|
|
glDeleteShader(vertex_shader);
|
|
|
|
if (ret_code) {
|
|
this->compiled = false;
|
|
glDeleteProgram(this->shader_program);
|
|
this->shader_program = 0;
|
|
}
|
|
return ret_code;
|
|
}
|
|
|
|
void OpenGlShaderProgram::unload()
|
|
{
|
|
if (this->compiled) {
|
|
glDeleteProgram(this->shader_program);
|
|
}
|
|
|
|
this->compiled = false;
|
|
}
|
|
|
|
int OpenGlShaderProgram::use()
|
|
{
|
|
if (!this->compiled)
|
|
return -1;
|
|
|
|
glUseProgram(this->shader_program);
|
|
this->setUniformMat4("projection_view_matrix", GlobalCanvasSettings::getPVMatrix());
|
|
|
|
return 0;
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformFloat(const std::string &uniform, float value)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniform1f(loc, value);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformInt(const std::string &uniform, int value)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniform1i(loc, value);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformVec2(const std::string &uniform, float *vector)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniform2fv(loc, 1, vector);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformVec3(const std::string &uniform, const glm::vec3 &vector)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniform3fv(loc, 1, &vector.x);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformMat4(const std::string &uniform, const glm::mat4 &matrix)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniformMatrix4fv(loc, 1, GL_FALSE, &matrix[0][0]);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformMat3(const std::string &uniform, const glm::mat3 &matrix)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniformMatrix3fv(loc, 1, GL_FALSE, &matrix[0][0]);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformVec4(const std::string &uniform, const glm::vec4 &vector)
|
|
{
|
|
int loc = this->getUniformLoc(uniform);
|
|
if (loc >= 0) {
|
|
glUniform4fv(loc, 1, &vector.x);
|
|
}
|
|
}
|
|
|
|
void OpenGlShaderProgram::setUniformBool(const std::string &uniform, bool value)
|
|
{
|
|
this->setUniformInt(uniform, value ? 1 : 0);
|
|
}
|
|
|
|
int OpenGlShaderProgram::getUniformLoc(const std::string &uniform)
|
|
{
|
|
if (!this->compiled)
|
|
return -1;
|
|
|
|
return glGetUniformLocation(this->shader_program, uniform.c_str());
|
|
}
|