00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sofa/helper/gl/GLSLShader.h>
00028 #include <stdlib.h>
00029 #include <math.h>
00030 #include <fstream>
00031 #include <iostream>
00032
00033 namespace sofa
00034 {
00035
00036 namespace helper
00037 {
00038
00039 namespace gl
00040 {
00041
00042 bool GLSLShader::InitGLSL()
00043 {
00044 GLenum err = glewInit();
00045 if (GLEW_OK != err)
00046 {
00047
00048 fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
00049 return false;
00050 }
00051
00052
00053
00054 if(!GLEW_ARB_shader_objects)
00055 {
00056 fprintf(stderr, "Error: GL_ARB_shader_objects extension not supported!\n");
00057 return false;
00058 }
00059
00060
00061 if(!GLEW_ARB_shading_language_100)
00062 {
00063 fprintf(stderr, "Error: GL_ARB_shading_language_100 extension not supported!\n");
00064 return false;
00065 }
00066
00067 return true;
00068 }
00069
00070 GLSLShader::GLSLShader()
00071 {
00072 m_hVertexShader = 0;
00073 m_hGeometryShader = 0;
00074 m_hFragmentShader = 0;
00075 m_hProgramObject = 0;
00076 geometry_input_type = -1;
00077 geometry_output_type = -1;
00078 geometry_vertices_out = -1;
00079 header = "";
00080 }
00081
00082 GLSLShader::~GLSLShader()
00083 {
00084
00085
00086 }
00087
00088 void GLSLShader::AddHeader(const std::string &header)
00089 {
00090 this->header += header;
00091 this->header += "\n";
00092 }
00093
00094 void GLSLShader::AddDefineMacro(const std::string &name, const std::string &value)
00095 {
00096 AddHeader("#define " + name + " " + value);
00097 }
00098
00100 std::string GLSLShader::LoadTextFile(const std::string& strFile)
00101 {
00102
00103 std::ifstream fin(strFile.c_str());
00104
00105
00106 if(!fin)
00107 return "";
00108
00109 std::string strLine = "";
00110 std::string strText = "";
00111
00112
00113 while(std::getline(fin, strLine))
00114 {
00115 strText = strText + "\n" + strLine;
00116 }
00117
00118
00119 fin.close();
00120
00121
00122 return strText;
00123 }
00124
00126 bool GLSLShader::CompileShader(GLint target, const std::string& source, GLhandleARB& shader)
00127 {
00128 const char* stype = "";
00129 if (target == GL_VERTEX_SHADER_ARB) stype = "vertex";
00130 else if (target == GL_FRAGMENT_SHADER_ARB) stype = "fragment";
00131 #ifdef GL_GEOMETRY_SHADER_EXT
00132 else if (target == GL_GEOMETRY_SHADER_EXT) stype = "geometry";
00133 #endif
00134
00135 shader = glCreateShaderObjectARB(target);
00136
00137 const char* src = source.c_str();
00138
00139 glShaderSourceARB(shader, 1, &src, NULL);
00140
00141 glCompileShaderARB(shader);
00142
00143 GLint compiled = 0, length = 0, laux = 0;
00144 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
00145 if (!compiled) std::cerr << "ERROR: Compilation of "<<stype<<" shader failed:\n"<<src<<std::endl;
00146
00147 glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
00148 if (length)
00149 {
00150 GLcharARB *logString = (GLcharARB *)malloc((length+1) * sizeof(GLcharARB));
00151 glGetInfoLogARB(shader, length, &laux, logString);
00152 std::cerr << logString << std::endl;
00153 free(logString);
00154 }
00155 return (compiled!=0);
00156 }
00157
00159 void GLSLShader::InitShaders(const std::string& strVertex, const std::string& strGeometry, const std::string& strFragment)
00160 {
00161
00162 if(!strVertex.length() || !strFragment.length())
00163 return;
00164
00165
00166 if(m_hVertexShader || m_hGeometryShader || m_hFragmentShader || m_hProgramObject)
00167 Release();
00168
00169 bool ready = true;
00170
00171
00172 ready &= CompileShader( GL_VERTEX_SHADER_ARB, header + LoadTextFile(strVertex), m_hVertexShader );
00173 if (!strGeometry.empty())
00174 {
00175 #ifdef GL_GEOMETRY_SHADER_EXT
00176 ready &= CompileShader( GL_GEOMETRY_SHADER_EXT, LoadTextFile(strGeometry), m_hGeometryShader );
00177 #else
00178 std::cerr << "SHADER ERROR: GL_GEOMETRY_SHADER_EXT not defined. Please use a recent version of GLEW.\n";
00179 ready = false;
00180 #endif
00181 }
00182 ready &= CompileShader( GL_FRAGMENT_SHADER_ARB, header + LoadTextFile(strFragment), m_hFragmentShader );
00183
00184 if (!ready)
00185 {
00186 std::cerr << "SHADER compilation failed.\n";
00187 return;
00188 }
00189
00190
00191 m_hProgramObject = glCreateProgramObjectARB();
00192
00193
00194 glAttachObjectARB(m_hProgramObject, m_hVertexShader);
00195 #ifdef GL_GEOMETRY_SHADER_EXT
00196 if (m_hGeometryShader)
00197 glAttachObjectARB(m_hProgramObject, m_hGeometryShader);
00198 #endif
00199 glAttachObjectARB(m_hProgramObject, m_hFragmentShader);
00200
00201 #ifdef GL_GEOMETRY_SHADER_EXT
00202 if (m_hGeometryShader)
00203 {
00204 if (geometry_input_type != -1) glProgramParameteriEXT(m_hProgramObject, GL_GEOMETRY_INPUT_TYPE_EXT, geometry_input_type );
00205 if (geometry_output_type != -1) glProgramParameteriEXT(m_hProgramObject, GL_GEOMETRY_OUTPUT_TYPE_EXT, geometry_output_type );
00206 if (geometry_vertices_out != -1) glProgramParameteriEXT(m_hProgramObject, GL_GEOMETRY_VERTICES_OUT_EXT, geometry_vertices_out );
00207 }
00208 #endif
00209
00210 glLinkProgramARB(m_hProgramObject);
00211
00212 GLint linked = 0, length = 0, laux = 0;
00213 glGetObjectParameterivARB(m_hProgramObject, GL_OBJECT_LINK_STATUS_ARB, &linked);
00214 if (!linked) std::cerr << "ERROR: Link of program shader failed:\n"<<std::endl;
00215
00216 glGetObjectParameterivARB(m_hProgramObject, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
00217 if (length)
00218 {
00219 GLcharARB *logString = (GLcharARB *)malloc((length+1) * sizeof(GLcharARB));
00220 glGetInfoLogARB(m_hProgramObject, length, &laux, logString);
00221 std::cerr << logString << std::endl;
00222 free(logString);
00223 }
00224
00225
00226 glUseProgramObjectARB(0);
00227 }
00228
00229
00230 void GLSLShader::SetInt(GLint variable, int newValue) { if (variable!=-1) glUniform1iARB(variable, newValue); }
00231 void GLSLShader::SetInt2(GLint variable, int i1, int i2) { if (variable!=-1) glUniform2iARB(variable, i1, i2); }
00232 void GLSLShader::SetInt3(GLint variable, int i1, int i2, int i3) { if (variable!=-1) glUniform3iARB(variable, i1, i2, i3); }
00233 void GLSLShader::SetInt4(GLint variable, int i1, int i2, int i3, int i4) { if (variable!=-1) glUniform4iARB(variable, i1, i2, i3, i4); }
00234 void GLSLShader::SetFloat(GLint variable, float newValue) { if (variable!=-1) glUniform1fARB(variable, newValue); }
00235 void GLSLShader::SetFloat2(GLint variable, float v0, float v1) { if (variable!=-1) glUniform2fARB(variable, v0, v1); }
00236 void GLSLShader::SetFloat3(GLint variable, float v0, float v1, float v2) { if (variable!=-1) glUniform3fARB(variable, v0, v1, v2); }
00237 void GLSLShader::SetFloat4(GLint variable, float v0, float v1, float v2, float v3) { if (variable!=-1) glUniform4fARB(variable, v0, v1, v2, v3); }
00238
00239 void GLSLShader::SetIntVector(GLint variable, GLsizei count, const GLint *value) { if (variable!=-1) glUniform1ivARB(variable, count, value); }
00240 void GLSLShader::SetIntVector2(GLint variable, GLsizei count, const GLint *value) { if (variable!=-1) glUniform2ivARB(variable, count, value); }
00241 void GLSLShader::SetIntVector3(GLint variable, GLsizei count, const GLint *value) { if (variable!=-1) glUniform3ivARB(variable, count, value); }
00242 void GLSLShader::SetIntVector4(GLint variable, GLsizei count, const GLint *value) { if (variable!=-1) glUniform4ivARB(variable, count, value); }
00243
00244 void GLSLShader::SetFloatVector(GLint variable, GLsizei count, const float *value) { if (variable!=-1) glUniform1fvARB(variable, count, value); }
00245 void GLSLShader::SetFloatVector2(GLint variable, GLsizei count, const float *value){ if (variable!=-1) glUniform2fvARB(variable, count, value); }
00246 void GLSLShader::SetFloatVector3(GLint variable, GLsizei count, const float *value){ if (variable!=-1) glUniform3fvARB(variable, count, value); }
00247 void GLSLShader::SetFloatVector4(GLint variable, GLsizei count, const float *value){ if (variable!=-1) glUniform4fvARB(variable, count, value); }
00248
00249
00250
00251 void GLSLShader::TurnOn() { if (m_hProgramObject) glUseProgramObjectARB(m_hProgramObject); }
00252 void GLSLShader::TurnOff() { if (m_hProgramObject) glUseProgramObjectARB(0); }
00253
00255 GLint GLSLShader::GetVariable(std::string strVariable)
00256 {
00257
00258 if(!m_hProgramObject)
00259 return -1;
00260
00261
00262
00263 return glGetUniformLocationARB(m_hProgramObject, strVariable.c_str());
00264 }
00265
00266
00268 void GLSLShader::Release()
00269 {
00270
00271 if(m_hVertexShader)
00272 {
00273 glDetachObjectARB(m_hProgramObject, m_hVertexShader);
00274 glDeleteObjectARB(m_hVertexShader);
00275 m_hVertexShader = 0;
00276 }
00277
00278
00279 if(m_hGeometryShader)
00280 {
00281 glDetachObjectARB(m_hProgramObject, m_hGeometryShader);
00282 glDeleteObjectARB(m_hGeometryShader);
00283 m_hGeometryShader = 0;
00284 }
00285
00286
00287 if(m_hFragmentShader)
00288 {
00289 glDetachObjectARB(m_hProgramObject, m_hFragmentShader);
00290 glDeleteObjectARB(m_hFragmentShader);
00291 m_hFragmentShader = 0;
00292 }
00293
00294
00295 if(m_hProgramObject)
00296 {
00297 glDeleteObjectARB(m_hProgramObject);
00298 m_hProgramObject = 0;
00299 }
00300 }
00301
00302 }
00303
00304 }
00305
00306 }