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