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