Using multiple vertex streams in vertex shaders

Started by
6 comments, last by HellRaiZer 17 years, 6 months ago
In Direct3D you can have a mesh stream consisting of pos,nrml,uv. In another stream you can have 1000 xyz positions. You can tell D3D to draw that 1 object x number of times using the second stream as an input to a vertex shader in one draw call. Does openGL have this type of setup? If so can someone let me know the extension to look at or what is all invloved in this? Any demos of this available? MSDN Documentation on streams
Advertisement
Well yes it does.


I guess you could make these connections:
IDirect3DDevice->CreateVertexBuffer   equalsglBinderBuffer(GL_ARRAY_BUFFER, textureID)glBufferData(GL_ARRAY_BUFFER, sizeInBytes, ptrToVertices, GL_STATIC_DRAW)and IDirect3DDevice->SetStreamSource  equalsglVertexPointer(3, GL_FLOAT, stride, offset);andIDirect3DDevice::DrawPrimitiveUP  equalsglDrawArraysIDirect3DDevice::DrawIndexedPrimitive  equalsglDrawElements  orglDrawRangeElements


Err.. well basiclly they're alot the same just different names. Shouldn't be to hard to figure out with the help of a reference.

Anyways, these are called Vertex Buffer Objects in OpenGL. And there's a tutorial about them on nehe.gamedev.net. They're part of OpenGL 1.5, so you have to bind the functions pointers yourself for some dumb reason, at least if you're on a windows machine.
I looked at the tutorial.. but it doesnt show how to do what im talking about.

Say I want to draw a billboard that has xyz and uv.
so thats 4 verts * ( 5(xyzuv) * 4 (sizeof(float)) ) that vbo would only be 80 bytes.

But say I had another VBO of 1000 xyz positions. 12000 bytes

When I got to draw, how can i tell openGL to draw that one billboard and use
the first 12 bytes of second vbo... then draw another and use 12 bytes offset
into the buffer.. and so on. From what I saw the vbos have to match one for one... repeating the billborad info

I want to mirror this..
if( SUCCEEDED( pd3dDevice->BeginScene() ) ){    // Set up the geometry data stream    UINT g_numInstancesToDraw = 1000;  //number of billboards    // g_VB_Geometry has my 80 bytes of billboard info    pd3dDevice->SetStreamSourceFreq(0,                (D3DSTREAMSOURCE_INDEXEDDATA | g_numInstancesToDraw));    pd3dDevice->SetStreamSource(0, g_VB_Geometry, 0,                D3DXGetDeclVertexSize( g_VBDecl_Geometry, 0 ));    // g_VB_InstanceData has my 12000 bytes of position data    // Set up the instance data stream    // for every instance drawn, send in one xyz position    pd3dDevice->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1));        pd3dDevice->SetStreamSource(1, g_VB_InstanceData, 0,                 D3DXGetDeclVertexSize( g_VBDecl_InstanceData, 1 ));    pd3dDevice->SetVertexDeclaration( ... );    pd3dDevice->SetVertexShader( ... );    pd3dDevice->SetIndices( ... );    // sends that position info straight into a awaiting vertex shader to be added to     // base vertex position (gl_Vertex).    pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0,                 g_dwNumVertices, 0, g_dwNumIndices/3 );        pd3dDevice->EndScene();}


and I want to be able to do this in a vertex shader.


//SHADER
uniform vec3 offset;

void main()
{
gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + offset);
}
//SHADER
Instancing doesn't exist in OGL in that form.

You can fake it however by using the immediate mode functions to set a number of vertex attributes and then just draw the VBO like normal.
I probably should have just asked this first. What then would be the fastest way
in OpenGL to draw a single tree mesh in N different positions with N different
rotations and scales. The tree mesh will never change, but the pos/rots and
scales will be grabbed from a quadtree and be view dependant so those will change
when the camera moves.

This is the way I have it now:

while(p != tqd->_render_query_results->end()){    tree_record& trec = *(*p);                    glPushMatrix();    glTranslatef(trec.x, trec.y, trec.z);    glRotatef(trec.heading, 0.0f, 0.0f, 1.0f);    if (!trec.attributes.empty())    {        scale = trec.attributes[0];        glScalef(scale, scale, scale);    }    tqd->_tree_model->render();    glPopMatrix();    ++p;}
Yes, from SetStreamSourceFreq I guess you are talking about instancing.
GL doesn't suffer like D3D because it runs in user mode while D3D runs in kernel mode. One error in D3D and you system hangs. Every single call to D3D drags performance down a lot.

Just render your tree as usual. Do redundent state checking.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Quote:Original post by phantom
Instancing doesn't exist in OGL in that form.

...


actually nvidia seems to provide an extension called nvx_instanced_arrays:

http://download.nvidia.com/developer/presentations/2006/gdc/2006-GDC_OpenGL_NV_exts.pdf

Quote:
actually nvidia seems to provide an extension called nvx_instanced_arrays:

http://download.nvidia.com/developer/presentations/2006/gdc/2006-GDC_OpenGL_NV_exts.pdf

There are no specs for this, and this isn't reported in the extension string.
If you try to get the functions out of the drivers, all of them are NULL. It exists (as a string) with all of its functions but non of them works. Drivers 91.47.

Even if the functions weren't NULL, i wouldn't expect them to work. At least this happens with NVX_conditional_render. :)

So wait for the specs, or wait for it to be promoted to non-experimental.

HellRaiZer
HellRaiZer

This topic is closed to new replies.

Advertisement