Back to index

nux  3.0.0
IOpenGLAsmShader.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "GLResource.h"
00024 #include "GraphicsDisplay.h"
00025 #include "GpuDevice.h"
00026 #include "GLDeviceObjects.h"
00027 #include "IOpenGLAsmShader.h"
00028 
00029 namespace nux
00030 {
00031 
00032   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmShader);
00033   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmVertexShader);
00034   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmPixelShader);
00035   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLAsmShaderProgram);
00036 
00037   bool ExtractShaderString3(const NString &ShaderToken, const NString &ShaderSource, NString &RetSource, NString ShaderPreprocessorDefines);
00038 
00039   IOpenGLAsmShader::IOpenGLAsmShader(NString ShaderName, OpenGLResourceType ResourceType)
00040     :   IOpenGLResource(ResourceType)
00041     ,   _ShaderName(ShaderName)
00042   {
00043 
00044   }
00045 
00046   IOpenGLAsmShader::~IOpenGLAsmShader()
00047   {
00048 
00049   }
00050 
00051   IOpenGLAsmVertexShader::IOpenGLAsmVertexShader(NString ShaderName)
00052     :   IOpenGLAsmShader(ShaderName, RT_GLSL_VERTEXSHADER)
00053     ,   m_CompiledAndReady(false)
00054   {
00055 #ifndef NUX_OPENGLES_20
00056     CHECKGL(glGenProgramsARB(1, &_OpenGLID));
00057 #endif
00058   }
00059 
00060   IOpenGLAsmVertexShader::~IOpenGLAsmVertexShader()
00061   {
00062 #ifndef NUX_OPENGLES_20
00063     CHECKGL(glDeleteProgramsARB(1, &_OpenGLID));
00064     _OpenGLID = 0;
00065     m_CompiledAndReady = false;
00066 #endif
00067   }
00068 
00069   void IOpenGLAsmVertexShader::SetShaderCode(const char *ShaderCode)
00070   {
00071     nuxAssertMsg(ShaderCode, "[IOpenGLAsmVertexShader::SetShaderCode] Invalid shader code.");
00072     NUX_RETURN_IF_NULL(ShaderCode);
00073     m_CompiledAndReady = false;
00074     _ShaderCode = ShaderCode;
00075   }
00076 
00077   bool IOpenGLAsmVertexShader::Compile()
00078   {
00079     m_CompiledAndReady = false;
00080 #ifndef NUX_OPENGLES_20
00081     size_t CodeSize = _ShaderCode.Size();
00082 
00083     if (CodeSize == 0)
00084     {
00085       nuxDebugMsg("[IOpenGLAsmVertexShader::Compile] Vertex shader source code is empty.");
00086     }
00087 
00088     char *ShaderSource = new char[CodeSize+1];
00089     Memset(ShaderSource, 0, CodeSize + 1);
00090     Memcpy(ShaderSource, TCHAR_TO_ANSI(_ShaderCode.GetTCharPtr()), CodeSize);
00091 
00092     CHECKGL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, _OpenGLID));
00093     glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, CodeSize, ShaderSource);
00094 
00095     if ( GL_INVALID_OPERATION == glGetError())
00096     {
00097       // Find the error position
00098       GLint errPos;
00099       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
00100       // Print implementation-dependent program
00101       // errors and warnings string.
00102       const unsigned char *ErrorString;
00103       ErrorString = NUX_STATIC_CAST(const unsigned char *, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
00104       nuxError("[IOpenGLAsmVertexShader::Compile] Error in vertex shader at position: %d\n%s\n", errPos, ErrorString );
00105       return m_CompiledAndReady;
00106     }
00107 
00108     delete[] ShaderSource;
00109 
00110     m_CompiledAndReady = true;
00111 #endif
00112     return m_CompiledAndReady;
00113   }
00114 
00115   bool IOpenGLAsmVertexShader::IsValid()
00116   {
00117     return m_CompiledAndReady;
00118   }
00119 
00120   IOpenGLAsmPixelShader::IOpenGLAsmPixelShader(NString ShaderName)
00121     :   IOpenGLAsmShader(ShaderName, RT_GLSL_PIXELSHADER)
00122     ,   m_CompiledAndReady(false)
00123   {
00124 #ifndef NUX_OPENGLES_20
00125     CHECKGL(glGenProgramsARB(1, &_OpenGLID));
00126 #endif
00127   }
00128 
00129   IOpenGLAsmPixelShader::~IOpenGLAsmPixelShader()
00130   {
00131 #ifndef NUX_OPENGLES_20
00132     CHECKGL(glDeleteProgramsARB(1, &_OpenGLID));
00133     _OpenGLID = 0;
00134     m_CompiledAndReady = false;
00135 #endif
00136   }
00137 
00138   void IOpenGLAsmPixelShader::SetShaderCode(const char *ShaderCode)
00139   {
00140     nuxAssertMsg(ShaderCode, "[IOpenGLAsmPixelShader::SetShaderCode] Invalid shader code.");
00141     NUX_RETURN_IF_NULL(ShaderCode);
00142     m_CompiledAndReady = false;
00143     _ShaderCode = ShaderCode;
00144   }
00145 
00146   bool IOpenGLAsmPixelShader::Compile()
00147   {
00148     m_CompiledAndReady = false;
00149 #ifndef NUX_OPENGLES_20
00150     size_t CodeSize = _ShaderCode.Size();
00151 
00152     if (CodeSize == 0)
00153     {
00154       nuxDebugMsg("[IOpenGLAsmPixelShader::Compile] Vertex shader source code is empty.");
00155     }
00156 
00157     char *ShaderSource = new char[CodeSize+1];
00158     Memset(ShaderSource, 0, CodeSize + 1);
00159     Memcpy(ShaderSource, TCHAR_TO_ANSI(_ShaderCode.GetTCharPtr()), CodeSize);
00160 
00161     CHECKGL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _OpenGLID));
00162     glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, CodeSize, ShaderSource);
00163 
00164     if ( GL_INVALID_OPERATION == glGetError())
00165     {
00166       // Find the error position
00167       GLint errPos;
00168       glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
00169       // Print implementation-dependent program
00170       // errors and warnings string.
00171       const unsigned char *ErrorString;
00172       ErrorString = NUX_STATIC_CAST(const unsigned char *, glGetString(GL_PROGRAM_ERROR_STRING_ARB));
00173       nuxError("[IOpenGLAsmPixelShader::Compile] Error in fragment shader at position: %d\n%s\n", errPos, ErrorString );
00174     }
00175 
00176     delete[] ShaderSource;
00177 
00178     m_CompiledAndReady = true;
00179 #endif
00180     return m_CompiledAndReady;
00181   }
00182 
00183   bool IOpenGLAsmPixelShader::IsValid()
00184   {
00185     return m_CompiledAndReady;
00186   }
00187 
00188   IOpenGLAsmShaderProgram::IOpenGLAsmShaderProgram(NString ShaderProgramName)
00189     :   IOpenGLResource(RT_GLSL_SHADERPROGRAM)
00190     ,   _ShaderProgramName(ShaderProgramName)
00191   {
00192     _OpenGLID = 0;
00193     m_AsmVertexProgram = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmVertexShader();
00194     m_AsmFragmentProgram = GetGraphicsDisplay()->GetGpuDevice()->CreateAsmPixelShader();
00195   }
00196 
00197   IOpenGLAsmShaderProgram::~IOpenGLAsmShaderProgram()
00198   {
00199     _OpenGLID = 0;
00200   }
00201 
00202   void IOpenGLAsmShaderProgram::LoadIShaderFile(const char *ShaderFileName)
00203   {
00204     nuxAssertMsg(ShaderFileName, "[IOpenGLAsmShaderProgram::LoadIShaderFile] Invalid shader file name.");
00205     NUX_RETURN_IF_NULL(ShaderFileName);
00206     NString SourceCode;
00207     LoadFileToString(SourceCode, ShaderFileName);
00208     LoadIShader(&SourceCode[0]);
00209   }
00210 
00211   void IOpenGLAsmShaderProgram::LoadIShader(const char *ShaderCode)
00212   {
00213     nuxAssertMsg(ShaderCode, "[IOpenGLAsmShaderProgram::LoadIShader] Invalid shader code.");
00214     NUX_RETURN_IF_NULL(ShaderCode);
00215     NString VertexShaderSource;
00216     ExtractShaderString3("[Vertex Shader]", ShaderCode, VertexShaderSource, NString(""));
00217     NString PixelShaderSource;
00218     ExtractShaderString3("[Fragment Shader]", ShaderCode, PixelShaderSource, NString(""));
00219 
00220     m_AsmVertexProgram->SetShaderCode(&VertexShaderSource[0]);
00221     m_AsmFragmentProgram->SetShaderCode(&PixelShaderSource[0]);
00222 
00223     m_AsmVertexProgram->Compile();
00224     m_AsmFragmentProgram->Compile();
00225   }
00226 
00227   void IOpenGLAsmShaderProgram::LoadVertexShader(const char *glslshader)
00228   {
00229     nuxAssertMsg(glslshader, "[IOpenGLAsmShaderProgram::LoadVertexShader] Invalid shader code.");
00230     NUX_RETURN_IF_NULL(glslshader);
00231     m_AsmVertexProgram->SetShaderCode(glslshader);
00232     m_AsmVertexProgram->Compile();
00233   }
00234 
00235   void IOpenGLAsmShaderProgram::LoadPixelShader(const char *glslshader)
00236   {
00237     nuxAssertMsg(glslshader, "[IOpenGLAsmShaderProgram::LoadPixelShader] Invalid shader code.");
00238     NUX_RETURN_IF_NULL(glslshader);
00239     m_AsmFragmentProgram->SetShaderCode(glslshader);
00240     m_AsmFragmentProgram->Compile();
00241   }
00242 
00243   void IOpenGLAsmShaderProgram::Link()
00244   {
00245     m_AsmVertexProgram->Compile();
00246     m_AsmFragmentProgram->Compile();
00247   }
00248 
00249   bool IOpenGLAsmShaderProgram::IsValid()
00250   {
00251     if (m_AsmVertexProgram->IsValid() && m_AsmFragmentProgram->IsValid())
00252       return true;
00253 
00254     return false;
00255   }
00256 
00257   void IOpenGLAsmShaderProgram::Begin(void)
00258   {
00259 #ifndef NUX_OPENGLES_20
00260     CHECKGL(glEnable(GL_VERTEX_PROGRAM_ARB));
00261     CHECKGL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, m_AsmVertexProgram->GetOpenGLID()));
00262     CHECKGL(glEnable(GL_FRAGMENT_PROGRAM_ARB));
00263     CHECKGL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, m_AsmFragmentProgram->GetOpenGLID()));
00264 #endif
00265   }
00266 
00267   void IOpenGLAsmShaderProgram::End(void)
00268   {
00269 #ifndef NUX_OPENGLES_20
00270     CHECKGL(glDisable(GL_VERTEX_PROGRAM_ARB));
00271     CHECKGL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
00272     CHECKGL(glDisable(GL_FRAGMENT_PROGRAM_ARB));
00273     CHECKGL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0));
00274 #endif
00275   }
00276 
00277 #ifndef NUX_OPENGLES_20
00278   void IOpenGLAsmShaderProgram::SetVertexEnvParameter4dARB(unsigned int index, double x, double y, double z, double w)
00279   {
00280     CHECKGL(glProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w));
00281   }
00282 
00283   void IOpenGLAsmShaderProgram::SetVertexEnvParameter4dvARB(unsigned int index, const double *params)
00284   {
00285     CHECKGL(glProgramEnvParameter4dvARB(GL_VERTEX_PROGRAM_ARB, index, params));
00286   }
00287 
00288   void IOpenGLAsmShaderProgram::SetVertexEnvParameter4fARB(unsigned int index, float x, float y, float z, float w)
00289   {
00290     CHECKGL(glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w));
00291   }
00292 
00293   void IOpenGLAsmShaderProgram::SetVertexEnvParameter4fvARB(unsigned int index, const float *params)
00294   {
00295     CHECKGL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, params));
00296   }
00297 
00298   void IOpenGLAsmShaderProgram::SetVertexLocalParameter4dARB(unsigned int index, double x, double y, double z, double w)
00299   {
00300     CHECKGL(glProgramEnvParameter4dARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w));
00301   }
00302 
00303   void IOpenGLAsmShaderProgram::SetVertexLocalParameter4dvARB(unsigned int index, const double *params)
00304   {
00305     CHECKGL(glProgramEnvParameter4dvARB(GL_VERTEX_PROGRAM_ARB, index, params));
00306   }
00307 
00308   void IOpenGLAsmShaderProgram::SetVertexLocalParameter4fARB(unsigned int index, float x, float y, float z, float w)
00309   {
00310     CHECKGL(glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, index, x, y, z, w));
00311   }
00312 
00313   void IOpenGLAsmShaderProgram::SetVertexLocalParameter4fvARB(unsigned int index, const float *params)
00314   {
00315     CHECKGL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, index, params));
00316   }
00317 
00318   void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4dARB(unsigned int index, double x, double y, double z, double w)
00319   {
00320     CHECKGL(glProgramEnvParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w));
00321   }
00322 
00323   void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4dvARB(unsigned int index, const double *params)
00324   {
00325     CHECKGL(glProgramEnvParameter4dvARB(GL_FRAGMENT_PROGRAM_ARB, index, params));
00326   }
00327 
00328   void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4fARB(unsigned int index, float x, float y, float z, float w)
00329   {
00330     CHECKGL(glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w));
00331   }
00332 
00333   void IOpenGLAsmShaderProgram::SetFragmentEnvParameter4fvARB(unsigned int index, const float *params)
00334   {
00335     CHECKGL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, params));
00336   }
00337 
00338   void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4dARB(unsigned int index, double x, double y, double z, double w)
00339   {
00340     CHECKGL(glProgramEnvParameter4dARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w));
00341   }
00342 
00343   void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4dvARB(unsigned int index, const double *params)
00344   {
00345     CHECKGL(glProgramEnvParameter4dvARB(GL_FRAGMENT_PROGRAM_ARB, index, params));
00346   }
00347 
00348   void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4fARB(unsigned int index, float x, float y, float z, float w)
00349   {
00350     CHECKGL(glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, index, x, y, z, w));
00351   }
00352 
00353   void IOpenGLAsmShaderProgram::SetFragmentLocalParameter4fvARB(unsigned int index, const float *params)
00354   {
00355     CHECKGL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, index, params));
00356   }
00357 #endif
00358 }
00359 
00360