#include <stdio.h>
#include <iostream>
#include "Shader.h"
int CheckGLError(char *file, int line)
{
GLenum glErr;
int retCode = 0;
glErr = glGetError();
while (glErr != GL_NO_ERROR) {
cout << "GL Error #" << glErr << "(" << gluErrorString(glErr) << ") " << " in File " << file << " at line: " << line << endl;
retCode = 1;
glErr = glGetError();
}
return retCode;
}
CShaderObject::CShaderObject(GLenum vShaderType)
{
_ShaderType = vShaderType;
_ShaderID = glCreateShader(_ShaderType);
if (_ShaderID == 0)
{
cout << "Fail to create shader object!\n";
exit(-1);
}
}
CShaderObject::~CShaderObject(void)
{
glDeleteShader(_ShaderID);
}
unsigned long CShaderObject::getFileLength(ifstream& vFile)
{
if(!vFile.good()) return 0;
unsigned long pos=vFile.tellg();
vFile.seekg(0,ios::end);
unsigned long len = vFile.tellg();
vFile.seekg(ios::beg);
return len;
}
GLuint CShaderObject::loadShaderFromFile(char* vFileName)
{
ifstream file;
file.open(vFileName, ios::in);
if(!file) return 0;
GLint len = getFileLength(file);
_pShaderSource = new char[len+1];
int i=0;
while (file.good())
{
_pShaderSource[i++] = file.get(); // get character from file
if (i>len) i=len;
}
_pShaderSource[i] = 0; // 0 terminate it.
int k = 1;
while (_pShaderSource[i-k] != '}')
{
_pShaderSource[i-k] = 0;
k++;
}
file.close();
int ShaderStatus;
glShaderSource(_ShaderID, 1, (const GLchar **)&_pShaderSource, &len);
CheckGLError(__FILE__, __LINE__);
glCompileShader(_ShaderID);
CheckGLError(__FILE__, __LINE__);
glGetShaderiv(_ShaderID, GL_COMPILE_STATUS, &ShaderStatus);
if (ShaderStatus == GL_FALSE)
{
cout << "Fail to compile the shader:" << vFileName << "\n";
GLchar compileErr[1024];
glGetShaderInfoLog(_ShaderID, 1024, NULL, compileErr);
cout << "Compile errors: \n" << compileErr << "\n";
exit(-1);
}
return _ShaderID;
}
CProgramObject::CProgramObject(void)
{
_ProgramID = glCreateProgram();
if (_ProgramID == 0)
{
cout << "Fail to create shader program object!\n";
exit(-1);
}
}
CProgramObject::~CProgramObject(void)
{
for (unsigned int i=0; i<_ShaderObjectList.size(); i++)
{
delete _ShaderObjectList[i].pObject;
}
glDeleteProgram(_ProgramID);
}
GLuint CProgramObject::loadShaderFromFile(char *vFileName, GLenum vShaderType)
{
CShaderObject *pObject=new CShaderObject(vShaderType);
GLuint ShaderID;
ShaderObject t;
ShaderID = pObject->loadShaderFromFile(vFileName);
if (ShaderID == 0)
{
cout << "Fail to load the shader source file!\n";
exit(-1);
}
t.pObject = pObject;
t.ID = ShaderID;
_ShaderObjectList.push_back(t);
return ShaderID;
}
void CProgramObject::makePipeline(GLuint vVertexShaderID, GLuint vFragShaderID)
{
int ProgramStatus;
GLuint attachedShaders[10];
int numAttachedShaders;
glGetAttachedShaders(_ProgramID, 10, &numAttachedShaders, attachedShaders);
for (int i=0; i<numAttachedShaders; i++)
{
glDetachShader(_ProgramID, attachedShaders[i]);
CheckGLError(__FILE__, __LINE__);
}
glAttachShader(_ProgramID, vVertexShaderID);
CheckGLError(__FILE__, __LINE__);
glAttachShader(_ProgramID, vFragShaderID);
CheckGLError(__FILE__, __LINE__);
glLinkProgram(_ProgramID);
glGetProgramiv(_ProgramID, GL_LINK_STATUS, &ProgramStatus);
if (ProgramStatus == GL_FALSE)
{
cout << "Fail to link the program!\n";
exit(-1);
}
glUseProgram(_ProgramID);
CheckGLError(__FILE__, __LINE__);
}
void CProgramObject::sendUniform3f(char* vVarName, GLfloat v0, GLfloat v1, GLfloat v2)
{
GLint loc;
loc = glGetUniformLocation(_ProgramID, vVarName);
if (loc == -1)
{
cout << "Error: can't find uniform variable \"" << vVarName << "\"\n";
}
glUniform3f(loc, v0, v1, v2);
}
void CProgramObject::sendUniform1f(char* vVarName, GLfloat v)
{
GLint loc;
loc = glGetUniformLocation(_ProgramID, vVarName);
if (loc == -1)
{
cout << "Error: can't find uniform variable \"" << vVarName << "\"\n";
}
glUniform1f(loc, v);
}
void CProgramObject::sendUniform1i(char* vVarName, GLint v)
{
GLint loc;
loc = glGetUniformLocation(_ProgramID, vVarName);
if (loc == -1)
{
cout << "Error: can't find uniform variable \"" << vVarName << "\"\n";
}
glUniform1i(loc, v);
}