/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ //#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_ #include "shader.h" #include "stdlibincl.h" #include #include "debug.h" #ifndef PARSELINELENGHT #define PARSELINELENGHT 512 //!< how many chars to read at once #endif using namespace std; /** * standard constructor */ Shader::Shader (const char* vertexShaderFile, const char* fragmentShaderFile) { this->setClassID(CL_SHADER, "Shader"); this->fragmentShaderFile = NULL; this->vertexShaderFile = NULL; this->shaderProgram = 0; this->vertexShader = 0; this->fragmentShader = 0; if (GLEW_ARB_shader_objects && GLEW_ARB_shading_language_100) this->shaderProgram = glCreateProgramObjectARB(); if (vertexShaderFile != NULL) this->loadShaderProgramm(SHADER_VERTEX, vertexShaderFile); if (fragmentShaderFile != NULL) this->loadShaderProgramm(SHADER_FRAGMENT, fragmentShaderFile); try { glLinkProgramARB(this->shaderProgram); } catch(GLenum errorCode) { this->printError(this->shaderProgram); } } /** * standard deconstructor */ Shader::~Shader () { // delete what has to be deleted here this->deleteProgram(SHADER_VERTEX); this->deleteProgram(SHADER_FRAGMENT); glDeleteObjectARB(this->fragmentShader); glDeleteObjectARB(this->vertexShader); glDeleteObjectARB(this->shaderProgram); } bool Shader::loadShaderProgramm(SHADER_TYPE type, const char* fileName) { if (type != SHADER_VERTEX && type != SHADER_FRAGMENT) return false; this->deleteProgram(type); const char* program = fileRead(fileName); GLenum shader = 0; if (type == SHADER_VERTEX && GLEW_ARB_vertex_shader) { this->vertexShaderFile = new char[strlen(fileName)+1]; strcpy(this->vertexShaderFile, fileName); shader = this->vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); } if (type == SHADER_FRAGMENT && GLEW_ARB_fragment_shader) { this->fragmentShaderFile = new char[strlen(fileName)+1]; strcpy(this->fragmentShaderFile, fileName); shader = this->fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); } glShaderSourceARB(shader, 1, (const GLcharARB**)&program, NULL); try { glCompileShaderARB(shader); } catch (...) { this->printError(shader); } glAttachObjectARB(this->shaderProgram, shader); delete[] program; } char* Shader::fileRead(const char* fileName) { FILE* fileHandle; char* content = NULL; int count = 0; if (fileName != NULL) { fileHandle = fopen(fileName, "rt"); if (fileHandle != NULL) { fseek(fileHandle, 0, SEEK_END); count = ftell(fileHandle); rewind(fileHandle); if (count > 0) { content = new char[count+1]; count = fread(content, sizeof(char), count, fileHandle); content[count] = '\0'; } fclose(fileHandle); } } return content; } void Shader::activateShader() { glUseProgramObjectARB(this->shaderProgram); } void Shader::deactivateShader() { glUseProgramObjectARB(0); } void Shader::deleteProgram(SHADER_TYPE type) { if (type == SHADER_VERTEX) { delete[] this->vertexShaderFile; this->vertexShaderFile = NULL; glDeleteObjectARB(this->vertexShader); this->vertexShader = 0; } else if (type == SHADER_FRAGMENT) { delete[] this->fragmentShaderFile; this->fragmentShaderFile = NULL; glDeleteObjectARB(this->fragmentShader); this->fragmentShader = 0; } else return; } void Shader::printError(GLenum program) { int infologLength = 0; int charsWritten = 0; char *infoLog; glGetObjectParameterivARB(program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength); if (infologLength > 0) { infoLog = (char *)malloc(sizeof(char) * (infologLength+1)); glGetInfoLogARB(program, infologLength, &charsWritten, infoLog); printf("%s\n", infoLog); free(infoLog); } } void Shader::debug() const { PRINT(3)("Shader info: (SHADER: %d)\n", this->shaderProgram); if (this->vertexShader != 0) { /* PRINT(3)("VertexShaderProgramm: number=%d, file='%s'\n", this->vertexShader, this->vertexShaderFile); if (this->vertexShaderSource != NULL) for (unsigned int i = 0; i < this->vertexShaderSource->getCount(); i++) PRINT(3)("%d: %s\n", i, this->vertexShaderSource->getEntry(i)); } if (this->fragmentShader != 0) { PRINT(3)("FragmentShaderProgramm: number=%d, file='%s'\n", this->fragmentShader, this->fragmentShaderFile); if (this->fragmentShaderSource != NULL) for (unsigned int i = 0; i < this->fragmentShaderSource->getCount(); i++) PRINT(3)("%d: %s\n", i, this->fragmentShaderSource->getEntry(i));*/ } }