/* This file is part of the Pangolin Project. * http://github.com/stevenlovegrove/Pangolin * * Copyright (c) 2011 Steven Lovegrove * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include // Cg includes #include #include #include "gl.h" #ifdef HAVE_TOON #include #endif // HAVE_TOON namespace pangolin { //////////////////////////////////////////////// // Interface //////////////////////////////////////////////// /// Lightweight object wrapper for NVidia Cg Shader program objects. class CgProgram { friend class CgLoader; public: void SetUniform(const std::string& name, GlTexture& tex); void SetUniform(const std::string& name, float f); void SetUniform(const std::string& name, float v0, float v1); void SetUniform(const std::string& name, float v0, float v1, float v2, float v3); #ifdef HAVE_TOON void SetUniform(const std::string& name, const TooN::Vector<2>& v ); void SetUniform(const std::string& name, const TooN::Vector<3>& v ); template void SetUniform(const std::string& name, const TooN::Matrix& M ); #endif void UpdateParams(); protected: CGprogram mProg; CGcontext mContext; CGprofile mProfile; }; class CgLoader { public: CgLoader(); ~CgLoader(); // Call AFTER glewInit (or similar) void Initialise(); CgProgram LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader ); void EnableProgram(CgProgram program); void DisablePrograms(); void RenderDummyQuad(); void RenderDummyQuadWithTexCoords(int w, int h); protected: CGcontext mContext; CGprofile mFragmentProfile; CGprofile mVertexProfile; }; //////////////////////////////////////////////// // Implementation //////////////////////////////////////////////// inline bool cgOkay() { CGerror error; const char *string = cgGetLastErrorString(&error); if (error != CG_NO_ERROR) { std::cout << "CG Error: " << string << std::endl; // assert(0); return false; } return true; } inline CgLoader::CgLoader() :mContext(0) { } inline CgLoader::~CgLoader() { if(mContext) { // Destroying context destroys all programs associated with it cgDestroyContext(mContext); } } inline void CgLoader::Initialise() { mContext = cgCreateContext(); cgSetParameterSettingMode(mContext, CG_DEFERRED_PARAMETER_SETTING); cgOkay(); mFragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(mFragmentProfile); cgOkay(); mVertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(mVertexProfile); cgOkay(); } inline CgProgram CgLoader::LoadProgramFromFile(const std::string& file, const std::string& function, bool isVertexShader ) { if( !mContext ) { Initialise(); } CgProgram prog; prog.mContext = mContext; prog.mProfile = isVertexShader ? mVertexProfile : mFragmentProfile; prog.mProg = cgCreateProgramFromFile( prog.mContext, CG_SOURCE, file.c_str(), prog.mProfile, function.c_str(), NULL); if( !cgOkay() ) { std::cout << cgGetLastListing(mContext) << std::endl; assert(0); } cgGLLoadProgram(prog.mProg); if( !cgOkay() ) { const char* err = cgGetProgramString( prog.mProg, CG_COMPILED_PROGRAM ); int pos; glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); std::cout << err << std::endl; std::cout << "@ " << pos << std::endl; assert(0); } return prog; } inline void CgLoader::EnableProgram(CgProgram program) { cgGLBindProgram(program.mProg); cgGLEnableProfile(program.mProfile); cgOkay(); } inline void CgLoader::DisablePrograms() { cgGLDisableProfile(mFragmentProfile); cgGLDisableProfile(mVertexProfile); } inline void CgLoader::RenderDummyQuad() { glBegin(GL_QUADS); glVertex2d(-1,1); glVertex2d(1,1); glVertex2d(1,-1); glVertex2d(-1,-1); glEnd(); } inline void CgLoader::RenderDummyQuadWithTexCoords(int w, int h) { glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2d(-1,-1); glTexCoord2f(w, 0); glVertex2d(1,-1); glTexCoord2f(w, h); glVertex2d(1,1); glTexCoord2f(0, h); glVertex2d(-1,1); glEnd(); } void CgProgram::SetUniform(const std::string& name, float f) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgSetParameter1f( p, f ); cgUpdateProgramParameters(mProg); } void CgProgram::SetUniform(const std::string& name, GlTexture& tex) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgGLSetTextureParameter(p, tex.tid ); cgGLEnableTextureParameter(p); cgUpdateProgramParameters(mProg); } void CgProgram::SetUniform(const std::string& name, float v0, float v1, float v2, float v3) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgGLSetParameter4f(p, v0,v1,v2,v3); cgUpdateProgramParameters(mProg); } void CgProgram::SetUniform(const std::string& name, float v0, float v1) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgGLSetParameter2f(p, v0,v1); cgUpdateProgramParameters(mProg); } #ifdef HAVE_TOON void CgProgram::SetUniform(const std::string& name, const TooN::Vector<2>& v ) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgGLSetParameter2f(p, v[0],v[1] ); cgUpdateProgramParameters(mProg); } void CgProgram::SetUniform(const std::string& name, const TooN::Vector<3>& v ) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); cgGLSetParameter3f(p, v[0],v[1],v[2] ); cgUpdateProgramParameters(mProg); } template void CgProgram::SetUniform(const std::string& name, const TooN::Matrix& M ) { CGparameter p = cgGetNamedParameter( mProg, name.c_str()); float Mdata[R*C]; int i=0; for( int r=0; r