Here's some VBO code from my P3D Model lib :
Code:
procedure TP3DModel.UploadVBOS;
var
VerticiesSize : uint32;
NormalsSize : uint32;
UVsSize : uint32;
VertexBonesSize : uint32;
VertexRelToJointSize : uint32;
CurrentOffset : uint32;
TotalSize : uint32;
begin
if FLoaded and not FVBOUploaded then
begin
//Generate VBOs
glGenBuffers(1, @VBO);
VerticiesSize := length(mesh.Vertex) * sizeof(tvertex);
NormalsSize := length(mesh.Normal) * sizeof(tvertex);
UVsSize := length(mesh.UV) * sizeof(TVector2f);
VertexBonesSize := length(mesh.VertexBones) * sizeof(tvector);
VertexRelToJointSize := length(mesh.VertexRelToJoint) * sizeof(tvector);
VBOVerticesOffset := 0;
VBONormalsOffset := VerticiesSize;
VBOUVsOffset := VBONormalsOffset + NormalsSize;
VBOVertexBonesOffset := VBOUVsOffset + UVsSize;
VBOVertexRelToJointOffset := VBOVertexBonesOffset + VertexBonesSize;
TotalSize := VerticiesSize + NormalsSize + UVsSize + VertexBonesSize + VertexRelToJointSize;
//bind and upload data
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, TotalSize , nil , GL_STATIC_DRAW); //allocate memory for buffer
//load in seperate buffers at correct offsets
glBufferSubData(GL_ARRAY_BUFFER, VBOVerticesOffset, VerticiesSize , @mesh.Vertex[0]);
glBufferSubData(GL_ARRAY_BUFFER, VBONormalsOffset, NormalsSize , @mesh.normal[0]);
glBufferSubData(GL_ARRAY_BUFFER, VBOUVsOffset, UVsSize , @mesh.UV[0]);
glBufferSubData(GL_ARRAY_BUFFER, VBOVertexBonesOffset, VertexBonesSize , @mesh.VertexBones[0]);
glBufferSubData(GL_ARRAY_BUFFER, VBOVertexRelToJointOffset, VertexRelToJointSize , @mesh.VertexRelToJoint[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//create index vbo
glGenBuffers(1, @VBOIndicies);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOIndicies);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, length(Mesh.Indicies)*sizeof(GLuint), @mesh.Indicies[0], GL_STATIC_DRAW);
glbindbuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
end;
end;
procedure TP3DModel.DeleteVBOS;
begin
if FVBOUploaded then
begin
glDeleteBuffers(1, @VBO);
glDeleteBuffers(1, @VBOIndicies);
FVBOUploaded := false;
VBO := 0;
VBOIndicies := 0;
end;
end;
and here's how it renders :
Code:
procedure TP3DModel.RenderDynamic;
var
i1, i2, k, m: integer;
currentMaterial: integer;
currentShaderId: integer;
temptime: single;
attribname : string;
v : TVector;
begin
//enable shader
FArmatureShader.Enable;
if FDynamicRenderMode = DRMVBO then
begin
//Bind VBO Before setting pointers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//enable Attrib Arrays VBO
glEnableVertexAttribArray(FModelManagerLink^.AttribNormals);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertices);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertexRelToJoint);
glEnableVertexAttribArray(FModelManagerLink^.AttribUVs);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertexBones);
//set attrib pointers VBO
glVertexAttribPointer(FModelManagerLink^.AttribVertices,3,GL_FLOAT,false,0,nil);
glVertexAttribPointer(FModelManagerLink^.AttribNormals,3,GL_FLOAT,false,0,pglvoid(VBONormalsOffset));
glVertexAttribPointer(FModelManagerLink^.AttribUVs,2,GL_FLOAT,false,0,pglvoid(VBOUVsOffset));
glVertexAttribPointer(FModelManagerLink^.AttribVertexBones,4,GL_FLOAT,false,0,pglvoid(VBOVertexBonesOffset));
glVertexAttribPointer(FModelManagerLink^.AttribVertexRelToJoint,4,GL_FLOAT,false,0,pglvoid(VBOVertexRelToJointOffset));
//bind index buffer for rendering
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOIndicies);
end;
if FDynamicRenderMode = DRMAttribArray then
begin
//enable the attrib arrays used in shader
glEnableVertexAttribArray(FModelManagerLink^.AttribNormals);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertices);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertexRelToJoint);
glEnableVertexAttribArray(FModelManagerLink^.AttribUVs);
glEnableVertexAttribArray(FModelManagerLink^.AttribVertexBones);
//point the arrays at the data in system memory
glVertexAttribPointer(FModelManagerLink^.AttribVertices,3,GL_FLOAT,false,0,@Mesh.Vertex[0][0]);
glVertexAttribPointer(FModelManagerLink^.AttribNormals,3,GL_FLOAT,false,0,@Mesh.Normal[0][0]);
glVertexAttribPointer(FModelManagerLink^.AttribUVs,2,GL_FLOAT,false,0,@Mesh.UV[0][0]);
glVertexAttribPointer(FModelManagerLink^.AttribVertexBones,4,GL_FLOAT,false,0,@Mesh.VertexBones[0][0]);
glVertexAttribPointer(FModelManagerLink^.AttribVertexRelToJoint,4,GL_FLOAT,false,0,@Mesh.VertexRelToJoint[0][0]);
end;
//i3 := round((SDL_GetTicks/10)) mod 100;
inc(i7);
if i7 >= length(Self.Armature.Actions[0].AnimFrames) then i7 := 0;
//bind uniforms for mesh (can only bind after shader is bound)
if (FModelManagerLink^.SkinningMode = SMQuat) or (FModelManagerLink^.SkinningMode = SMDualQuat) then
begin
glUniform4fv(FModelManagerLink^.UPos,31,@armature.Actions[0].AnimFrames[i7].BonePos[0]);
glUniform4fv(FModelManagerLink^.URot,31,@armature.Actions[0].AnimFrames[i7].BoneRot[0]);
end else
if (FModelManagerLink^.SkinningMode = SMMatrix) then
begin
gluniformmatrix4fv(FModelManagerLink^.UMat,31,false,@armature.Actions[0].AnimFrames[i7].BoneMatrix[0][0][0]);
end;
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, TextureID );
if DynamicRenderMode = DRMVBO then
glDrawElements( GL_TRIANGLES,Mesh.IndexCount, GL_UNSIGNED_INT, nil) else
if DynamicRenderMode = DRMAttribArray then
glDrawElements( GL_TRIANGLES,Mesh.IndexCount, GL_UNSIGNED_INT, @Mesh.Indicies[0]);
FArmatureShader.disable;
if FDynamicRenderMode = DRMVBO then
begin
gldisableVertexAttribArray(FModelManagerLink^.AttribNormals);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertices);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertexRelToJoint);
gldisableVertexAttribArray(FModelManagerLink^.AttribUVs);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertexBones);
glbindbuffer(GL_ARRAY_BUFFER,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
end;
if FDynamicRenderMode = DRMAttribArray then
begin
gldisableVertexAttribArray(FModelManagerLink^.AttribNormals);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertices);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertexRelToJoint);
gldisableVertexAttribArray(FModelManagerLink^.AttribUVs);
gldisableVertexAttribArray(FModelManagerLink^.AttribVertexBones);
end;
end;
sorry if it's a bit confusing, it's designed for bone-animation on the GPU (called hardware skinning) but it does show how to populate a VBO, how to render from it and a reasonably good way of falling back on cards without VBO.
I'll try and help best I can if you get stuck, let me know.
Bookmarks