You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
311 lines
12 KiB
311 lines
12 KiB
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|
* Copyright (C) 2003-2005 3Dlabs Inc. Ltd. |
|
* Copyright (C) 2004-2005 Nathan Cournia |
|
* Copyright (C) 2008 Zebra Imaging |
|
* Copyright (C) 2010 VIRES Simulationstechnologie GmbH |
|
* |
|
* This application is open source and may be redistributed and/or modified |
|
* freely and without restriction, both in commercial and non commercial |
|
* applications, as long as this copyright notice is maintained. |
|
* |
|
* This application is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
*/ |
|
|
|
/* file: include/osg/Shader |
|
* author: Mike Weiblen 2008-01-02 |
|
* Holger Helmich 2010-10-21 |
|
*/ |
|
|
|
#ifndef OSG_SHADER |
|
#define OSG_SHADER 1 |
|
|
|
|
|
#include <osg/GL2Extensions> |
|
#include <osg/Object> |
|
#include <osg/buffered_value> |
|
|
|
#include <set> |
|
#include <map> |
|
|
|
namespace osg { |
|
|
|
class Program; |
|
|
|
/** Simple class for wrapping up the data used in OpenGL ES 2's glShaderBinary calls. |
|
* ShaderBinary is set up with the binary data then assigned to one or more osg::Shader. */ |
|
class OSG_EXPORT ShaderBinary : public osg::Object |
|
{ |
|
public: |
|
|
|
ShaderBinary(); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
ShaderBinary(const ShaderBinary& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osg, ShaderBinary); |
|
|
|
/** Allocated a data buffer of specified size/*/ |
|
void allocate(unsigned int size); |
|
|
|
/** Assign shader binary data, copying the specified data into locally stored data buffer, the original data can then be deleted.*/ |
|
void assign(unsigned int size, const unsigned char* data); |
|
|
|
/** Get the size of the shader binary data.*/ |
|
unsigned int getSize() const { return _data.size(); } |
|
|
|
/** Get a ptr to the shader binary data.*/ |
|
unsigned char* getData() { return _data.empty() ? 0 : &(_data.front()); } |
|
|
|
/** Get a const ptr to the shader binary data.*/ |
|
const unsigned char* getData() const { return _data.empty() ? 0 : &(_data.front()); } |
|
|
|
/** Read shader binary from file. |
|
* Return the resulting Shader or 0 if no valid shader binary could be read.*/ |
|
static ShaderBinary* readShaderBinaryFile(const std::string& fileName); |
|
|
|
protected: |
|
|
|
typedef std::vector<unsigned char> Data; |
|
Data _data; |
|
}; |
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////// |
|
/** osg::Shader is an application-level abstraction of an OpenGL glShader. |
|
* It is a container to load the shader source code text and manage its |
|
* compilation. |
|
* An osg::Shader may be attached to more than one osg::Program. |
|
* Shader will automatically manage per-context instancing of the |
|
* internal objects, if that is necessary for a particular display |
|
* configuration. |
|
*/ |
|
|
|
class OSG_EXPORT Shader : public osg::Object |
|
{ |
|
public: |
|
|
|
enum Type { |
|
VERTEX = GL_VERTEX_SHADER, |
|
TESSCONTROL = GL_TESS_CONTROL_SHADER, |
|
TESSEVALUATION = GL_TESS_EVALUATION_SHADER, |
|
GEOMETRY = GL_GEOMETRY_SHADER_EXT, |
|
FRAGMENT = GL_FRAGMENT_SHADER, |
|
UNDEFINED = -1 |
|
}; |
|
|
|
Shader(Type type = UNDEFINED); |
|
Shader(Type type, const std::string& source ); |
|
Shader(Type type, ShaderBinary* shaderBinary ); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
Shader(const Shader& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osg, Shader); |
|
|
|
int compare(const Shader& rhs) const; |
|
|
|
/** Set the Shader type as an enum. */ |
|
bool setType(Type t); |
|
|
|
/** Get the Shader type as an enum. */ |
|
inline Type getType() const { return _type; } |
|
|
|
/** Get the Shader type as a descriptive string. */ |
|
const char* getTypename() const; |
|
|
|
|
|
/** Set file name for the shader source code. */ |
|
inline void setFileName(const std::string& fileName) { _shaderFileName = fileName; } |
|
|
|
/** Get filename to which the shader source code belongs. */ |
|
inline const std::string& getFileName() const { return _shaderFileName; } |
|
|
|
|
|
/** Set the Shader's source code text from a string. */ |
|
void setShaderSource(const std::string& sourceText); |
|
|
|
/** Query the shader's source code text */ |
|
inline const std::string& getShaderSource() const { return _shaderSource; } |
|
|
|
|
|
/** Set the Shader using a ShaderBinary. */ |
|
void setShaderBinary(ShaderBinary* shaderBinary) { _shaderBinary = shaderBinary; } |
|
|
|
/** Get the Shader's ShaderBinary, return NULL if none is assigned. */ |
|
ShaderBinary* getShaderBinary() { return _shaderBinary.get(); } |
|
|
|
/** Get the const Shader's ShaderBinary, return NULL if none is assigned. */ |
|
const ShaderBinary* getShaderBinary() const { return _shaderBinary.get(); } |
|
|
|
|
|
/** Read shader source from file and then constructor shader of specified type. |
|
* Return the resulting Shader or 0 if no valid shader source could be read.*/ |
|
static Shader* readShaderFile( Type type, const std::string& fileName ); |
|
|
|
/** Load the Shader's source code text from a file. */ |
|
bool loadShaderSourceFromFile( const std::string& fileName ); |
|
|
|
|
|
/** The code injection map used when generating the main shader during main shader composition.*/ |
|
typedef std::multimap<float, std::string> CodeInjectionMap; |
|
|
|
/** Add code injection that will be placed in the main shader to enable support for this shader. |
|
* The position is set up so that code to be inserted before the main() will have a negative value, |
|
* a position between 0 and 1.0 will be inserted in main() and a position greater than 1.0 will |
|
* be placed after the main(). |
|
* During shader composition all the code injections are sorted in ascending order and then |
|
* placed in the appropriate section of the main shader. */ |
|
void addCodeInjection(float position, const std::string& code) { _codeInjectionMap.insert(CodeInjectionMap::value_type(position, code)); } |
|
|
|
/** Get the code injection map.*/ |
|
CodeInjectionMap& getCodeInjectionMap() { return _codeInjectionMap; } |
|
|
|
/** Get the const code injection map.*/ |
|
const CodeInjectionMap& getCodeInjectionMap() const { return _codeInjectionMap; } |
|
|
|
|
|
|
|
/** Resize any per context GLObject buffers to specified size. */ |
|
virtual void resizeGLObjectBuffers(unsigned int maxSize); |
|
|
|
/** release OpenGL objects in specified graphics context if State |
|
object is passed, otherwise release OpenGL objects for all graphics context if |
|
State object pointer NULL.*/ |
|
void releaseGLObjects(osg::State* state=0) const; |
|
|
|
/** Mark our PCSs as needing recompilation. |
|
* Also mark Programs that depend on us as needing relink */ |
|
void dirtyShader(); |
|
|
|
/** If needed, compile the PCS's glShader */ |
|
void compileShader(osg::State& state) const; |
|
|
|
/** For a given GL context, attach a glShader to a glProgram */ |
|
void attachShader(unsigned int contextID, GLuint program) const; |
|
|
|
/** For a given GL context, detach a glShader to a glProgram */ |
|
void detachShader(unsigned int contextID, GLuint program) const; |
|
|
|
/** Query InfoLog from a glShader */ |
|
bool getGlShaderInfoLog(unsigned int contextID, std::string& log) const; |
|
|
|
/** Mark internal glShader for deletion. |
|
* Deletion requests are queued until they can be executed |
|
* in the proper GL context. */ |
|
static void deleteGlShader(unsigned int contextID, GLuint shader); |
|
|
|
/** flush all the cached glShaders which need to be deleted |
|
* in the OpenGL context related to contextID.*/ |
|
static void flushDeletedGlShaders(unsigned int contextID,double currentTime, double& availableTime); |
|
|
|
/** discard all the cached glShaders which need to be deleted in the OpenGL context related to contextID. |
|
* Note, unlike flush no OpenGL calls are made, instead the handles are all removed. |
|
* this call is useful for when an OpenGL context has been destroyed. */ |
|
static void discardDeletedGlShaders(unsigned int contextID); |
|
|
|
static Shader::Type getTypeId( const std::string& tname ); |
|
|
|
public: |
|
/** PerContextShader (PCS) is an OSG-internal encapsulation of glShader per-GL context. */ |
|
class OSG_EXPORT PerContextShader : public osg::Referenced |
|
{ |
|
public: |
|
PerContextShader(const Shader* shader, unsigned int contextID); |
|
|
|
GLuint getHandle() const {return _glShaderHandle;} |
|
|
|
void requestCompile(); |
|
void compileShader(osg::State& state); |
|
bool needsCompile() const {return _needsCompile;} |
|
bool isCompiled() const {return _isCompiled;} |
|
bool getInfoLog( std::string& infoLog ) const; |
|
|
|
/** Attach our glShader to a glProgram */ |
|
void attachShader(GLuint program) const; |
|
|
|
/** Detach our glShader from a glProgram */ |
|
void detachShader(GLuint program) const; |
|
|
|
protected: /*methods*/ |
|
~PerContextShader(); |
|
|
|
protected: /*data*/ |
|
/** Pointer to our parent osg::Shader */ |
|
const Shader* _shader; |
|
/** Pointer to this context's extension functions. */ |
|
osg::ref_ptr<osg::GL2Extensions> _extensions; |
|
/** Handle to the actual glShader. */ |
|
GLuint _glShaderHandle; |
|
/** Does our glShader need to be recompiled? */ |
|
bool _needsCompile; |
|
/** Is our glShader successfully compiled? */ |
|
bool _isCompiled; |
|
const unsigned int _contextID; |
|
|
|
private: |
|
PerContextShader(); // disallowed |
|
PerContextShader(const PerContextShader&); // disallowed |
|
PerContextShader& operator=(const PerContextShader&); // disallowed |
|
}; |
|
|
|
PerContextShader* getPCS(unsigned int contextID) const; |
|
|
|
protected: /*methods*/ |
|
virtual ~Shader(); |
|
|
|
|
|
friend class osg::Program; |
|
bool addProgramRef( osg::Program* program ); |
|
bool removeProgramRef( osg::Program* program ); |
|
|
|
protected: /*data*/ |
|
Type _type; |
|
std::string _shaderFileName; |
|
std::string _shaderSource; |
|
osg::ref_ptr<ShaderBinary> _shaderBinary; |
|
|
|
CodeInjectionMap _codeInjectionMap; |
|
|
|
/** osg::Programs that this osg::Shader is attached to */ |
|
typedef std::set< osg::Program* > ProgramSet; |
|
ProgramSet _programSet; |
|
mutable osg::buffered_value< osg::ref_ptr<PerContextShader> > _pcsList; |
|
|
|
private: |
|
Shader& operator=(const Shader&); // disallowed |
|
}; |
|
|
|
|
|
class OSG_EXPORT ShaderComponent : public osg::Object |
|
{ |
|
public: |
|
|
|
ShaderComponent(); |
|
ShaderComponent(const ShaderComponent& sc,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osg, ShaderComponent) |
|
|
|
unsigned int addShader(osg::Shader* shader); |
|
void removeShader(unsigned int i); |
|
|
|
osg::Shader* getShader(unsigned int i) { return _shaders[i].get(); } |
|
const osg::Shader* getShader(unsigned int i) const { return _shaders[i].get(); } |
|
|
|
unsigned int getNumShaders() const { return _shaders.size(); } |
|
|
|
virtual void compileGLObjects(State& state) const; |
|
virtual void resizeGLObjectBuffers(unsigned int maxSize); |
|
virtual void releaseGLObjects(State* state=0) const; |
|
|
|
protected: |
|
|
|
typedef std::vector< osg::ref_ptr<osg::Shader> > Shaders; |
|
Shaders _shaders; |
|
}; |
|
|
|
|
|
} |
|
|
|
#endif
|
|
|