arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

shader.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////
00002 // 6/6/02       Aaron Lefohn    Scientific Computing and Imaging Institute
00003 // School of Computing          University of Utah
00004 //
00005 //  This library is free software; you can redistribute it and/or
00006 //  modify it under the terms of the GNU Lesser General Public
00007 //  License as published by the Free Software Foundation; either
00008 //  version 2.1 of the License, or (at your option) any later version.
00009 //
00010 //  This library is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 //  Lesser General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU Lesser General Public
00016 //  License along with this library; if not, write to the Free Software
00017 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 ////////////////////////////////////////////////////////////////////////
00019 //
00020 // Shader.cpp: implementation of the Shader class.
00021 //
00022 /////////////////////////////////////////////////////////////////////
00023 
00024 #include <state/shader.h>
00025 #include <texture/multiTex.h>
00026 #include <iostream>
00027 #include <GL/glUtil.h>
00028 
00029 using namespace std;
00030 using namespace gutz;
00031 
00032 using namespace glift;
00033 
00034 //////////////////////////////////////////////////////////////////////
00035 /// Construction/Destruction
00036 //////////////////////////////////////////////////////////////////////
00037 
00038 Shader::Shader( GenState* genState )
00039 {
00040    initMembers( NULL, NULL, genState ? VecStateP(1,genState) : VecStateP() );
00041 }
00042 
00043 Shader::Shader( const VecStateP& genAttribs )
00044 {
00045    initMembers( NULL, NULL, genAttribs );
00046 }
00047 
00048 Shader::Shader( Texture* tex, GenState* genState )
00049 {
00050    initMembers( tex, NULL, genState ? VecStateP(1,genState) : VecStateP() );
00051 }
00052 
00053 Shader::Shader( Texture* tex, const VecStateP& genAttribs )
00054 {
00055    initMembers( tex, NULL, genAttribs);
00056 }
00057 
00058 Shader::Shader( Texture* tex, ProgShader* progShader, GenState* genState )
00059 {
00060    initMembers( tex, progShader, genState ? VecStateP(1,genState) : VecStateP() );
00061 }
00062 
00063 Shader::Shader( Texture* tex, ProgShader* progShader, const VecStateP& genAttribs )
00064 {
00065    initMembers( tex, progShader, genAttribs );
00066 }
00067 
00068 Shader::Shader( const Shader& rhs )
00069 {
00070    initMembers( rhs );
00071 }
00072 
00073 Shader& Shader::operator=( const Shader& rhs )
00074 {
00075    if( &rhs != this ) {
00076       initMembers( rhs );
00077    }
00078    return *this;
00079 }
00080 
00081 void Shader::initMembers( Texture* tex, ProgShader* progShader, const VecStateP& genAttribs )
00082 {
00083    m_texture = tex;
00084    m_progShader = progShader;
00085    m_genAttribs  = genAttribs;
00086 
00087    /// - Make sure that the number of textures and number of texture offsets match.
00088    if( m_progShader || m_texture)  {
00089       checkTexture();
00090    }
00091 }
00092 
00093 void Shader::initMembers( const Shader& rhs )
00094 {
00095    initMembers( rhs.m_texture, rhs.m_progShader, rhs.m_genAttribs );
00096 }
00097 
00098 void Shader::checkTexture()
00099 {
00100    /// Ensure that progShader specifies the same number of textures as 'm_texture' contains.
00101    if( m_progShader && m_texture ) {
00102       if( m_texture->numTexUnits() != m_progShader->numTexUnits() ) {
00103          err() << "initMembers(...) Error:\n"
00104             << "\tShader defines " << m_progShader->numTexUnits() 
00105             << "\ttexture perturbation(s) but " << m_texture->numTexUnits() << " textures were provided.\n"
00106             << "\t'EmptyTexture' objects can be used to enable texture\n"
00107             << "\tunits for their texture coordinates only.\n";
00108          exit(1);
00109       }
00110    }    
00111 
00112    /// Check the number of textures vs. number of texture perturbations.
00113    MultiTex* multiTex = dynamic_cast<MultiTex*>( m_texture );
00114    if( m_progShader && !multiTex ) {
00115       if( m_progShader->numTexUnits() > 1 ) {
00116          err() << "initMembers(...) Error:\n"
00117             << "\tShader requires " << m_progShader->numTexUnits() 
00118             << "\ttexture unit(s) and only 1 texture was provided.\n"
00119             << "\t'EmptyTexture' objects can be used to enable texture\n"
00120             << "\tunits for their texture coordinates only.\n";
00121          exit(1);
00122       }
00123    }
00124 }
00125 
00126 Shader::~Shader()
00127 {}
00128 
00129 /// Generate appropriate texture coordinates, taking into account 
00130 /// multiTexturing, texCoordTransforms, and texture contants
00131 MultiTexCoord* Shader::genTexCoords( const arrayw2f& rawTexCoord, const vec3f& primScale ) const
00132 {
00133    if( m_texture && rawTexCoord.size()==0 ) {
00134       err() << "genTexCoords(...) Error:\n"
00135          << "\tAttempt to create texture coordinates for a primitive that does\n"
00136          << "\tNOT have texture coordinates enabled.\n"
00137          << "\tIf texture coordinates are desired, construct primitive with \n"
00138          << "\ttexture coordinate generation enabled.\n";
00139       exit(1);
00140    }
00141 
00142    MultiTexCoord* multiTexCoord = NULL;
00143    if( m_progShader == NULL ) {
00144       if( !rawTexCoord.empty() ) {
00145          multiTexCoord = new MultiTexCoord( this->numTexUnits(), rawTexCoord );
00146       }
00147    }
00148    else {
00149       /// Note: m_progShader and m_tex are guaranteed (by the Shader Constructor)
00150       ///       to have the same number of texture units.
00151       multiTexCoord = m_progShader->genTexCoords( rawTexCoord, primScale );
00152    }
00153 
00154    /// Perturb the texture coords if subTextures are being used
00155    if( MultiTex* tex = dynamic_cast<MultiTex*>(m_texture) ) {   
00156       for(int t=0; t < numTexUnits(); t++) {
00157          if( SubTex* subtex = dynamic_cast<SubTex*>((*tex)[t]) ) {
00158             subtex->adjustTexCoord( (*multiTexCoord)[t] );
00159          }
00160       }
00161    }
00162    else if( m_texture ) { /// Single Texture
00163       if( SubTex* subtex = dynamic_cast<SubTex*>(m_texture) ) {
00164          subtex->adjustTexCoord( (*multiTexCoord)[0] );
00165       }
00166    }
00167 
00168    return multiTexCoord;
00169 }
00170 
00171 void Shader::bindDef()
00172 {
00173    if( m_texture    ) { m_texture->bind(); }
00174    if( m_progShader ) { m_progShader->bind(); }
00175 
00176    for(unsigned int i=0; i < m_genAttribs.size(); i++) {
00177       if( m_genAttribs[i] ) { m_genAttribs[i]->bind(); }
00178    }
00179    glErr(estr(),"Shader", "bindDef");
00180 }
00181 
00182 void Shader::releaseDef()
00183 {
00184    for(int i=m_genAttribs.size()-1; i >= 0; i--) {
00185       if( m_genAttribs[i] ) { m_genAttribs[i]->release(); }
00186    }
00187    if( m_progShader ) { m_progShader->release(); }
00188    if( m_texture    ) { m_texture->release(); }
00189 }
00190 
00191 

Send questions, comments, and bug reports to:
jmk