[osg-users] problem setting texture min/mag filter

Robert Osfield robert.osfield at gmail.com
Tue Feb 20 09:28:25 PST 2018


HI Antiro,

Thanks for the code example.  I don't have the time to test right
away.  A quick code review and I spotted that the image is 10x10 which
will be rescalled to nearest power of two with the default
construction of osg::Texture2D.  Most modern hardware supports non
power of two textures so it should be safe to enable this via:

  texture->setResizeNonPowerOfTwoHint(false);

Could you try this and let us know how you get on.

Robert.

On 20 February 2018 at 17:10, antiro black <antiro42 at gmail.com> wrote:
> Hi,
>
> I made an executable example based on the osgtexture2D example. I removed the code to render the different walls of the cube with the exception of the filter wall. I kept the rest as close to the original as possible. changes to the code have been marked using comments.
>
> Essentially all I'm doing is generating an input image instead of loading one.
>
>
> Code:
>
> #include <osg/Node>
> #include <osg/Geometry>
> #include <osg/Notify>
> #include <osg/MatrixTransform>
> #include <osg/Texture2D>
> #include <osg/DrawPixels>
> #include <osg/PolygonOffset>
> #include <osg/Geode>
>
> #include <osgDB/Registry>
> #include <osgDB/ReadFile>
>
> #include <osgText/Text>
>
> #include <osgViewer/Viewer>
>
> ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> //
> // filter wall and animation callback.
> //
>
> class FilterCallback : public osg::NodeCallback
> {
> public:
>
>     FilterCallback(osg::Texture2D* texture,osgText::Text* text,double delay=1.0):
>         _texture(texture),
>         _text(text),
>         _delay(delay),
>         _currPos(0),
>         _prevTime(0.0)
>     {
>         // start with a mip mapped mode to ensure that
>         _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_LINEAR);
>         _magFilterList.push_back(osg::Texture2D::LINEAR);
>         _textList.push_back("Tri-linear mip mapping (default filtering)\nsetFilter(MIN_FILTER,LINEAR_MIP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
>
>         _minFilterList.push_back(osg::Texture2D::NEAREST);
>         _magFilterList.push_back(osg::Texture2D::NEAREST);
>         _textList.push_back("Nearest filtering\nsetFilter(MIN_FILTER,NEAREST)\nsetFilter(MAG_FILTER,NEAREST)");
>
>         _minFilterList.push_back(osg::Texture2D::LINEAR);
>         _magFilterList.push_back(osg::Texture2D::LINEAR);
>         _textList.push_back("Linear filtering\nsetFilter(MIN_FILTER,LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
>
>         _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_NEAREST);
>         _magFilterList.push_back(osg::Texture2D::LINEAR);
>         _textList.push_back("nearest mip mapping (default filtering)\nsetFilter(MIN_FILTER,)\nsetFilter(MAG_FILTER,LINEAR)");
>
>         _minFilterList.push_back(osg::Texture2D::LINEAR_MIPMAP_NEAREST);
>         _magFilterList.push_back(osg::Texture2D::LINEAR);
>         _textList.push_back("bi-linear mip mapping\nsetFilter(MIN_FILTER,LINEAR_MIPMAP_NEAREST)\nsetFilter(MAG_FILTER,LINEAR)");
>
>         _minFilterList.push_back(osg::Texture2D::NEAREST_MIPMAP_LINEAR);
>         _magFilterList.push_back(osg::Texture2D::LINEAR);
>         _textList.push_back("bi-linear mip mapping\nsetFilter(MIN_FILTER,NEAREST_MIPMAP_LINEAR)\nsetFilter(MAG_FILTER,LINEAR)");
>
>
>         setValues();
>     }
>
>     virtual void operator()(osg::Node*, osg::NodeVisitor* nv)
>     {
>         if (nv->getFrameStamp())
>         {
>             double currTime = nv->getFrameStamp()->getSimulationTime();
>             if (currTime-_prevTime>_delay)
>             {
>                 // update filter modes and text.
>                 setValues();
>
>                 // advance the current position, wrap round if required.
>                 _currPos++;
>                 if (_currPos>=_minFilterList.size()) _currPos=0;
>
>                 // record time
>                 _prevTime = currTime;
>             }
>         }
>     }
>
>     void setValues()
>     {
>         _texture->setFilter(osg::Texture2D::MIN_FILTER,_minFilterList[_currPos]);
>         _texture->setFilter(osg::Texture2D::MAG_FILTER,_magFilterList[_currPos]);
>
>         _text->setText(_textList[_currPos]);
>     }
>
> protected:
>
>     typedef std::vector<osg::Texture2D::FilterMode> FilterList;
>     typedef std::vector<std::string>                TextList;
>
>     osg::ref_ptr<osg::Texture2D>    _texture;
>     osg::ref_ptr<osgText::Text>     _text;
>     double                          _delay;
>
>     FilterList                      _minFilterList;
>     FilterList                      _magFilterList;
>     TextList                        _textList;
>
>     unsigned int                    _currPos;
>     double                          _prevTime;
>
> };
>
> osg::Node* createFilterWall(osg::BoundingBox& bb,osg::Image *img)
> {
>     osg::Group* group = new osg::Group;
>
>     // left hand side of bounding box.
>     osg::Vec3 top_left(bb.xMin(),bb.yMin(),bb.zMax());
>     osg::Vec3 bottom_left(bb.xMin(),bb.yMin(),bb.zMin());
>     osg::Vec3 bottom_right(bb.xMin(),bb.yMax(),bb.zMin());
>     osg::Vec3 top_right(bb.xMin(),bb.yMax(),bb.zMax());
>     osg::Vec3 center(bb.xMin(),(bb.yMin()+bb.yMax())*0.5f,(bb.zMin()+bb.zMax())*0.5f);
>     float height = bb.zMax()-bb.zMin();
>
>     // create the geometry for the wall.
>     osg::Geometry* geom = new osg::Geometry;
>
>     osg::Vec3Array* vertices = new osg::Vec3Array(4);
>     (*vertices)[0] = top_left;
>     (*vertices)[1] = bottom_left;
>     (*vertices)[2] = bottom_right;
>     (*vertices)[3] = top_right;
>     geom->setVertexArray(vertices);
>
>     osg::Vec2Array* texcoords = new osg::Vec2Array(4);
>     (*texcoords)[0].set(0.0f,1.0f);
>     (*texcoords)[1].set(0.0f,0.0f);
>     (*texcoords)[2].set(1.0f,0.0f);
>     (*texcoords)[3].set(1.0f,1.0f);
>     geom->setTexCoordArray(0,texcoords);
>
>     osg::Vec3Array* normals = new osg::Vec3Array(1);
>     (*normals)[0].set(1.0f,0.0f,0.0f);
>     geom->setNormalArray(normals, osg::Array::BIND_OVERALL);
>
>     osg::Vec4Array* colors = new osg::Vec4Array(1);
>     (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
>     geom->setColorArray(colors, osg::Array::BIND_OVERALL);
>
>     geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));
>
>     osg::Geode* geom_geode = new osg::Geode;
>     geom_geode->addDrawable(geom);
>     group->addChild(geom_geode);
>
>
>     // set up the texture state.
>     osg::Texture2D* texture = new osg::Texture2D;
>     texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
>     texture->setImage(img); //////<-- setting image directly from ptr (original used osgDB::readImageFile() )
>
>     osg::StateSet* stateset = geom->getOrCreateStateSet();
>     stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
>
>     // create the text label.
>
>     osgText::Text* text = new osgText::Text;
>     text->setDataVariance(osg::Object::DYNAMIC);
>
>     text->setFont("fonts/arial.ttf");
>     text->setPosition(center);
>     text->setCharacterSize(height*0.03f);
>     text->setAlignment(osgText::Text::CENTER_CENTER);
>     text->setAxisAlignment(osgText::Text::YZ_PLANE);
>
>     osg::Geode* text_geode = new osg::Geode;
>     text_geode->addDrawable(text);
>
>     osg::StateSet* text_stateset = text_geode->getOrCreateStateSet();
>     text_stateset->setAttributeAndModes(new osg::PolygonOffset(-1.0f,-1.0f),osg::StateAttribute::ON);
>
>     group->addChild(text_geode);
>
>     // set the update callback to cycle through the various min and mag filter modes.
>     group->setUpdateCallback(new FilterCallback(texture,text));
>
>     return group;
>
> }
>
>
> osg::Node* createModel()
> {
>
>     // create the root node which will hold the model.
>     osg::Group* root = new osg::Group();
>
>     // turn off lighting
>     root->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
>
>     osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
>
> /////////// NEW CODE: ///////////////
>                 int w=10,h=10;
>                 GLubyte * pixels=(GLubyte*)calloc(w*h*3,sizeof(GLubyte));
>         int pixelCount=0;
>
>         for(int i=0;i<100;i++){
>                 int x=pixelCount%w;
>                 int y=int(pixelCount/w);
>
>                 int xy = y*w + x;
>                 //pixels[xy*3]=GLubyte(stoi(tile->ToConstScalarToken()->GetRawData()));
>                 pixels[xy*3]=GLubyte(unsigned(x<6?180:10));
>                 pixels[xy*3+1]=0;
>                 pixels[xy*3+2]=0;
>
>                 pixelCount++;
>         }
>         osg::Image* m_tileDataImg = new osg::Image;
>         m_tileDataImg->setImage(w,h,1,GL_RGB,GL_RGB,GL_UNSIGNED_BYTE,pixels,osg::Image::NO_DELETE);
> /////////// END NEW CODE: ///////////////
>
>     root->addChild(createFilterWall(bb,m_tileDataImg)); ///// <-- passing image ptr (original code used image filename)
>
>     return root;
> }
>
> int main(int , char **)
> {
>     // construct the viewer.
>     osgViewer::Viewer viewer;
>
>     // add model to viewer.
>     viewer.setSceneData( createModel() );
>
>     return viewer.run();
> }
>
>
>
>
> Note that the filter wall is on the side of the cube, so you have to rotate it before you see anything.
>
> The input image which I am generating is the following (verified by using osgDB::writeImageFile() to output it):
>
> [Image: https://i.imgur.com/8YUX0UD.png ]
> It might be too small to see, but the important part is that it contains only two colors.
>
>
> The result I get with nearest filtering:
> [Image: https://i.imgur.com/h6MIpI9.png ]
> Suddenly there is a band with an intermediate color which is not present in the input.
>
>
> The expected result (created by editing the screenshot):
> [Image: https://i.imgur.com/Plew0gD.png ]
>
> I'm not sure how the images translate to the mailing list, so just in case: this is the imgur album containing the three images: https://imgur.com/a/rNFu0
>
> Thank you!
>
> Cheers,
> antiro[img][/img]
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=72972#72972
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


More information about the osg-users mailing list