Hi Mateusz,

Take in mind that 1D textures are limited to 8192 texels, if you need more
you should use a TextureBufferObject. I've attached a simple example
getting postions from a texture 1D. The TransferFunction used is not
necessary.

Hope it helps.



2013/6/20 Mateusz Janiak <mati_jan...@wp.pl>

> Hi,
>
> I have a large static scene to render - it will not change in time. It can
> contain even 1M spheres representing atoms in a particular material. I have
> read a lot about instanced drawing and went through examples:
> osgdrawinstanced
> osgshaders
>
> but I can not to figure out how can I pass world positions for my sphere
> prototype instances. I am rather not familiar with plain OpenGL and GLSL,
> but what I have figured out till now is that I have to follow seweral steps
> in general:
> 1. Create my geometry drawable (simple sphere in my case using VBO)
> 2. Create vertex shader program tha would populate my sphere prototype on
> GPU side with defined number of instances
> 3. Attach to vertex shader a buffer? texture? some data representing
> positions of instances of this particular sphere type in world.
> 4. Sample buffer, texture with respect to gl_InstanceID to obtain sphere
> position at VS side
>
> I think I could perform such operation for each sphere type in scene
> separately as there would be about 5 different spheres (radius). Is this
> correct approach? Or I should avoid creating several independent programs
> and try to create one doing all the stuff for different spheres?
>
> I would appriciate if anyone could guide me through process of binding
> sphere`s world positions to vertext. As mentioned I was trying to attach to
> my geometry 1D texture filled with positions of sphere instances and read
> it in shader according to gl_InstanceID for obtaning proper position,
> hovewer I am doing something wrong and I see just one sphere with strange
> colors on it. I think my sampling and binding fails but I have no ide how
> could I investigate the problem and "debug" shader if it is even posiible.
>
> I will just attach fragments of code I think are crucial for this task:
> VS code
>
> Code:
> #version 330 core
> uniform sampler1D tex;
> uniform int texSize;
> void main(void) {
> /* fetch instance position from texture buffer and add the local vertex
> coordinate to it ? using gl_InstanceID and texSize to properly determine
> position of my instance coordinates*/
> vec4 ObjectSpacePosition = texture(tex, gl_InstanceID / float(texSize)) +
> vec4(gl_Vertex, 1.0);
> ObjectSpacePosition.w = 1.0;
>
> /* transform into view space */
> vec4 ViewSpacePosition = gl_ModelViewMatrix * ObjectSpacePosition;
>
> /* transform into clip space */
> gl_Position = gl_ProjectionMatrix * ViewSpacePosition;
> }
>
>
>
> Texture with position coordinates:
>
>
> Code:
> unsigned int instCount = ...;
>
> osg::Image* image = new osg::Image;
>
> // allocate the image data, instCount x 1 x 1 with 4 rgba floats -
> equivalent to a Vec4!
> image->allocateImage(instCount,1,1,GL_RGBA,GL_FLOAT);
> image->setInternalTextureFormat(GL_RGBA);
>
> // fill in the image data
> osg::Vec4* dataPtr = (osg::Vec4*)image->data();
> for( osg::Vec3 pos : InstancePositions )
> {
> *dataPtr++ = osg::Vec4(pos, 1.0);
> }
>
> osg::Texture1D* texture = new osg::Texture1D;
> texture->setWrap(osg::Texture1D::WRAP_S,osg::Texture1D::WrapMode::REPEAT);
> texture->setFilter(osg::Texture1D::MIN_FILTER,osg::Texture1D::NEAREST);
> texture->setImage(image);
>
>
>
> And finally state set for geometry:
>
>
> Code:
> osg::ref_ptr< osg::StateSet > s = new osg::StateSet;
>
> // setting proper GL modes
> s->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
> s->setMode(GL_LIGHTING, osg::StateAttribute::ON);
> s->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
> s->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
> s->setMode(GL_BLEND, osg::StateAttribute::OFF);
>
> //create shader
> osg::ref_ptr< osg::Shader > nVertexShader = new osg::Shader();
> nVertexShader->setType( osg::Shader::VERTEX );
> nVertexShader->setShaderSource( ... );
>
> osg::ref_ptr< osg::Program > program = new osg::Program();
> program->addShader( nVertexShader.get() );
>
> s->setAttribute( program.get(), osg::StateAttribute::ON |
> osg::StateAttribute::PROTECTED );
>
> //set texture for node which I want to sample in shader for positions
> s->setTextureAttribute(0,texture,osg::StateAttribute::OVERRIDE);
>
> s->setTextureMode(0,GL_TEXTURE_1D,osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
>
> s->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
>
> s->setTextureMode(0,GL_TEXTURE_3D,osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE);
> // size of texture so I can rescale my gl_InstanceID to proper float value
> in shader for texture sampling
> osg::Uniform* texSize = new osg::Uniform("texSize",instCount);
> s->addUniform(texSize);
> //sets the texture? not sure about this line
> s->addUniform(new osg::Uniform("tex", 0));
>
>
>
>
> I have read about uniform arrays but they have some limitations as far as
> I have diged about them, so I thought this would be a better way to load
> texture once to GPU and then use it all the time. Once again - if someone
> keen with VS, OpenGL, GLSL could guide me with this task I would be very
> gratefull. I think such example could be also a good startup for others
> rendering such big scenes if provided general steps are posiible at all.
>
> Thank you!
>
> Cheers,
> Mateusz[/code]
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=54715#54715
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users@lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>



-- 
Jordi Torres
#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 + 0.5)/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
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to