00001 /*************************************************************************** 00002 * Copyright (c) 2008 Art Tevs * 00003 * * 00004 * This library is free software; you can redistribute it and/or modify * 00005 * it under the terms of the GNU Lesser General Public License as * 00006 * published by the Free Software Foundation; either version 3 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This library is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU Lesse General Public License for more details. * 00013 * * 00014 * The full license is in LICENSE file included with this distribution. * 00015 ***************************************************************************/ 00016 00017 #ifndef _C_SHADER_ATTRIBUTE_H_ 00018 #define _C_SHADER_ATTRIBUTE_H_ 00019 00020 //------------------------------------------------------------------------- 00021 // Includes 00022 //------------------------------------------------------------------------- 00023 #include <osg/Shader> 00024 #include <osg/Program> 00025 #include <osg/Uniform> 00026 #include <osg/Texture> 00027 #include <osg/StateAttribute> 00028 00029 #include <osgPPU/Export.h> 00030 00031 namespace osgPPU 00032 { 00033 00034 //! Wrapper class to simplify work with shader and uniforms 00035 /** 00036 * ShaderAttribute class is a simple wrapper for the osg::Shader, osg::Program 00037 * and osg::Uniform classes to simplify the work with shaders. It can be used 00038 * to define shader programs for the osgPPU::Unit or in external applications 00039 * as well. 00040 * 00041 * Current version of the class do not support Uniform StateAttribute values - OVERRIDE and PROTECTED. 00042 * This because the uniforms are applied directly in the apply method of the ShaderAttribute. 00043 * In order to be able to use it you have to apply the uniforms directly with osg methods to the 00044 * according StateSet. This wrapper is just a simpler version of osg's uniform handlings. 00045 **/ 00046 class OSGPPU_EXPORT ShaderAttribute : public osg::Program 00047 { 00048 public: 00049 META_StateAttribute(osgPPU, ShaderAttribute, PROGRAM); 00050 00051 /** Initialize shader to the fixed function pipeline per default **/ 00052 ShaderAttribute(); 00053 00054 /** 00055 * Copy constructor to create a shader object from the other one. 00056 * NOTE: copyop is currently ignored. The uniforms will be copied completely, 00057 * hence after the copy you will get two uniforms with the same value. 00058 **/ 00059 ShaderAttribute(const ShaderAttribute&, const osg::CopyOp& copyop=osg::CopyOp::DEEP_COPY_ALL); 00060 00061 /** Release used memory and close all used shader programs **/ 00062 virtual ~ShaderAttribute(); 00063 00064 /** 00065 * Add new uniform. The uniform can also represent an array. 00066 * The uniform will be applied in the apply method. Unfortunately 00067 * only the StateAttribute mode ON/OFF is checked. Hence PROTECTED and OVERRIDE are 00068 * currently not supported. 00069 * @param name Name of the uniform 00070 * @param type Type of the uniform 00071 * @param elementCount Number of elements if you add an array, otherwise 1 00072 **/ 00073 void add(const std::string& name, osg::Uniform::Type type, unsigned int elementCount = 1, osg::StateAttribute::OverrideValue mode = osg::StateAttribute::ON); 00074 00075 /** 00076 * Add new uniform. The uniform value will be copied. 00077 **/ 00078 void add(osg::Uniform* uniform, osg::StateAttribute::OverrideValue mode = osg::StateAttribute::ON); 00079 void add(osg::StateSet::RefUniformPair uniform); 00080 00081 /** 00082 * Delete uniform. Uniforms which are deleted are removed from the parental StateSets too. 00083 * @param name Name of the uniform 00084 **/ 00085 void del(const std::string& name); 00086 00087 /** 00088 * Set uniform value. 00089 **/ 00090 bool set(const std::string& name, bool b0){return set(0,name,b0);} 00091 bool set(const std::string& name, bool b0, bool b1){return set(0,name,b0,b1);} 00092 bool set(const std::string& name, bool b0, bool b1, bool b2){return set(0,name,b0,b1,b2);} 00093 bool set(const std::string& name, bool b0, bool b1, bool b2, bool b3){return set(0,name,b0,b1,b2,b3);} 00094 00095 bool set(const std::string& name, int i0){return set(0,name,i0);} 00096 bool set(const std::string& name, int i0, int i1){return set(0,name,i0,i1);} 00097 bool set(const std::string& name, int i0, int i1, int i2){return set(0,name,i0,i1,i2);} 00098 bool set(const std::string& name, int i0, int i1, int i2, int i3){return set(0,name,i0,i1,i2,i3);} 00099 00100 bool set(const std::string& name, float b0){return set(0,name,b0);} 00101 bool set(const std::string& name, float b0, float b1){return set(0,name,b0,b1);} 00102 bool set(const std::string& name, float b0, float b1, float b2){return set(0,name,b0,b1,b2);} 00103 bool set(const std::string& name, float b0, float b1, float b2, float b3){return set(0,name,b0,b1,b2,b3);} 00104 00105 bool set(const std::string& name, const osg::Vec2& v){return set(0,name,v);} 00106 bool set(const std::string& name, const osg::Vec3& v){return set(0,name,v);} 00107 bool set(const std::string& name, const osg::Vec4& v){return set(0,name,v);} 00108 00109 bool set(const std::string& name, const osg::Matrix2& m){return set(0,name,m);} 00110 bool set(const std::string& name, const osg::Matrix3& m){return set(0,name,m);} 00111 bool set(const std::string& name, const osg::Matrixf& m){return set(0,name,m);} 00112 00113 bool set(unsigned int index, const std::string& name, bool b0); 00114 bool set(unsigned int index, const std::string& name, bool b0, bool b1); 00115 bool set(unsigned int index, const std::string& name, bool b0, bool b1, bool b2); 00116 bool set(unsigned int index, const std::string& name, bool b0, bool b1, bool b2, bool b3); 00117 00118 bool set(unsigned int index, const std::string& name, int i0); 00119 bool set(unsigned int index, const std::string& name, int i0, int i1); 00120 bool set(unsigned int index, const std::string& name, int i0, int i1, int i2); 00121 bool set(unsigned int index, const std::string& name, int i0, int i1, int i2, int i3); 00122 00123 bool set(unsigned int index, const std::string& name, float b0); 00124 bool set(unsigned int index, const std::string& name, float b0, float b1); 00125 bool set(unsigned int index, const std::string& name, float b0, float b1, float b2); 00126 bool set(unsigned int index, const std::string& name, float b0, float b1, float b2, float b3); 00127 00128 bool set(unsigned int index, const std::string& name, const osg::Vec2& v); 00129 bool set(unsigned int index, const std::string& name, const osg::Vec3& v); 00130 bool set(unsigned int index, const std::string& name, const osg::Vec4& v); 00131 00132 bool set(unsigned int index, const std::string& name, const osg::Matrix2& m); 00133 bool set(unsigned int index, const std::string& name, const osg::Matrix3& m); 00134 bool set(unsigned int index, const std::string& name, const osg::Matrixf& m); 00135 00136 00137 /** 00138 * Bind a texture to the specified uniform. This method do siplify your life ;-) 00139 * @param index If uniform is an array element, then specify the index here 00140 * @param name Name of the uniform to which to bound the texture 00141 * @param tex Texture to bound 00142 * @param unit Texture unit to which to bound the texture. Specify -1 to automagically choose free texture unit 00143 **/ 00144 bool bindTexture(unsigned int index, const std::string& name, osg::Texture* tex, int unit = -1); 00145 00146 //! @copydoc bindTexture() 00147 bool bindTexture(const std::string& name, osg::Texture* tex, int unit = -1) {return bindTexture(0, name, tex, unit);} 00148 00149 /** 00150 * Bind a vertex attribute to a uniform. You have to take care to deliver correct 00151 * attribute data for the specified attribute. 00152 * @see osg::Programm::addBindAttribLocation() 00153 * @param name Name of the uniform variable 00154 * @param index Attribute index which to bound 00155 **/ 00156 bool bindAttribute(const std::string& name, unsigned int index); 00157 00158 /** 00159 * For shader model 4.0 hardwares you can specify the frag data to bound 00160 **/ 00161 bool bindFragData(const std::string& name, unsigned int index); 00162 00163 /** 00164 * Apply the shader attribute to the given state. This will bind the shader program 00165 * and set the uniforms. NOTE: The uniforms would be bound in this method, 00166 * hence the appropriate uniform value might be propagated to the shader in the next frame. 00167 **/ 00168 virtual void apply (osg::State &state) const; 00169 00170 /** @copydoc osg::StateAttribute::compare() **/ 00171 virtual int compare(const osg::StateAttribute& sa) const 00172 { 00173 // Check for equal types, then create the rhs variable 00174 // used by the COMPARE_StateAttribute_Paramter macros below. 00175 COMPARE_StateAttribute_Types(ShaderAttribute, sa) 00176 00177 // Compare each parameter in turn against the rhs. 00178 COMPARE_StateAttribute_Parameter(mMaxTextureUnits) 00179 COMPARE_StateAttribute_Parameter(mDirtyTextureBindings) 00180 00181 // TODO: currently no uniform comparison is made 00182 00183 return 0; // Passed all the above comparison macros, so must be equal. 00184 } 00185 00186 /** 00187 * Get uniform by a its name. If uniform was previously added or created this method will return it. 00188 * @param name Name of the uniform 00189 **/ 00190 osg::Uniform* get(const std::string& name); 00191 00192 /** 00193 * Set uniform list. 00194 **/ 00195 void setUniformList(const osg::StateSet::UniformList& list); 00196 00197 /** 00198 * Get correpsonding uniform list. 00199 **/ 00200 const osg::StateSet::UniformList& getUniformList() const { return mUniforms; } 00201 00202 /** 00203 * Set the number of maximal supported texture units. Per default this number is set to 8. 00204 * This number is needed to setup automagic texture to uniform binding. 00205 **/ 00206 void setMaximalSupportedTextureUnits(int i); 00207 00208 /** 00209 * Get maximum supported texture units. The results is the same as set by setMaximalSupportedTextureUnits() method 00210 **/ 00211 int getMaximalSupportedTextureUnits() const { return mMaxTextureUnits; } 00212 00213 /** 00214 * Mark the ShaderAttribute as dirty. This will force to reset all the texture binding to 00215 * parental StateSets on the next apply method. @see bindTexture() 00216 **/ 00217 void dirty() { mDirtyTextureBindings = true; } 00218 00219 struct TexUnit{ 00220 osg::ref_ptr<osg::Texture> t; 00221 int unit; 00222 unsigned int element; 00223 std::string name; 00224 }; 00225 00226 protected: 00227 00228 00229 typedef std::map<std::string, std::map<int,TexUnit> > TexUnitDb; 00230 00231 //! Database to hold the texture to uniform bindings 00232 TexUnitDb mTexUnits; 00233 00234 //! List of all added parameters 00235 osg::StateSet::UniformList mUniforms; 00236 00237 //! mark if boundings are dirty 00238 bool mDirtyTextureBindings; 00239 00240 //! maximal possible number of supported texture units 00241 int mMaxTextureUnits; 00242 00243 /** 00244 * Set parameters as uniform values. 00245 **/ 00246 void addParameter(const std::string& name, osg::Uniform* param, osg::StateAttribute::OverrideValue mode); 00247 00248 /** 00249 * Reset texture bindings. Call this if you have rebound textures and want to force 00250 * to recreate texture boundings within the shader. Normally this would be called 00251 * automatically by the update function if you have previously called any bind function 00252 **/ 00253 void resetTextureUniforms(); 00254 00255 //! Convert string type name into type 00256 osg::Uniform::Type convertToUniformType(const std::string& name); 00257 00258 }; 00259 00260 }; // end namespace 00261 00262 #endif
Copyright (C) 2008 by Art Tevs (LGPL)