229 lines
6.2 KiB
C++
229 lines
6.2 KiB
C++
#include "shader.h"
|
|
#include <iostream>
|
|
|
|
#include <glm/ext.hpp>
|
|
|
|
Shader::Shader(const std::string &vertexSource, const std::string &fragmentSource)
|
|
{
|
|
m_lastShaderError = NULL;
|
|
m_lastProgramError = NULL;
|
|
|
|
m_program = glCreateProgram();
|
|
|
|
GLuint vertexShaderId = createShader(vertexSource, GL_VERTEX_SHADER);
|
|
GLuint fragmentShaderId = createShader(fragmentSource, GL_FRAGMENT_SHADER);
|
|
|
|
glAttachShader(m_program, vertexShaderId);
|
|
glAttachShader(m_program, fragmentShaderId);
|
|
|
|
glBindAttribLocation(m_program, 0, "inPosition");
|
|
glBindAttribLocation(m_program, 1, "inNormal");
|
|
glBindAttribLocation(m_program, 2, "inTexCoord");
|
|
glBindAttribLocation(m_program, 3, "inTangent");
|
|
glBindAttribLocation(m_program, 4, "inBinormal");
|
|
|
|
glLinkProgram(m_program);
|
|
|
|
// check errors
|
|
GLint linked;
|
|
glGetProgramiv(m_program, GL_LINK_STATUS, &linked);
|
|
if (!linked) {
|
|
#ifdef RENDER_DEBUG
|
|
std::cerr << "Program not linked" << std::endl;
|
|
#endif
|
|
printProgramInfoLog(m_program);
|
|
m_program = 0;
|
|
}
|
|
|
|
glDetachShader(m_program, vertexShaderId);
|
|
glDetachShader(m_program, fragmentShaderId);
|
|
glDeleteShader(vertexShaderId);
|
|
glDeleteShader(fragmentShaderId);
|
|
}
|
|
|
|
Shader::Shader(const std::string &vertexSource, const std::string &geometrySource, const std::string &fragmentSource)
|
|
{
|
|
m_lastShaderError = NULL;
|
|
m_lastProgramError = NULL;
|
|
|
|
m_program = glCreateProgram();
|
|
|
|
GLuint vertexShaderId = createShader(vertexSource, GL_VERTEX_SHADER);
|
|
GLuint geometryShaderId = createShader(geometrySource, GL_GEOMETRY_SHADER);
|
|
GLuint fragmentShaderId = createShader(fragmentSource, GL_FRAGMENT_SHADER);
|
|
|
|
glAttachShader(m_program, vertexShaderId);
|
|
glAttachShader(m_program, geometryShaderId);
|
|
glAttachShader(m_program, fragmentShaderId);
|
|
|
|
glBindAttribLocation(m_program, 0, "inPosition");
|
|
glBindAttribLocation(m_program, 1, "inNormal");
|
|
glBindAttribLocation(m_program, 2, "inTexCoord");
|
|
|
|
glLinkProgram(m_program);
|
|
|
|
// check errors
|
|
GLint linked;
|
|
glGetProgramiv(m_program, GL_LINK_STATUS, &linked);
|
|
if (!linked) {
|
|
#ifdef RENDER_DEBUG
|
|
std::cerr << "Program not linked" << std::endl;
|
|
#endif
|
|
printProgramInfoLog(m_program);
|
|
m_program = 0;
|
|
}
|
|
|
|
glDetachShader(m_program, vertexShaderId);
|
|
glDetachShader(m_program, geometryShaderId);
|
|
glDetachShader(m_program, fragmentShaderId);
|
|
glDeleteShader(vertexShaderId);
|
|
glDeleteShader(geometryShaderId);
|
|
glDeleteShader(fragmentShaderId);
|
|
}
|
|
|
|
Shader::~Shader()
|
|
{
|
|
bool ok;
|
|
ok = glIsProgram(m_program);
|
|
if(ok)
|
|
glDeleteProgram(m_program);
|
|
if(m_lastShaderError != NULL)
|
|
delete [] m_lastShaderError;
|
|
if(m_lastProgramError != NULL)
|
|
delete [] m_lastProgramError;
|
|
}
|
|
|
|
GLuint Shader::createShader(const std::string &source, GLenum shaderType)
|
|
{
|
|
GLuint shaderId = glCreateShader(shaderType);
|
|
const GLchar *data = (const GLchar *)source.c_str();
|
|
glShaderSource(shaderId, 1, &data, NULL);
|
|
|
|
glCompileShader(shaderId);
|
|
|
|
// check errors
|
|
GLint compiled;
|
|
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &compiled);
|
|
if (!compiled) {
|
|
#ifdef RENDER_DEBUG
|
|
std::string type_str;
|
|
switch(shaderType)
|
|
{
|
|
case GL_VERTEX_SHADER:
|
|
type_str = "Vertex";
|
|
break;
|
|
case GL_GEOMETRY_SHADER:
|
|
type_str = "Geometry";
|
|
break;
|
|
case GL_FRAGMENT_SHADER:
|
|
type_str = "Fragment";
|
|
break;
|
|
}
|
|
std::cerr << type_str << " shader not compiled : " << std::endl;
|
|
std::cout << "Shader source :" << std::endl << source << std::endl;
|
|
#endif
|
|
printShaderInfoLog(shaderId);
|
|
return 0;
|
|
}
|
|
else
|
|
return shaderId;
|
|
}
|
|
|
|
void Shader::printShaderInfoLog(GLuint shaderId)
|
|
{
|
|
int infoLogLen = 0;
|
|
int charsWritten = 0;
|
|
glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &infoLogLen);
|
|
if (infoLogLen > 0) {
|
|
if(m_lastShaderError != NULL)
|
|
delete [] m_lastShaderError;
|
|
m_lastShaderError = new GLchar[infoLogLen];
|
|
glGetShaderInfoLog(shaderId, infoLogLen, &charsWritten, m_lastShaderError);
|
|
#ifdef RENDER_DEBUG
|
|
std::cerr << "InfoLog:" << std::endl << m_lastShaderError << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void Shader::printProgramInfoLog(GLuint programId)
|
|
{
|
|
int infoLogLen = 0;
|
|
int charsWritten = 0;
|
|
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLogLen);
|
|
if (infoLogLen > 0) {
|
|
if(m_lastProgramError != NULL)
|
|
delete [] m_lastProgramError;
|
|
m_lastProgramError = new GLchar[infoLogLen];
|
|
glGetProgramInfoLog(programId, infoLogLen, &charsWritten, m_lastProgramError);
|
|
#ifdef RENDER_DEBUG
|
|
std::cerr << "InfoLog:" << std::endl << m_lastProgramError << std::endl;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
GLuint Shader::getLocation(std::string attribName)
|
|
{
|
|
GLuint loc = glGetUniformLocation(m_program, attribName.c_str());
|
|
return loc;
|
|
}
|
|
|
|
void Shader::bind()
|
|
{
|
|
glUseProgram(m_program);
|
|
}
|
|
|
|
void Shader::unbind()
|
|
{
|
|
glUseProgram(0);
|
|
}
|
|
|
|
void Shader::bindFloat(GLuint location, float val)
|
|
{
|
|
glUniform1f(location, val);
|
|
}
|
|
|
|
void Shader::bindMat3(GLuint location, const glm::mat3 &mat)
|
|
{
|
|
glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(mat));
|
|
}
|
|
|
|
void Shader::bindMat4(GLuint location, const glm::mat4 &mat)
|
|
{
|
|
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(mat));
|
|
}
|
|
|
|
void Shader::bindMat4Array(GLuint location, const glm::mat4 *matrices, int nbMat)
|
|
{
|
|
glUniformMatrix4fv(location, nbMat, GL_FALSE, (GLfloat*)matrices);
|
|
}
|
|
|
|
void Shader::bindVec2(GLuint location, const glm::vec2 &vec)
|
|
{
|
|
glUniform2fv(location, 1, glm::value_ptr(vec));
|
|
}
|
|
|
|
void Shader::bindVec3(GLuint location, const glm::vec3 &vec)
|
|
{
|
|
glUniform3fv(location, 1, glm::value_ptr(vec));
|
|
}
|
|
|
|
void Shader::bindVec4(GLuint location, const glm::vec4 &vec)
|
|
{
|
|
glUniform4fv(location, 1, glm::value_ptr(vec));
|
|
}
|
|
|
|
void Shader::bindVec3Array(GLuint location, const glm::vec3* vec, int nb_elements)
|
|
{
|
|
glUniform3fv(location, nb_elements, (GLfloat*)vec);
|
|
}
|
|
|
|
void Shader::bindUnsignedInteger(GLuint location, GLuint unsigned_integer)
|
|
{
|
|
glUniform1ui(location, unsigned_integer);
|
|
}
|
|
|
|
void Shader::bindInteger(GLuint location, GLint integer)
|
|
{
|
|
glUniform1i(location, integer);
|
|
}
|