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 <[email protected]> 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 > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

