/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library 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. See the * OpenSceneGraph Public License for more details. */ #ifndef OSG_TEXTURE #define OSG_TEXTURE 1 #include #include #include #include #include #include // if not defined by gl.h use the definition found in: // http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_filter_anisotropic.txt #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #endif #ifndef GL_ARB_texture_compression #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB #define GL_COMPRESSED_INTENSITY_ARB 0x84EC #define GL_COMPRESSED_RGB_ARB 0x84ED #define GL_COMPRESSED_RGBA_ARB 0x84EE #define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 #define GL_TEXTURE_COMPRESSED_ARB 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 #endif #ifndef GL_EXT_texture_compression_s3tc #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #endif #ifndef GL_MIRRORED_REPEAT_IBM #define GL_MIRRORED_REPEAT_IBM 0x8370 #endif #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #ifndef GL_CLAMP_TO_BORDER_ARB #define GL_CLAMP_TO_BORDER_ARB 0x812D #endif #ifndef GL_GENERATE_MIPMAP_SGIS #define GL_GENERATE_MIPMAP_SGIS 0x8191 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 #endif #ifndef GL_TEXTURE_3D #define GL_TEXTURE_3D 0x806F #endif namespace osg { /** Texture base class which encapsulates OpenGl texture functionality which common betweent the various types of OpenGL textures.*/ class SG_EXPORT Texture : public osg::StateAttribute { public : Texture(); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ Texture(const Texture& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY); virtual osg::Object* cloneType() const = 0; virtual osg::Object* clone(const CopyOp& copyop) const = 0; virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "Texture"; } virtual Type getType() const { return TEXTURE; } virtual bool isTextureAttribute() const { return true; } enum WrapParameter { WRAP_S, WRAP_T, WRAP_R }; enum WrapMode { CLAMP = GL_CLAMP, CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER_ARB, REPEAT = GL_REPEAT, MIRROR = GL_MIRRORED_REPEAT_IBM }; /** Set the texture wrap mode.*/ void setWrap(WrapParameter which, WrapMode wrap); /** Get the texture wrap mode.*/ WrapMode getWrap(WrapParameter which) const; /** Sets the border color for this texture. Makes difference only if * wrap mode is CLAMP_TO_BORDER */ void setBorderColor(const Vec4& color) { _borderColor = color; dirtyTextureParameters(); } const Vec4& getBorderColor() const { return _borderColor; } enum FilterParameter { MIN_FILTER, MAG_FILTER }; enum FilterMode { LINEAR = GL_LINEAR, LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR, LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, NEAREST = GL_NEAREST, NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST }; /** Set the texture filter mode.*/ void setFilter(FilterParameter which, FilterMode filter); /** Get the texture filter mode.*/ FilterMode getFilter(FilterParameter which) const; /** Set the maximum anisotropy value, default value is 1.0 for * no anisotropic filtering. If hardware does not support anisotropic * filtering then normal filtering is used, equivilant to a max anisotropy value of 1.0. * valid range is 1.0f upwards. The maximum value depends on the graphics * system being used.*/ void setMaxAnisotropy(float anis); /** Get the maximum anisotropy value.*/ inline float getMaxAnisotropy() const { return _maxAnisotropy; } /** Set the hint of whether to use hardware mip map generation where available.*/ inline void setUseHardwareMipMapGeneration(bool useHardwareMipMapGeneration) { _useHardwareMipMapGeneration = useHardwareMipMapGeneration; } /** Get the hint of whether to use hardware mip map generation where available.*/ inline bool getUseHardwareMipMapGeneration() const { return _useHardwareMipMapGeneration; } enum InternalFormatMode { USE_IMAGE_DATA_FORMAT, USE_USER_DEFINED_FORMAT, USE_ARB_COMPRESSION, USE_S3TC_DXT1_COMPRESSION, USE_S3TC_DXT3_COMPRESSION, USE_S3TC_DXT5_COMPRESSION }; /** Set the internal format mode. * Note, If the mode is set USE_IMAGE_DATA_FORMAT, USE_ARB_COMPRESSION, * USE_S3TC_COMPRESSION the internalFormat is automatically selected, * and will overwrite the previous _internalFormat. */ inline void setInternalFormatMode(InternalFormatMode mode) { _internalFormatMode = mode; } /** Get the internal format mode.*/ inline InternalFormatMode getInternalFormatMode() const { return _internalFormatMode; } /** Set the internal format to use when creating OpenGL textures. * Also sets the internalFormatMode to USE_USER_DEFINED_FORMAT. */ inline void setInternalFormat(GLint internalFormat) { _internalFormatMode = USE_USER_DEFINED_FORMAT; _internalFormat = internalFormat; } /** Get the internal format to use when creating OpenGL textures.*/ inline GLint getInternalFormat() const { if (_internalFormat==0) computeInternalFormat(); return _internalFormat; } bool isCompressedInternalFormat() const; /** Get the handle to the texture object for the current context.*/ /** return the OpenGL texture object for specified context.*/ inline GLuint& getTextureObject(unsigned int contextID) const { // get the globj for the current contextID. return _handleList[contextID]; } inline unsigned int& getTextureParameterDirty(unsigned int contextID) const { // get the dirty flag for the current contextID. return _texParametersDirtyList[contextID]; } /** Force a recompile on next apply() of associated OpenGL texture objects.*/ void dirtyTextureObject(); /** Force a resetting on next apply() of associated OpenGL texture parameters.*/ void dirtyTextureParameters(); /** use deleteTextureObject instead of glDeleteTextures to allow * OpenGL texture objects to cached until they can be deleted * by the OpenGL context in which they were created, specified * by contextID.*/ static void deleteTextureObject(unsigned int contextID,GLuint handle); /** flush all the cached display list which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedTextureObjects(unsigned int contextID); /** Texture is pure virtual base class, apply must be overriden. */ virtual void apply(State& state) const = 0; /** Calls apply(state) to compile the texture. */ virtual void compile(State& state) const; /** Extensions class which encapsulates the querring of extensions and * associated function pointers, and provide convinience wrappers to * check for the extensions or use the associated functions.*/ class SG_EXPORT Extensions : public osg::Referenced { public: Extensions(); Extensions(const Extensions& rhs); void lowestCommonDenominator(const Extensions& rhs); void setupGLExtenions(); bool isTextureFilterAnisotropicSupported() const { return _isTextureFilterAnisotropicSupported; } bool isTextureCompressionARBSupported() const { return _isTextureCompressionARBSupported; } bool isTextureCompressionS3TCSupported() const { return _isTextureCompressionS3TCSupported; } bool isTextureMirroredRepeatSupported() const { return _isTextureMirroredRepeatSupported; } bool isTextureEdgeClampSupported() const { return _isTextureEdgeClampSupported; } bool isTextureBorderClampSupported() const { return _isTextureBorderClampSupported; } bool isGenerateMipMapSupported() const { return _isGenerateMipMapSupported; } GLint maxTextureSize() const { return _maxTextureSize; } bool isCompressedTexImage2DSupported() const { return _glCompressedTexImage2D!=0; } void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const; void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei type, const GLvoid *data) const; void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *data) const; protected: ~Extensions() {} bool _isTextureFilterAnisotropicSupported; bool _isTextureCompressionARBSupported; bool _isTextureCompressionS3TCSupported; bool _isTextureMirroredRepeatSupported; bool _isTextureEdgeClampSupported; bool _isTextureBorderClampSupported; bool _isGenerateMipMapSupported; GLint _maxTextureSize; void* _glCompressedTexImage2D; void* _glCompressedTexSubImage2D; void* _glGetCompressedTexImage; }; /** Function to call to get the extension of a specified context. * If the Exentsion object for that context has not yet been created then * and the 'createIfNotInitalized' flag been set to false then returns NULL. * If 'createIfNotInitalized' is true then the Extensions object is * automatically created. However, in this case the extension object * only be created with the graphics context associated with ContextID..*/ static const Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); /** setExtensions allows users to override the extensions across graphics contexts. * typically used when you have different extensions supported across graphics pipes * but need to ensure that they all use the same low common denominator extensions.*/ static void setExtensions(unsigned int contextID,Extensions* extensions); /** Helper method which does the creation of the texture itself, but does not set or use texture binding. * Note, do not call this method directly unless you are implementing your own Subload callback*/ void applyTexImage2D_load(GLenum target, const Image* image, State& state, GLsizei& width, GLsizei& height,GLsizei& numMimpmapLevels) const; /** Helper method which subloads images to the texture itself, but does not set or use texture binding. * Note, do not call this method directly unless you are implementing your own Subload callback*/ void applyTexImage2D_subload(GLenum target, const Image* image, State& state, GLsizei& width, GLsizei& height,GLsizei& numMimpmapLevels) const; protected : virtual ~Texture(); virtual void computeInternalFormat() const = 0; void computeInternalFormatWithImage(const osg::Image& image) const; bool isCompressedInternalFormat(GLint internalFormat) const; /** Helper method which does setting of texture paramters. */ void applyTexParameters(GLenum target, State& state) const; /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ int compareTexture(const Texture& rhs) const; typedef buffered_value TextureNameList; mutable TextureNameList _handleList; typedef buffered_value TexParameterDirtyList; mutable TexParameterDirtyList _texParametersDirtyList; WrapMode _wrap_s; WrapMode _wrap_t; WrapMode _wrap_r; FilterMode _min_filter; FilterMode _mag_filter; float _maxAnisotropy; bool _useHardwareMipMapGeneration; Vec4 _borderColor; InternalFormatMode _internalFormatMode; mutable GLint _internalFormat; }; } #endif