Files
kraken/KREngine/KREngine/Classes/KRShader.cpp
kearwood cece608881 Initial import of KREngine
--HG--
extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%404
2011-10-25 05:03:10 +00:00

182 lines
6.9 KiB
C++

//
// KRShader.cpp
// KREngine
//
// Created by Kearwood Gilbert on 11-08-11.
// Copyright 2011 Kearwood Software. All rights reserved.
//
#include "KRShader.h"
KRShader::KRShader(std::string options, const GLchar *szVertShaderSource, const GLchar *szFragShaderSource) {
m_iProgram = 0;
GLuint vertexShader = 0, fragShader = 0;
try {
const GLchar *vertSource[2] = {options.c_str(), szVertShaderSource};
const GLchar *fragSource[2] = {options.c_str(), szFragShaderSource};
// Create shader program.
m_iProgram = glCreateProgram();
// Create and compile vertex shader.
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 2, vertSource, NULL);
glCompileShader(vertexShader);
// Create and compile vertex shader.
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 2, fragSource, NULL);
glCompileShader(fragShader);
// Attach vertex shader to program.
glAttachShader(m_iProgram, vertexShader);
// Attach fragment shader to program.
glAttachShader(m_iProgram, fragShader);
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_VERTEX, "position");
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_TEXUV, "inputTextureCoordinate");
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_VERTEX, "myVertex");
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_NORMAL, "myNormal");
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_TANGENT, "myTangent");
glBindAttribLocation(m_iProgram, KRENGINE_ATTRIB_TEXUV, "myUV");
// Link program.
glLinkProgram(m_iProgram);
// Get uniform locations
m_uniforms[KRENGINE_UNIFORM_MATERIAL_AMBIENT] = glGetUniformLocation(m_iProgram, "material_ambient");
m_uniforms[KRENGINE_UNIFORM_MATERIAL_DIFFUSE] = glGetUniformLocation(m_iProgram, "material_diffuse");
m_uniforms[KRENGINE_UNIFORM_MATERIAL_SPECULAR] = glGetUniformLocation(m_iProgram, "material_specular");
m_uniforms[KRENGINE_UNIFORM_MATERIAL_ALPHA] = glGetUniformLocation(m_iProgram, "material_alpha");
m_uniforms[KRENGINE_UNIFORM_MATERIAL_SHININESS] = glGetUniformLocation(m_iProgram, "material_shininess");
m_uniforms[KRENGINE_UNIFORM_MVP] = glGetUniformLocation(m_iProgram, "myMVPMatrix");
m_uniforms[KRENGINE_UNIFORM_SHADOWMVP1] = glGetUniformLocation(m_iProgram, "myShadowMVPMatrix1");
m_uniforms[KRENGINE_UNIFORM_SHADOWMVP2] = glGetUniformLocation(m_iProgram, "myShadowMVPMatrix2");
m_uniforms[KRENGINE_UNIFORM_SHADOWMVP3] = glGetUniformLocation(m_iProgram, "myShadowMVPMatrix3");
m_uniforms[KRENGINE_UNIFORM_LIGHTDIRECTION] = glGetUniformLocation(m_iProgram, "lightDirection");
m_uniforms[KRENGINE_UNIFORM_CAMERAPOS] = glGetUniformLocation(m_iProgram, "cameraPosition");
m_uniforms[KRENGINE_UNIFORM_DIFFUSETEXTURE] = glGetUniformLocation(m_iProgram, "diffuseTexture");
m_uniforms[KRENGINE_UNIFORM_SPECULARTEXTURE] = glGetUniformLocation(m_iProgram, "specularTexture");
m_uniforms[KRENGINE_UNIFORM_NORMALTEXTURE] = glGetUniformLocation(m_iProgram, "normalTexture");
m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] = glGetUniformLocation(m_iProgram, "shadowTexture1");
m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] = glGetUniformLocation(m_iProgram, "shadowTexture2");
m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] = glGetUniformLocation(m_iProgram, "shadowTexture3");
} catch(...) {
if(vertexShader) {
glDeleteShader(vertexShader);
vertexShader = 0;
}
if(fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if(m_iProgram) {
glDeleteProgram(m_iProgram);
m_iProgram = 0;
}
}
// Release vertex and fragment shaders.
if (vertexShader) {
glDeleteShader(vertexShader);
}
if (fragShader) {
glDeleteShader(fragShader);
}
}
KRShader::~KRShader() {
if(m_iProgram) {
glDeleteProgram(m_iProgram);
}
}
void KRShader::bind(KRCamera *pCamera, KRMat4 &mvpMatrix, Vector3 &cameraPosition, Vector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers) {
glUseProgram(m_iProgram);
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
glUniformMatrix4fv(m_uniforms[KRENGINE_UNIFORM_MVP], 1, GL_FALSE, mvpMatrix.getPointer());
Vector3 nLightDir = lightDirection;
nLightDir.normalize();
// Bind the light direction vector
glUniform3f(
m_uniforms[KRENGINE_UNIFORM_LIGHTDIRECTION],
(GLfloat)nLightDir.x,
(GLfloat)nLightDir.y,
(GLfloat)nLightDir.z
);
// Bind the camera position, in model space
glUniform3f(
m_uniforms[KRENGINE_UNIFORM_CAMERAPOS],
(GLfloat)cameraPosition.x,
(GLfloat)cameraPosition.y,
(GLfloat)cameraPosition.z
);
// Bind the shadowmap space matrices
for(int iShadow=0; iShadow < cShadowBuffers; iShadow++) {
glUniformMatrix4fv(m_uniforms[KRENGINE_UNIFORM_SHADOWMVP1 + iShadow], 1, GL_FALSE, pShadowMatrices[iShadow].getPointer());
}
// Sets the diffuseTexture variable to the first texture unit
glUniform1i(m_uniforms[KRENGINE_UNIFORM_DIFFUSETEXTURE], 0);
// Sets the specularTexture variable to the second texture unit
glUniform1i(m_uniforms[KRENGINE_UNIFORM_SPECULARTEXTURE], 1);
// Sets the normalTexture variable to the third texture unit
glUniform1i(m_uniforms[KRENGINE_UNIFORM_NORMALTEXTURE], 2);
// Sets the shadowTexture variable to the fourth texture unit
glUniform1i(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1], 3);
glUniform1i(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2], 4);
glUniform1i(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3], 5);
/*
#if defined(DEBUG)
if (![self validateProgram:m_iProgram])
{
NSLog(@"Failed to validate program: %d", m_shadowShaderProgram);
return;
}
#endif
*/
GLint logLength, status;
glValidateProgram(m_iProgram);
glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(m_iProgram, logLength, &logLength, log);
fprintf(stderr, "Program validate log:\n%s", log);
free(log);
}
/*
glGetProgramiv(m_iProgram, GL_VALIDATE_STATUS, &status);
if (status == 0) {
return false;
} else {
return true;
}
*/
}
GLuint KRShader::getProgram() {
return m_iProgram;
}