00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00033 #include "gl_glsl_shader_system/gl_glsl_shader.h"
00034 #include <GL/glew.h>
00035
00036 #include "gpucalc/text_file_loader.h"
00037 #include "gpucalc/graphic_core.h"
00038 #include "gpucalc/log_manager.h"
00039 #include "gpucalc/application.h"
00040 #include "gpucalc/string_util.h"
00041 #include "gpucalc/uniform.h"
00042 #include "gpucalc/texture.h"
00043
00044 namespace gpucalc
00045 {
00046 GLGLSLShader::GLGLSLShader(const std::string & ShaderName, ShaderSystem * system):
00047 Object(_GLGLSLShaderClassName, ShaderName), Shader(_GLGLSLShaderClassName, ShaderName, system),
00048 mGLSLProgramID(0), mGLSLFragmentShaderID(0), mMultiTextureNumber(0), mUniformVector(),
00049 mIsCompiled(false), mIsDebug(false), mShaderSource(), mShaderCompilerParams()
00050 {
00051 mGLSLProgramID = glCreateProgramObjectARB();
00052 LogManager::getSingleton().logMessage(this, "GLSL program created with OpenGL ID: " +
00053 auxillary::StringUtil::toString(mGLSLProgramID), LML_Trivial);
00054
00055 mGLSLFragmentShaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00056 LogManager::getSingleton().logMessage(this, "GLSL fragment shader created with OpenGL ID: " +
00057 auxillary::StringUtil::toString(mGLSLFragmentShaderID), LML_Trivial);
00058
00059 glAttachObjectARB(mGLSLProgramID, mGLSLFragmentShaderID);
00060 }
00061
00062
00063 GLGLSLShader::~GLGLSLShader()
00064 {
00065 glDetachShader(mGLSLProgramID, mGLSLFragmentShaderID);
00066 glDeleteShader(mGLSLFragmentShaderID);
00067 glDeleteProgram(mGLSLProgramID);
00068 LogManager::getSingleton().logMessage(this, "deleted.", LML_Trivial);
00069 }
00070
00071
00072 void GLGLSLShader::setSource(const std::string & ShaderSource)
00073 {
00074 mShaderSource = ShaderSource;
00075 mIsCompiled = false;
00076 }
00077
00078
00079 void GLGLSLShader::addUniform(Uniform * uniform)
00080 {
00081 if (addToContainer(uniform, mUniformVector))
00082 {
00083 uniform->uploadToGPU();
00084 }
00085 }
00086
00087
00088 void GLGLSLShader::removeUniform(Uniform * uniform)
00089 {
00090 removeFromContainer(uniform, mUniformVector);
00091 }
00092
00093
00094 void GLGLSLShader::setUniformVariable(Uniform * uniform)
00095 {
00096 GLint Location = getUniformLocation(uniform->getObjectName());
00097 if (Location != -1)
00098 {
00099 switch (uniform->getUniformType())
00100 {
00101 case Uniform::UT_INT_1:
00102 glUniform1iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00103 break;
00104
00105 case Uniform::UT_INT_2:
00106 glUniform2iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00107 break;
00108
00109 case Uniform::UT_INT_3:
00110 glUniform3iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00111 break;
00112
00113 case Uniform::UT_INT_4:
00114 glUniform4iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00115 break;
00116
00117 case Uniform::UT_FLOAT_1:
00118 glUniform1fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00119 break;
00120
00121
00122 case Uniform::UT_FLOAT_2:
00123 glUniform2fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00124 break;
00125
00126 case Uniform::UT_FLOAT_3:
00127 glUniform3fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00128 break;
00129
00130 case Uniform::UT_FLOAT_4:
00131 glUniform4fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00132 break;
00133
00134
00135 case Uniform::UT_MAT_2X2:
00136 glUniformMatrix2fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00137 break;
00138
00139 case Uniform::UT_MAT_3X3:
00140 glUniformMatrix3fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00141 break;
00142
00143 case Uniform::UT_MAT_4X4:
00144 glUniformMatrix4fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00145 break;
00146
00147 default:
00148 Except<ERR_NOT_IMPLEMENTED>(this, "Other uniform types not implemented.", "GLGLSLShader::setUniformVariable", __FILE__, __LINE__);
00149 break;
00150 }
00151
00152 LogManager::getSingleton().logMessage(this, "Uniform variable \"" + uniform->getObjectName() + "\" successfuly set.", LML_Trivial);
00153 }
00154 }
00155
00156
00157 void GLGLSLShader::setUniformSampler(Uniform * uniform)
00158 {
00159 Texture * Sampler = uniform->getSampler();
00160 if (!Sampler->isUploadedToGPU())
00161 {
00162 Sampler->uploadToGPU();
00163 }
00164
00165 GLint Location = getUniformLocation(Sampler->getObjectName());
00166 if (Location != -1)
00167 {
00168 glActiveTextureARB(GL_TEXTURE0_ARB + mMultiTextureNumber);
00169 Sampler->bind();
00170
00171 glUniform1i(Location, mMultiTextureNumber);
00172 ++mMultiTextureNumber;
00173 LogManager::getSingleton().logMessage(this, "Uniform sampler \"" + uniform->getObjectName() + "\" successfully set.", LML_Trivial);
00174 }
00175 }
00176
00177
00178 void GLGLSLShader::compile(const std::string & Parameters)
00179 {
00180
00181 mShaderCompilerParams = Parameters;
00182
00183 LogManager::getSingleton().logMessage(this, "This type of shader cannot use compiler parameters. Following parameters will be ignored: \"" +
00184 Parameters + "\".", LML_Critical);
00185
00186 const char * src = mShaderSource.c_str();
00187
00188 glShaderSource(mGLSLFragmentShaderID, 1, &src, NULL);
00189 glCompileShader(mGLSLFragmentShaderID);
00190 compileStatus();
00191 LogManager::getSingleton().logMessage(this, "Shader compiled.", LML_Trivial);
00192
00193 glLinkProgram(mGLSLProgramID);
00194 linkStatus();
00195 LogManager::getSingleton().logMessage(this, "Program linked.", LML_Trivial);
00196
00197
00198 if (LogManager::getSingleton().getLogDetail() == LL_Verbose)
00199 {
00200 ShaderInfoLog();
00201 ProgramInfoLog();
00202 }
00203 mIsCompiled = true;
00204 }
00205
00206
00207 void GLGLSLShader::preCompute()
00208 {
00209 if (!mIsCompiled)
00210 {
00211 compile(mShaderCompilerParams);
00212 }
00213
00214 mMultiTextureNumber = 0;
00215 bind();
00216 for (UniformVector::iterator i = mUniformVector.begin(); i != mUniformVector.end(); ++i)
00217 {
00218 Uniform * uniform = (*i);
00219 Uniform::UniformType uniform_type = uniform->getUniformType();
00220 if ((uniform_type == Uniform::UT_TEX_1) || (uniform_type == Uniform::UT_TEX_2))
00221 {
00222 setUniformSampler(uniform);
00223 }
00224 else
00225 {
00226 setUniformVariable(uniform);
00227 }
00228 }
00229 }
00230
00231
00232 void GLGLSLShader::validate()
00233 {
00234 GLint validate_status = 0;
00235 glValidateProgram(mGLSLProgramID);
00236 glGetProgramiv(mGLSLProgramID, GL_VALIDATE_STATUS, &validate_status);
00237 if (validate_status != GL_TRUE)
00238 {
00239 Warning<ERR_SOURCE_COMPILATION_ERROR>(this, "Does not check validation!", "GLGLSLShader::validateShader", __FILE__, __LINE__);
00240 ProgramInfoLog();
00241 }
00242 else
00243 {
00244 LogManager::getSingleton().logMessage(this, "Validated, shader is ready for computation.", LML_Trivial);
00245 }
00247 }
00248
00249
00250 void GLGLSLShader::compileStatus()
00251 {
00252 GLint compile_status = 0;
00253 glGetShaderiv(mGLSLFragmentShaderID, GL_COMPILE_STATUS, &compile_status);
00254 if (compile_status != GL_TRUE)
00255 {
00256 ShaderInfoLog();
00257 Except<ERR_SOURCE_COMPILATION_ERROR>(this, "Cannot compile!", "GLGLSLShader::compileStatus()", __FILE__, __LINE__);
00258 }
00259 }
00260
00261
00262 void GLGLSLShader::ShaderInfoLog()
00263 {
00264 GLint infologLength = 0;
00265 GLint charsWritten = 0;
00266 char * infoLog;
00267
00268 glGetShaderiv(mGLSLFragmentShaderID, GL_INFO_LOG_LENGTH, &infologLength);
00269 if (infologLength > 1)
00270 {
00271 infoLog = new char [infologLength];
00272 glGetShaderInfoLog(mGLSLFragmentShaderID, infologLength, &charsWritten, infoLog);
00273 LogManager::getSingleton().logMessage(this, "Log of shader compilation:", LML_Critical);
00274 LogManager::getSingleton().logMessage(this, infoLog, LML_Critical);
00275 delete [] infoLog;
00276 }
00277 }
00278
00279
00280 void GLGLSLShader::linkStatus()
00281 {
00282 GLint link_status;
00283 glGetProgramiv(mGLSLProgramID, GL_LINK_STATUS, &link_status);
00284 if (link_status != GL_TRUE)
00285 {
00286 ProgramInfoLog();
00287 Except<ERR_SOURCE_COMPILATION_ERROR>(this, "Cannot link!", "GLGLSLShader::linkStatus()", __FILE__, __LINE__);
00288 }
00289 }
00290
00291
00292 void GLGLSLShader::ProgramInfoLog()
00293 {
00294 GLint infologLength = 0;
00295 GLint charsWritten = 0;
00296 char * infoLog;
00297 glGetProgramiv(mGLSLProgramID, GL_INFO_LOG_LENGTH, &infologLength);
00298 if (infologLength > 1)
00299 {
00300 infoLog = new char [infologLength];
00301 glGetProgramInfoLog(mGLSLProgramID, infologLength, &charsWritten, infoLog);
00302 LogManager::getSingleton().logMessage(this, "Log of program compilation:", LML_Critical);
00303 LogManager::getSingleton().logMessage(this, infoLog, LML_Critical);
00304 delete [] infoLog;
00305 }
00306 }
00307
00308
00309 GLint GLGLSLShader::getUniformLocation(const std::string & Name)
00310 {
00311 GLint Result = glGetUniformLocation(mGLSLProgramID, Name.c_str());
00312 if (Result == -1)
00313 {
00314 Warning<ERR_ITEM_NOT_FOUND>(this, "Uniform variable \"" + Name + "\" cannot be found in shader", "GLGLSLShader::getUniformLocation", __FILE__, __LINE__);
00315 }
00316 return Result;
00317 }
00318 }