PDA

View Full Version : update object buffer with ATI VAO



nitzan
12-10-2002, 03:20 PM
How do I create/render more then one array object ?

more specifically, I created my array buffer by passing null to NewObjectBufferATI
and called glUpdateObjectBufferATI with my new data to create some array objects.

The problem is I dont understand how to call glDrawElementsArrayATI(). Can someone point to a good tutorial ?

this page: http://www.ati.com/developer/ATIVertexArrayObject.pdf does not explain how to draw more then one array object in the array buffer.

Unfortunately I seem to have done something wrong, and sometimes my program runs fine, sometimes it draws random triangles, and somtimes it does a mutli-color snow crash requiring a reboot!

Thanks,

Nitzan

Ysaneya
12-11-2002, 12:19 AM
I think you're confusing glDrawElementsArrayATI ( part of the ATI_element_array extension ) and the ATI_vertex_array_object extension. In the later, you just setup your pointers using the glArrayObjectATI function, instead of the standard glXXXPointer functions; and you render with a normal glDrawElements call.

The specification is your best friend to understand the in & outs of this extension: http://oss.sgi.com/projects/ogl-sample/registry/ATI/vertex_array_object.txt

I'm not really sure to understand your question about having more than one array object. Why would you need more than one VAO at the same time ? What do you want to do ?

Here's an example of setting up the pointers for vertex pos, tex coord 0 and normals:



struct s_vertex
{
float pos[3];
float normal[3];
float tex0[2];
};

glEnableClientState(GL_VERTEX_ARRAY);
glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * 3);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * (3 + 3));

glDrawElements(...)

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);



Y.


[This message has been edited by Ysaneya (edited 12-11-2002).]

nitzan
12-11-2002, 07:36 AM
How can I render more then one object with one VAO ? Lets say I have two textured cubes, each one textured with a different texture. How do I draw both of them using vao's ?

I tried creating a vao for each one (m_vao and m_vao2):

glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, 0);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * 3);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao, sizeof(float) * (3 + 3));
glDrawElements(...)

and

glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao2, 0);
glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(s_vertex), m_vao2, sizeof(float) * 3);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(s_vertex), m_vao2, sizeof(float) * (3 + 3));
glDrawElements(...)

But my program crashes. I figured it crashed becuase I need to pack the VAO's into an Object buffer, like it says here: http://www.ati.com/developer/ATIVertexArrayObject.pdf

Do I not need to do this ?

Nitzan

NitroGL
12-11-2002, 08:13 AM
Here's the function I use for building a VAO for my 3DS models:



void TDS_BuildVAO(TDS_Model_t *Model)
{
int i, j;

for(i=0;i<Model->NumMesh;i++)
{
int index=0;
float *data=NULL;

Model->Mesh[i].VAOID=glNewObjectBufferATI(sizeof(float)*Model->Mesh[i].NumVertex*14, NULL, GL_DYNAMIC_ATI);

if(HasMOB)
data=(float *)glMapObjectBufferATI(Model->Mesh[i].VAOID);
else
data=(float *)malloc(sizeof(float)*Model->Mesh[i].NumVertex*14);

if(data==NULL)
{
char temp[1024];

sprintf(temp, "VAO data buffer memory allocate/map failed for object: %s", Model->Mesh[i].Name);
MessageBox(NULL, temp, "OpenGL", MB_OK);

glFreeObjectBufferATI(Model->Mesh[i].VAOID);
Model->Mesh[i].VAOID=0;

break;
}

for(j=0;j<Model->Mesh[i].NumVertex;j++)
{
data[index++]=Model->Mesh[i].Vertex[3*j];
data[index++]=Model->Mesh[i].Vertex[3*j+1];
data[index++]=Model->Mesh[i].Vertex[3*j+2];

data[index++]=Model->Mesh[i].UV[2*j];
data[index++]=Model->Mesh[i].UV[2*j+1];

data[index++]=Model->Mesh[i].Tangent[3*j];
data[index++]=Model->Mesh[i].Tangent[3*j+1];
data[index++]=Model->Mesh[i].Tangent[3*j+2];

data[index++]=Model->Mesh[i].Binormal[3*j];
data[index++]=Model->Mesh[i].Binormal[3*j+1];
data[index++]=Model->Mesh[i].Binormal[3*j+2];

data[index++]=Model->Mesh[i].Normal[3*j];
data[index++]=Model->Mesh[i].Normal[3*j+1];
data[index++]=Model->Mesh[i].Normal[3*j+2];
}

if(HasMOB)
glUnmapObjectBufferATI(Model->Mesh[i].VAOID);
else
{
glUpdateObjectBufferATI(Model->Mesh[i].VAOID, 0, sizeof(float)*index, data, GL_DISCARD_ATI);
FREE(data);
}
}
}


And then I use this to render:



void TDS_DrawModel(TDS_Model_t *Model)
{
int i;

glColor3f(1.0f, 1.0f, 1.0f);

for(i=0;i<Model->NumMesh;i++)
{
int index=Model->Mesh[i].MaterialIndex;

if(index>=Model->NumMaterial)
{
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 1, Kd[0], Kd[1], Kd[2], 0.0f);
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 2, Ks[0], Ks[1], Ks[2], SpecularExpoent);
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 3, Ka[0], Ka[1], Ka[2], 0.0f);
}
else
{
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 1, Model->Material[index].Diffuse[0], Model->Material[index].Diffuse[1], Model->Material[index].Diffuse[2], 0.0f);
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 2, Model->Material[index].Specular[0], Model->Material[index].Specular[1], Model->Material[index].Specular[2], Model->Material[index].Shininess*100.0f);
glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB , 3, Model->Material[index].Ambient[0], Model->Material[index].Ambient[1], Model->Material[index].Ambient[2], 0.0f);

if(Model->Material[index].BaseTexID!=0)
{
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, Model->Material[index].BaseTexID);
}

if(Model->Material[index].BumpTexID!=0)
{
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, Model->Material[index].BumpTexID);
}
}

if(HasVAO&amp;&amp;Model->Mesh[i].VAOID)
{
glArrayObjectATI(GL_VERTEX_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, 0);
glEnableClientState(GL_VERTEX_ARRAY);

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 2, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*3);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE1_ARB);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*5);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE2_ARB);
glArrayObjectATI(GL_TEXTURE_COORD_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*8);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glArrayObjectATI(GL_NORMAL_ARRAY, 3, GL_FLOAT, sizeof(float)*14, Model->Mesh[i].VAOID, sizeof(float)*11);
glEnableClientState(GL_NORMAL_ARRAY);
}
else
{
glVertexPointer(3, GL_FLOAT, 0, Model->Mesh[i].Vertex);
glEnableClientState(GL_VERTEX_ARRAY);

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, Model->Mesh[i].UV);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(3, GL_FLOAT, 0, Model->Mesh[i].Tangent);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(3, GL_FLOAT, 0, Model->Mesh[i].Binormal);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glNormalPointer(GL_FLOAT, 0, Model->Mesh[i].Normal);
glEnableClientState(GL_NORMAL_ARRAY);
}

glDrawElements(GL_TRIANGLES, Model->Mesh[i].NumFace*3, GL_UNSIGNED_SHORT, Model->Mesh[i].Face);

glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}

glActiveTextureARB(GL_TEXTURE0_ARB);
}


HasVAO is a bool that tells the function weather or not the extension is supported, same with HasMOB only for the ATI_map_object_buffer extension. Everything else should be easy enough to figure out.

I create one object buffer per mesh in the model (one VAO ID per mesh).