00001 #include "Shader.hpp"
00002
00003 #include <stdio.h>
00004 #include <iostream>
00005 #include "utility.h"
00006
00007 Shader::Shader(const std::string &path) :
00008 _success(false),
00009 _fragment_shader(0),
00010 _vertex_shader(0)
00011 {
00012
00013
00014 get_errors();
00015
00016 string vertex_shader_source;
00017 if (file_exists(path+".vert")) {
00018 vertex_shader_source = read_file(path+".vert");
00019 } else {
00020 cerr << "Vertex shader file "
00021 << path <<".vert does not exist." << endl;
00022 return;
00023 }
00024
00025 string fragment_shader_source;
00026 if (file_exists(path+".frag")) {
00027 fragment_shader_source = read_file(path+".frag");
00028 } else {
00029 cerr << "Fragment shader file "
00030 << path <<".frag does not exist." << endl;
00031 return;
00032 }
00033
00034
00035 _vertex_shader = compile(GL_VERTEX_SHADER, vertex_shader_source);
00036 if (_vertex_shader == 0)
00037 return;
00038
00039 get_errors();
00040
00041 _fragment_shader = compile(GL_FRAGMENT_SHADER, fragment_shader_source);
00042 if (_fragment_shader == 0)
00043 return;
00044
00045 get_errors();
00046
00047
00048
00049 link();
00050 if (_program == 0)
00051 return;
00052
00053 _success = true;
00054 get_errors();
00055 }
00056
00057 Shader::~Shader()
00058 {
00059 glDeleteProgram(_program);
00060 glDeleteShader(_vertex_shader);
00061 glDeleteShader(_fragment_shader);
00062 }
00063
00064 GLuint Shader::compile (GLenum type, const string &source)
00065 {
00066
00067 get_errors();
00068 GLuint shader = glCreateShader(type);
00069
00070 if (shader == 0) {
00071 cerr << "Could not create shader object." << endl;
00072 return 0;
00073 }
00074
00075 get_errors();
00076
00077
00078
00079 const char* src = source.data();
00080
00081 int len = source.size();
00082
00083 glShaderSource(shader, 1, &src, &len);
00084
00085 glCompileShader(shader);
00086
00087
00088
00089 int status;
00090
00091 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
00092
00093 if (status != GL_TRUE) {
00094 cout << "Shader compilation failed." << endl;
00095 shader_log(shader);
00096 }
00097
00098 get_errors();
00099
00100 return shader;
00101 }
00102
00103 void Shader::link(void)
00104 {
00105
00106 _program = glCreateProgram();
00107
00108
00109
00110 glAttachShader(_program, _vertex_shader);
00111 glAttachShader(_program, _fragment_shader);
00112
00113 glLinkProgram(_program);
00114
00115
00116
00117 int status;
00118
00119 glGetProgramiv(_program, GL_LINK_STATUS, &status);
00120
00121 if (status != GL_TRUE) {
00122 cout << "Shader linking failed." << endl;
00123 program_log(_program);
00124
00125 glDeleteProgram(_program);
00126 _program = 0;
00127 }
00128
00129 get_errors();
00130 }
00131
00132 #define LOG_BUFFER_SIZE 8096
00133
00134 void Shader::program_log(GLuint program)
00135 {
00136 char logBuffer[LOG_BUFFER_SIZE];
00137 GLsizei length;
00138
00139 logBuffer[0] = '\0';
00140 glGetProgramInfoLog(program, LOG_BUFFER_SIZE, &length,logBuffer);
00141
00142 if (length > 0) {
00143 cout << logBuffer << endl;
00144 }
00145 }
00146
00147 void Shader::shader_log(GLuint shader)
00148 {
00149 char logBuffer[LOG_BUFFER_SIZE];
00150 GLsizei length;
00151
00152 logBuffer[0] = '\0';
00153 glGetShaderInfoLog(shader, LOG_BUFFER_SIZE, &length,logBuffer);
00154
00155 if (length > 0) {
00156 cout << logBuffer << endl;
00157 }
00158 }
00159
00160 bool Shader::wasSuccessfullyLinked()
00161 {
00162 return _success;
00163 }