00001 #include "GLProgramm.h"
00002
00003 #include <QFile>
00004 #include <QDebug>
00005
00006 GLShader::GLShader(GLuint type)
00007 {
00008 changed = true;
00009 initialized = false;
00010 shader = 0;
00011 this->type = type;
00012 loopPos = -1;
00013 maxLoopIterations = 139;
00014 loopIterations = maxLoopIterations;
00015 }
00016
00017 GLShader::~GLShader()
00018 {
00019 free();
00020 }
00021
00022 char* getFileContents(const QString & fileName)
00023 {
00024 QFile *file = new QFile(fileName);
00025
00026 if(!file->open(QIODevice::ReadOnly | QIODevice::Unbuffered))
00027 return 0;
00028
00029 int fileSize = file->size();
00030
00031
00032 char *content = new char[fileSize + 1];
00033
00034 file->read(content, fileSize);
00035 content[fileSize] = '\0';
00036
00037 file->close();
00038
00039 return content;
00040 }
00041
00042 bool GLShader::load(QString shaderName)
00043 {
00044 this->shaderName = shaderName;
00045 const char *shaderSource = getFileContents("shader/" + shaderName + ".glsl");
00046
00047 if(shaderSource == 0)
00048 {
00049 source = "";
00050 return false;
00051 }
00052
00053 source = shaderSource;
00054 delete shaderSource;
00055
00056 loopPos = -1;
00057 string::size_type currentPos;
00058
00059 char searchCharacters[] = "|#";
00060 string::size_type lastPos;
00061
00062 lastPos = 0;
00063 currentPos = source.find_first_of(searchCharacters, lastPos);
00064 while(currentPos != -1)
00065 {
00066 if(source.at(currentPos) == '#')
00067 {
00068 loopPos = parts.size();
00069 }
00070 parts.push_back(source.substr(lastPos, currentPos));
00071 glue.push_back("");
00072 lastPos = currentPos + 1;
00073 currentPos = source.find_first_of(searchCharacters, lastPos);
00074 }
00075 parts.push_back(source.substr(lastPos));
00076
00077 initialized = false;
00078
00079 return false;
00080 }
00081
00082 bool GLShader::change()
00083 {
00084 bool ret = false;
00085
00086 if(initialized) {
00087 if(loopPos != -1)
00088 {
00089 if(maxLoopIterations > 70) {
00090 maxLoopIterations = 70;
00091 } else if(maxLoopIterations > 56) {
00092 maxLoopIterations = 56;
00093 } else if(maxLoopIterations > 28) {
00094 maxLoopIterations = 28;
00095 } else if(maxLoopIterations > 20) {
00096 maxLoopIterations = 20;
00097 } else if(maxLoopIterations > 18) {
00098 maxLoopIterations = 18;
00099 }else {
00100 maxLoopIterations -= 1;
00101 }
00102 if(loopIterations > maxLoopIterations) {
00103 loopIterations = maxLoopIterations;
00104 }
00105 qDebug() << "changed loop count: " << loopIterations;
00106 }
00107 }
00108 else
00109 {
00110
00111 GLint glParam;
00112 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, &glParam);
00113 if(maxLoopIterations > (GLuint)(glParam - 4) / 3) {
00114 qDebug() << "steps: " << maxLoopIterations << " | ~tex instructions: " << maxLoopIterations * 3 + 4 << "(" << glParam << ")";
00115
00116 }
00117 if(loopIterations > maxLoopIterations) {
00118 loopIterations = maxLoopIterations;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 initialized = true;
00128 }
00129
00130 if(loopPos != -1)
00131 {
00132 char insertString[4];
00133 sprintf_s(insertString, sizeof(insertString), "%u", loopIterations);
00134 glue[loopPos] = insertString;
00135 ret = true;
00136 }
00137
00138 string::size_type currentPos;
00139
00140 source = parts[0];
00141 currentPos = 1;
00142 while(currentPos < parts.size())
00143 {
00144 source += glue[currentPos - 1];
00145 source += parts[currentPos];
00146 ++currentPos;
00147 }
00148
00149
00150
00151
00152
00153
00154 return ret;
00155 }
00156
00157 bool GLShader::compile(bool *changed)
00158 {
00159 bool ret = true;
00160
00161 if(changed != 0)
00162 {
00163 *changed = change();
00164 }
00165 else if(!initialized)
00166 {
00167 change();
00168 }
00169
00170 if(shader == 0 || (changed != 0 && *changed))
00171 {
00172 if(shader == 0)
00173 {
00174 shader = glCreateShader(type);
00175 }
00176 const char *stringArray = source.c_str();
00177 glShaderSource(shader, 1, &stringArray, 0);
00178 glCompileShader(shader);
00179
00180
00181
00182 GLenum glError;
00183 glError = glGetError();
00184 if(glError != GL_NO_ERROR)
00185 {
00186 qDebug() << "compile shader error " << shaderName << ": " << (char*)gluErrorString(glError);
00187 ret = false;
00188 }
00189
00190 GLint glParam;
00191 glGetShaderiv(shader, GL_COMPILE_STATUS, &glParam);
00192 if(glParam == GL_FALSE)
00193 {
00194 qDebug() << "compile shader failed " << shaderName;
00195
00196 ret = false;
00197 }
00198
00199
00200
00201
00202
00203
00204 if(!ret)
00205 {
00206 char buf[1024];
00207 glGetShaderInfoLog(shader, sizeof(buf), NULL, buf);
00208 qDebug() << "info: " << buf;
00209 }
00210
00211 changed = false;
00212
00213 }
00214
00215 return ret;
00216 }
00217
00218 void GLShader::free()
00219 {
00220 if(shader != 0)
00221 {
00222 GLenum glError;
00223
00224 glDeleteShader(shader);
00225 shader = 0;
00226
00227 glError = glGetError();
00228 if(glError != GL_NO_ERROR)
00229 {
00230 qDebug() << "free shader error: " << (char*)gluErrorString(glError);
00231 }
00232 }
00233 }