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

Reply via email to