From 2ab0f689eb7fef39d7aff0bdf5486e2e6fc64fc0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 16 Aug 2002 15:14:43 +0000 Subject: [PATCH] Added Texuture::SubloadCallback example into the osgprerender demo to illustrate how to use it. Changed the ImpostorSprite to use LINEAR,LINEAR for min and mag filters for the impostor texture. --- include/osg/Image | 8 +- include/osg/Texture | 38 ++++--- src/Demos/osgprerender/osgprerender.cpp | 135 ++++++++++++++++++++---- src/osg/ImpostorSprite.cpp | 2 + 4 files changed, 145 insertions(+), 38 deletions(-) diff --git a/include/osg/Image b/include/osg/Image index 4ac80e1d1..7a6651145 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -105,12 +105,18 @@ class SG_EXPORT Image : public Object inline const unsigned char *data() const { return _data; } - unsigned char* data(int column, int row=0,int image=0) + inline unsigned char* data(int column, int row=0,int image=0) { if (!_data) return NULL; return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); } + inline const unsigned char* data(int column, int row=0,int image=0) const + { + if (!_data) return NULL; + return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); + } + /** Flip the image horizontally.*/ void flipHorizontal(int image=0); diff --git a/include/osg/Texture b/include/osg/Texture index d6848a7c1..5071f2510 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -245,7 +245,7 @@ class SG_EXPORT Texture : public StateAttribute /** Set the texture subload width. If width or height are zero then * the repsective size value is calculated from the source image sizes. */ - inline void setSubloadTextureSize(const int width, const int height) + inline void setSubloadTextureSize(const int width, const int height) const { _textureWidth = width; _textureHeight = height; @@ -288,6 +288,21 @@ class SG_EXPORT Texture : public StateAttribute height = _subloadImageHeight; } + class SubloadCallback : public Referenced + { + public: + virtual void load(GLenum target, const Texture& texture,State& state) const = 0; + virtual void subload(GLenum target, const Texture& texture,State& state) const = 0; + }; + + void setSubloadCallback(SubloadCallback* cb) { _subloadCallback = cb; _subloadMode = cb ? USE_CALLBACK:OFF; } + + SubloadCallback* getSubloadCallback() { return _subloadCallback.get(); } + + const SubloadCallback* getSubloadCallback() const { return _subloadCallback.get(); } + + + /** Get the handle to the texture object for the current context.*/ /** return the OpenGL texture object for specified context.*/ inline GLuint& getTextureObject(const uint contextID) const @@ -321,26 +336,15 @@ class SG_EXPORT Texture : public StateAttribute virtual void compile(State& state) const; - /** Get the number of mip map levels the the texture has been created with,*/ + /** Set the number of mip map levels the the texture has been created with, + should only be called within an osg::Texuture::apply() and custom OpenGL texture load.*/ + void setNumMipmapLevels(unsigned int num) const { _numMimpmapLevels=num; } + + /** Get the number of mip map levels the the texture has been created with.*/ unsigned int getNumMipmapLevels() const { return _numMimpmapLevels; } - class SubloadCallback : public Referenced - { - public: - virtual void load(GLenum target, const Texture& texture,State& state) const; - virtual void subload(GLenum target, const Texture& texture,State& state) const; - }; - - void setSubloadCallback(SubloadCallback* cb) { _subloadCallback = cb; _subloadMode = cb ? USE_CALLBACK:OFF; } - - SubloadCallback* getSubloadCallback() { return _subloadCallback.get(); } - - const SubloadCallback* getSubloadCallback() const { return _subloadCallback.get(); } - - - /** 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 diff --git a/src/Demos/osgprerender/osgprerender.cpp b/src/Demos/osgprerender/osgprerender.cpp index d79adae3c..23951d6ea 100644 --- a/src/Demos/osgprerender/osgprerender.cpp +++ b/src/Demos/osgprerender/osgprerender.cpp @@ -23,7 +23,6 @@ #include #include - class MyAppCallback : public osg::NodeCallback { public: @@ -284,6 +283,119 @@ class MyGeometryCallback : }; +// Custom Texture subload callback, just acts the the standard subload modes in osg::Texture right now +// but code be used to define your own style callbacks. +class MyTextureSubloadCallback : public osg::Texture::SubloadCallback +{ + public: + virtual void load(GLenum target, const osg::Texture& texture,osg::State&) const + { + osg::notify(osg::INFO)<<"doing load"<0)?subloadImageWidth:texture.getImage()->s(); + GLsizei height = (subloadImageHeight>0)?subloadImageHeight:texture.getImage()->t(); + + int subloadTextureOffsetX; + int subloadTextureOffsetY; + texture.getSubloadTextureOffset(subloadTextureOffsetX,subloadTextureOffsetY); + + int textureWidth; + int textureHeight; + texture.getSubloadTextureSize(textureWidth, textureHeight); + + bool sizeChanged = false; + if (textureWidth==0) + { + // need to calculate texture dimension + sizeChanged = true; + textureWidth = 1; + for (; textureWidth < (static_cast(subloadTextureOffsetX) + width); textureWidth <<= 1) {} + } + + if (textureHeight==0) + { + // need to calculate texture dimension + sizeChanged = true; + textureHeight = 1; + for (; textureHeight < (static_cast(subloadTextureOffsetY) + height); textureHeight <<= 1) {} + } + + if (sizeChanged) + { + texture.setSubloadTextureSize(textureWidth, textureHeight); + } + + // reserve appropriate texture memory + glTexImage2D(target, 0, texture.getInternalFormatValue(), + textureWidth, textureHeight, 0, + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + NULL); + + + glPixelStorei(GL_UNPACK_ROW_LENGTH,texture.getImage()->s()); + + + glTexSubImage2D(target, 0, + subloadTextureOffsetX, subloadTextureOffsetY, + width, height, + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + texture.getImage()->data(subloadImageOffsetX,subloadImageOffsetY)); + + glPixelStorei(GL_UNPACK_ROW_LENGTH,0); + + } + + virtual void subload(GLenum target, const osg::Texture& texture,osg::State&) const + { + osg::notify(osg::INFO)<<"doing subload"<s()); + + int subloadTextureOffsetX; + int subloadTextureOffsetY; + texture.getSubloadTextureOffset(subloadTextureOffsetX,subloadTextureOffsetY); + + int subloadImageOffsetX; + int subloadImageOffsetY; + texture.getSubloadImageOffset(subloadImageOffsetX,subloadImageOffsetY); + + int subloadImageWidth; + int subloadImageHeight; + texture.getSubloadImageSize(subloadImageWidth,subloadImageHeight); + + glTexSubImage2D(target, 0, + subloadTextureOffsetX, subloadTextureOffsetY, + (subloadImageWidth>0)?subloadImageWidth:texture.getImage()->s(), (subloadImageHeight>0)?subloadImageHeight:texture.getImage()->t(), + (GLenum) texture.getImage()->getPixelFormat(), (GLenum) texture.getImage()->getDataType(), + texture.getImage()->data(subloadImageOffsetX,subloadImageOffsetY)); + + glPixelStorei(GL_UNPACK_ROW_LENGTH,0); + } +}; + + + + osg::Node* createPreRenderSubGraph(osg::Node* subgraph) { @@ -348,28 +460,13 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph) image->setInternalTextureFormat(GL_RGBA); osg::Texture* texture = new osg::Texture; - texture->setSubloadMode(osg::Texture::IF_DIRTY); + //texture->setSubloadMode(osg::Texture::IF_DIRTY); + texture->setSubloadCallback(new MyTextureSubloadCallback()); texture->setImage(image); texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); -// { -// // set up the second tex coord array for the an additional texture -// // to add texture to the flag. -// polyGeom->setTexCoordArray(1,texcoords); -// -// osg::Image* overlay_image = osgDB::readImageFile("tank.rgb"); -// osg::Texture* overlay_texture = new osg::Texture; -// overlay_texture->setImage(overlay_image); -// stateset->setTextureAttributeAndModes(1, overlay_texture,osg::StateAttribute::ON); -// -// osg::TexEnv* overlay_texenv = new osg::TexEnv; -// overlay_texenv->setMode(osg::TexEnv::BLEND); -// overlay_texenv->setColor(osg::Vec4(0.3f,0.3f,0.3f,1.0f)); -// stateset->setTextureAttribute(1, overlay_texenv); -// } - polyGeom->setStateSet(stateset); polyGeom->setAppCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f)); @@ -381,10 +478,8 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph) parent->setAppCallback(new MyAppCallback(subgraph)); -// parent->setCullCallback(new MyCullCallback(subgraph,texture)); parent->setCullCallback(new MyCullCallback(subgraph,image)); -// parent->addChild(billboard); parent->addChild(geode); return parent; diff --git a/src/osg/ImpostorSprite.cpp b/src/osg/ImpostorSprite.cpp index 755aab09a..00fda605d 100644 --- a/src/osg/ImpostorSprite.cpp +++ b/src/osg/ImpostorSprite.cpp @@ -254,6 +254,8 @@ ImpostorSprite* ImpostorSpriteManager::createOrReuseImpostorSprite(int s,int t,i stateset->setAttributeAndModes( _alphafunc.get(), StateAttribute::ON ); Texture* texture = osgNew Texture; + texture->setFilter(Texture::MIN_FILTER,Texture::LINEAR); + texture->setFilter(Texture::MAG_FILTER,Texture::LINEAR); stateset->setTextureAttributeAndModes(0,texture,StateAttribute::ON); stateset->setTextureAttribute(0,_texenv.get());