1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 * Copyright (C) 2003-2005 3Dlabs Inc. Ltd.
3 * Copyright (C) 2004-2005 Nathan Cournia
4 * Copyright (C) 2008 Zebra Imaging
5 * Copyright (C) 2010 VIRES Simulationstechnologie GmbH
7 * This application is open source and may be redistributed and/or modified
8 * freely and without restriction, both in commercial and non commercial
9 * applications, as long as this copyright notice is maintained.
11 * This application is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16/* file: include/osg/Shader
17 * author: Mike Weiblen 2008-01-02
18 * Holger Helmich 2010-10-21
25#include <osg/GLExtensions>
27#include <osg/buffered_value>
36// set of shader define strings that the shader is dependent upon.
37typedef std::set<std::string> ShaderDefines;
39/** Simple class for wrapping up the data used in OpenGL ES 2's glShaderBinary calls.
40 * ShaderBinary is set up with the binary data then assigned to one or more osg::Shader. */
41class OSG_EXPORT ShaderBinary : public osg::Object
47 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
48 ShaderBinary(const ShaderBinary& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
50 META_Object(osg, ShaderBinary);
52 /** Allocated a data buffer of specified size.*/
53 void allocate(unsigned int size);
55 /** Assign shader binary data, copying the specified data into locally stored data buffer, the original data can then be deleted.*/
56 void assign(unsigned int size, const unsigned char* data);
58 /** Get the size of the shader binary data.*/
59 unsigned int getSize() const { return static_cast<unsigned int>(_data.size()); }
61 /** Get a ptr to the shader binary data.*/
62 unsigned char* getData() { return _data.empty() ? 0 : &(_data.front()); }
64 /** Get a const ptr to the shader binary data.*/
65 const unsigned char* getData() const { return _data.empty() ? 0 : &(_data.front()); }
67 /** Read shader binary from file.
68 * Return the resulting Shader or 0 if no valid shader binary could be read.*/
69 static ShaderBinary* readShaderBinaryFile(const std::string& fileName);
73 typedef std::vector<unsigned char> Data;
78///////////////////////////////////////////////////////////////////////////
79/** osg::Shader is an application-level abstraction of an OpenGL glShader.
80 * It is a container to load the shader source code text and manage its
82 * An osg::Shader may be attached to more than one osg::Program.
83 * Shader will automatically manage per-context instancing of the
84 * internal objects, if that is necessary for a particular display
88class OSG_EXPORT Shader : public osg::Object
93 VERTEX = GL_VERTEX_SHADER,
94 TESSCONTROL = GL_TESS_CONTROL_SHADER,
95 TESSEVALUATION = GL_TESS_EVALUATION_SHADER,
96 GEOMETRY = GL_GEOMETRY_SHADER,
97 FRAGMENT = GL_FRAGMENT_SHADER,
98 COMPUTE = GL_COMPUTE_SHADER,
102 Shader(Type type = UNDEFINED);
103 Shader(Type type, const std::string& source );
104 Shader(Type type, ShaderBinary* shaderBinary );
106 /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
107 Shader(const Shader& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
109 META_Object(osg, Shader);
111 int compare(const Shader& rhs) const;
113 /** Set the Shader type as an enum. */
114 bool setType(Type t);
116 /** Get the Shader type as an enum. */
117 inline Type getType() const { return _type; }
119 /** Get the Shader type as a descriptive string. */
120 const char* getTypename() const;
123 /** Set file name for the shader source code. */
124 inline void setFileName(const std::string& fileName) { _shaderFileName = fileName; }
126 /** Get filename to which the shader source code belongs. */
127 inline const std::string& getFileName() const { return _shaderFileName; }
130 /** Set the Shader's source code text from a string. */
131 void setShaderSource(const std::string& sourceText);
133 /** Query the shader's source code text */
134 inline const std::string& getShaderSource() const { return _shaderSource; }
137 enum ShaderDefinesMode
143 void setShaderDefinesMode(ShaderDefinesMode sdm) { _shaderDefinesMode = sdm; }
144 ShaderDefinesMode getShaderDefinesMode() const { return _shaderDefinesMode; }
147 void setShaderDefines(const ShaderDefines& shaderDefs) { _shaderDefines = shaderDefs; }
148 ShaderDefines& getShaderDefines() { return _shaderDefines; }
149 const ShaderDefines& getShaderDefines() const { return _shaderDefines; }
151 void setShaderRequirements(const ShaderDefines& shaderDefs) { _shaderRequirements = shaderDefs; }
152 ShaderDefines& getShaderRequirements() { return _shaderRequirements; }
153 const ShaderDefines& getShaderRequirements() const { return _shaderRequirements; }
156 /** Set the Shader using a ShaderBinary. */
157 void setShaderBinary(ShaderBinary* shaderBinary) { _shaderBinary = shaderBinary; }
159 /** Get the Shader's ShaderBinary, return NULL if none is assigned. */
160 ShaderBinary* getShaderBinary() { return _shaderBinary.get(); }
162 /** Get the const Shader's ShaderBinary, return NULL if none is assigned. */
163 const ShaderBinary* getShaderBinary() const { return _shaderBinary.get(); }
165#ifdef OSG_USE_DEPRECATED_API
166 /** Deorecated use osgDB::readRefShaderFile().*/
167 static Shader* readShaderFile( Type type, const std::string& fileName );
169 /** Deorecated use osgDB::readRefShaderFile(). */
170 bool loadShaderSourceFromFile( const std::string& fileName );
173 /** The code injection map used when generating the main shader during main shader composition.*/
174 typedef std::multimap<float, std::string> CodeInjectionMap;
176 /** Add code injection that will be placed in the main shader to enable support for this shader.
177 * The position is set up so that code to be inserted before the main() will have a negative value,
178 * a position between 0 and 1.0 will be inserted in main() and a position greater than 1.0 will
179 * be placed after the main().
180 * During shader composition all the code injections are sorted in ascending order and then
181 * placed in the appropriate section of the main shader. */
182 void addCodeInjection(float position, const std::string& code) { _codeInjectionMap.insert(CodeInjectionMap::value_type(position, code)); }
184 /** Get the code injection map.*/
185 CodeInjectionMap& getCodeInjectionMap() { return _codeInjectionMap; }
187 /** Get the const code injection map.*/
188 const CodeInjectionMap& getCodeInjectionMap() const { return _codeInjectionMap; }
192 /** Resize any per context GLObject buffers to specified size. */
193 virtual void resizeGLObjectBuffers(unsigned int maxSize);
195 /** release OpenGL objects in specified graphics context if State
196 object is passed, otherwise release OpenGL objects for all graphics context if
197 State object pointer NULL.*/
198 void releaseGLObjects(osg::State* state=0) const;
200 /** Mark our PCSs as needing recompilation.
201 * Also mark Programs that depend on us as needing relink */
204 /** If needed, compile the PCS's glShader */
205 void compileShader(osg::State& state) const;
207 static Shader::Type getTypeId( const std::string& tname );
210 /** PerContextShader (PCS) is an OSG-internal encapsulation of glShader per-GL context. */
211 class OSG_EXPORT PerContextShader : public osg::Referenced
214 PerContextShader(const Shader* shader, unsigned int contextID);
216 void setDefineString(const std::string& defStr) { _defineStr = defStr; }
217 const std::string& getDefineString() const { return _defineStr; }
219 GLuint getHandle() const {return _glShaderHandle;}
221 void requestCompile();
222 void compileShader(osg::State& state);
223 bool needsCompile() const {return _needsCompile;}
224 bool isCompiled() const {return _isCompiled;}
225 bool getInfoLog( std::string& infoLog ) const;
227 /** Attach our glShader to a glProgram */
228 void attachShader(GLuint program) const;
230 /** Detach our glShader from a glProgram */
231 void detachShader(GLuint program) const;
233 protected: /*methods*/
237 /** Pointer to our parent osg::Shader */
238 const Shader* _shader;
240 /** Pointer to this context's extension functions. */
241 osg::ref_ptr<osg::GLExtensions> _extensions;
243 /** Handle to the actual glShader. */
244 GLuint _glShaderHandle;
246 /** Define string passed on to Shaders to help configure them.*/
247 std::string _defineStr;
249 /** Does our glShader need to be recompiled? */
252 /** Is our glShader successfully compiled? */
255 const unsigned int _contextID;
258 PerContextShader(); // disallowed
259 PerContextShader(const PerContextShader&); // disallowed
260 PerContextShader& operator=(const PerContextShader&); // disallowed
264 struct OSG_EXPORT ShaderObjects : public osg::Referenced
266 typedef std::vector< osg::ref_ptr<PerContextShader> > PerContextShaders;
268 ShaderObjects(const Shader* shader, unsigned int contextID);
270 unsigned int _contextID;
271 const Shader* _shader;
272 mutable PerContextShaders _perContextShaders;
274 PerContextShader* getPCS(const std::string& defineStr) const;
275 PerContextShader* createPerContextShader(const std::string& defineStr);
276 void requestCompile();
279 PerContextShader* getPCS(osg::State& state) const;
281 protected: /*methods*/
285 friend class osg::Program;
286 bool addProgramRef( osg::Program* program );
287 bool removeProgramRef( osg::Program* program );
289 void _computeShaderDefines();
290 void _parseShaderDefines(const std::string& str, ShaderDefines& defines);
295 std::string _shaderFileName;
296 std::string _shaderSource;
297 osg::ref_ptr<ShaderBinary> _shaderBinary;
299 CodeInjectionMap _codeInjectionMap;
301 // ShaderDefines variables
302 ShaderDefinesMode _shaderDefinesMode;
303 ShaderDefines _shaderDefines;
304 ShaderDefines _shaderRequirements;
306 /** osg::Programs that this osg::Shader is attached to */
307 typedef std::set< osg::Program* > ProgramSet;
308 ProgramSet _programSet;
309 OpenThreads::Mutex _programSetMutex;
310 mutable osg::buffered_value< osg::ref_ptr<ShaderObjects> > _pcsList;
313 Shader& operator=(const Shader&); // disallowed
317class OSG_EXPORT ShaderComponent : public osg::Object
322 ShaderComponent(const ShaderComponent& sc,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
324 META_Object(osg, ShaderComponent);
326 unsigned int addShader(osg::Shader* shader);
327 void removeShader(unsigned int i);
329 osg::Shader* getShader(unsigned int i) { return _shaders[i].get(); }
330 const osg::Shader* getShader(unsigned int i) const { return _shaders[i].get(); }
332 unsigned int getNumShaders() const { return static_cast<unsigned int>(_shaders.size()); }
334 virtual void compileGLObjects(State& state) const;
335 virtual void resizeGLObjectBuffers(unsigned int maxSize);
336 virtual void releaseGLObjects(State* state=0) const;
340 typedef std::vector< osg::ref_ptr<osg::Shader> > Shaders;