Hi all,

I am trying to show instanced geometry using a texture1D like a vertex
buffer. In fact I have it working more or less... but if my Texture 1D is
non power of two then my shader does not render some of the instances.
Attached is the code and two images, one with a non power of two texture(9
elements) that fails to draw last element, and other with 256 elements that
is drawn correctly.

I am using TransferFunction1D to pass my geometry array to a texture1D.
Anybody knows what I'm doing wrong? Of course I have set
texture->setResizeNonPowerOfTwoHint(false);

Thank you in advance!

Jordi.


-- 
Jordi Torres Fabra

gvSIG 3D blog
http://gvsig3d.blogspot.com
Instituto de Automática e Informática Industrial
http://www.ai2.upv.es

<<attachment: 9instances.png>>

<<attachment: 256instances.png>>

#include <osg/Texture1D>
#include <osg/TransferFunction>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Uniform>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/StateSetManipulator>
#include <osgGA/TrackballManipulator>
#include <osg/ShapeDrawable>
#include <iostream>


osg::Texture1D* geometryArrayToTexture(osg::Vec3dArray* geometryArray)
{
    osg::Texture1D* texture= new osg::Texture1D();
    osg::Image* im= new osg::Image();
    int size = geometryArray->size();
    osg::TransferFunction1D::ColorMap geometryMap;
    int value =0;

    for (osg::Vec3dArray::iterator it= geometryArray->begin(); it!= geometryArray->end();++it)
    {
        geometryMap[(float)value/(float)geometryArray->size()] = osg::Vec4((float)it->x(),(float)it->y(),(float)it->z(),0.);
        ++value;
    }
    if (geometryMap.empty())
    {
        std::cout<<"Error: No values read from geometry: "<<std::endl;
        return 0;
    }
    osg::TransferFunction1D* transferFunction = new osg::TransferFunction1D;
    transferFunction->allocate(geometryArray->size());
    transferFunction->assign(geometryMap);
    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::NEAREST);
    texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::NEAREST);
    texture->setResizeNonPowerOfTwoHint(false);
    im = transferFunction->getImage();
    im->setInternalTextureFormat(GL_RGBA32F_ARB);
    im->setPixelFormat(GL_RGBA);
    im->setDataType(GL_FLOAT);
    texture->setImage(im);
    return texture;
}

int main (int argc, char *argv[])
{

    const float halfDimX( .5 );
    const float halfDimZ( .5 );
    osg::Geometry *geom = new osg::Geometry();
    osg::Geometry *auxgeom = new osg::Geometry();
    osg::Vec3Array* instaceArray = new osg::Vec3Array;
    osg::Geode* g= new osg::Geode();

    //Create a geometry for use as instance
    //** Borrowed from osgdrawinstaced example**
    instaceArray->resize( 4 );
    geom->setVertexArray( instaceArray );
    geom->setUseDisplayList( false );
    geom->setUseVertexBufferObjects( true );

    // Geometry for a single quad.
    (*instaceArray)[ 0 ] = osg::Vec3( -halfDimX, 0., -halfDimZ );
    (*instaceArray)[ 1 ] = osg::Vec3( halfDimX, 0., -halfDimZ );
    (*instaceArray)[ 2 ] = osg::Vec3( halfDimX, 0., halfDimZ );
    (*instaceArray)[ 3 ] = osg::Vec3( -halfDimX, 0., halfDimZ );

    //SET number of instances
    float ninstances=9;

    // Use the DrawArraysInstanced PrimitiveSet and tell it to draw ninstances.
    geom->addPrimitiveSet( new osg::DrawArrays( GL_QUADS, 0, 4, ninstances ) );

    osg::BoundingBox bb( -1, -1, -1, 10., 10., 10. );
    geom->setInitialBound( bb );

    osg::Vec3dArray* geometryArray = new osg::Vec3dArray;

    // Fill geometry array
    for(int i=0;i<ninstances/sqrt(ninstances);++i)
        for(int j =0 ;j<ninstances/sqrt(ninstances);++j)
            geometryArray->push_back( osg::Vec3( i*2., 0., j*2.));

    //Uniform stuff
    osg::ref_ptr<osg::Texture1D> tex = geometryArrayToTexture(geometryArray);
    osg::ref_ptr<osg::StateSet>ss= g->getOrCreateStateSet();
    ss->setTextureAttribute(0, tex);
    osg::Uniform* guniform= new osg::Uniform("texturePos", tex );
    guniform->set(0);
    ss->addUniform(guniform);
    ss->addUniform(  new osg::Uniform( "color", osg::Vec4(1.,1.,0.,0.) ));
    ss->addUniform(  new osg::Uniform( "nInstances", ninstances));
    //shader
    std::string vertexSource =

            "#extension GL_EXT_gpu_shader4 : enable\n"
            "uniform sampler1D texturePos;\n"
            "uniform float nInstances;\n"
            "void main() \n"
            "{ \n"
            "vec4 pos= gl_Vertex+ vec4(texture1D(texturePos,(float(gl_InstanceID)/nInstances)).xyz,0.);\n"
            "gl_Position= gl_ModelViewProjectionMatrix*pos;\n"
            "} \n";
    std::string fragSource =
            "uniform vec4 color;\n"
            "void main() \n"
            "{ \n"
            "gl_FragColor = color; \n"
            "} \n";

    //shader activation stuff
    osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader();
    vertexShader->setType( osg::Shader::VERTEX );
    vertexShader->setShaderSource( vertexSource );
    osg::ref_ptr< osg::Shader > fragmentShader = new osg::Shader();
    fragmentShader->setType( osg::Shader::FRAGMENT);
    fragmentShader->setShaderSource( fragSource );
    osg::ref_ptr< osg::Program > program = new osg::Program();
    program->addShader( vertexShader.get() );
    program->addShader( fragmentShader.get() );
    ss->setAttribute( program.get(),osg::StateAttribute::ON );
    geom->setStateSet(ss);

    osg::Group* root= new osg::Group();
    root->addChild(g);
    g->addDrawable(geom);

    osgViewer::Viewer* viewer= new osgViewer::Viewer();
    viewer->setSceneData( root );
    viewer->addEventHandler(new osgViewer::StatsHandler());
    viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
    viewer->addEventHandler(new osgViewer::WindowSizeHandler());
    return viewer->run();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to