Results 1 to 10 of 16

Thread: Optimize drawing 10.000 2D-lines with VBO?

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Ok, I'll give you some tips then.

    First of all, can you show me your complete sourcecode? The last post only contains the render code, not the creation of the buffer etc..

    The most confusing part of VBO's is that it uses the functions that were meant for vertex array's. I see that you are passing a pointer to the array to glVertexPointer() and glColorPointer(). This is correct for vertex array's but NOT for VBO's. The functions are used differently. You must pass the data in a glBufferDataARB() call and use 0 as the last parameter for both glVertexPointer and glColorPointer().

    Just google some more and ask more specific questions. You could also check the following tutorial:

    http://playcontrol.net/ewing/jibberj...er_object.html

    I know that VBO's are confusing. You just HAVE to go thourgh one of the tutorials, write down the functions that are used and figure out what happens exactly.

    I may write a VBO tutorial one day, for pascal. Right now, I dont have time for that.

    Good luck!
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  2. #2
    Thanks for giving me tips. I have been playing with it all day again and this is what I have at the moment (but still nothing is drawn)
    (is from: http://www.ozone3d.net/tutorials/opengl_vbo_p2.php, my translation from C++ to Delphi). I checked it with your tutorial and did not see any strange things. My viewwindow is set up from (0,0) - (1024,76

    Code:
    var
      vc: Integer;
      ColorSize, PositionSize : Integer;
    const
      BufferSize = 2;
      POSITION_OBJECT = 0;
      COLOR_OBJECT = 1;
    var
      BufferName: array [0..BufferSize-1] of GLuint;
    begin
    
      glGenBuffersARB := wglGetProcAddress('glGenBuffersARB');
      glBindBufferARB := wglGetProcAddress('glBindBufferARB');
      glBufferDataARB := wglGetProcAddress('glBufferDataARB');
      glDeleteBuffersARB := wglGetProcAddress('glDeleteBuffersARB');
    
      PositionSize := length(VertexBuffer) * SizeOf(TVertex2f);
      ColorSize := length(ColorBuffer) * SizeOf(TColor3f);
    
      vc := Length(VertexBuffer);
    
      // allocate a new buffer
      glGenBuffersARB(1, @BufferName[COLOR_OBJECT]);
      // bind the buffer object to use
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferName[COLOR_OBJECT]);
      glBufferDataARB(GL_ARRAY_BUFFER_ARB, ColorSize, @ColorBuffer[0], GL_STREAM_DRAW);
      glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
    
      glGenBuffersARB(1, @BufferName[POSITION_OBJECT]);
      glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferName[POSITION_OBJECT]);
      glBufferDataARB(GL_ARRAY_BUFFER_ARB, PositionSize, @VertexBuffer[0], GL_STREAM_DRAW);
      glVertexPointer(2, GL_FLOAT, 0, 0);
    
      glEnableClientState(GL_VERTEX_ARRAY);
      glEnableClientState(GL_COLOR_ARRAY);
    
      glDrawArrays(GL_TRIANGLES, 0, vc);
    
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_COLOR_ARRAY);
    with data:
    Code:
    type
      TVertex2f = record
        X, Y: TPositionType;
      end;
    
      TColor3f = record
       R, G, B: GLubyte;
      end;
    
    const
      VertexBuffer: array [0..5] of TVertex2f = (
        (X : 0; Y : 0;),
        (X : 200; Y : 0;),
        (X : 200; Y : 200;),
        (X : 200; Y : 200;),
        (X : 0;  Y : 200;),
        (X : 0; Y : 0;)
      );
      ColorBuffer: array [0..5] of TColor3f = (
        (R : 255; G : 0; B : 0),
        (R : 255; G : 255; B : 0),
        (R : 0; G : 255; B : 0),
        (R : 0; G : 255; B : 0),
        (R : 0; G : 0; B : 255),
        (R : 255; G : 0; B : 0)
      );
    Last edited by WhatJac3; 23-09-2010 at 09:47 PM. Reason: additional information

  3. #3
    I noticed the following line:

    Code:
      glBufferDataARB(GL_ARRAY_BUFFER_ARB, ColorSize, @ColorBuffer[0], GL_STREAM_DRAW);
    Have a look at the last GL_STREAM_DRAW parameter. I couldn't find official documentation of this function, so I just quote the tutorial:

    "stream" means the data will be changed every frame (specified once and used once).
    I suggest you change it to GL_STATIC_DRAW, because I think GL_STREAM_DRAW will throw away your data after it is rendered once.

    The rest of your code looks ok.

    Hope this helps.

    Edit: About the WYSIWYG problem, you have to enable those buttons in your profile. Forum -> Forum Actions -> General settings, and then scroll down until you see the "Message Editor Interface" optoin.
    Last edited by chronozphere; 24-09-2010 at 06:43 AM.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  4. #4
    Well I finally solved it. The GL_STREAM_DRAW was not the solution. My problem was that I was using multiple libraries. The default 'OpenGL' from Delphi combined with the dglOpenGL (and sometimes even GL library and copied GL functions from NeHe). The combination of this all made it impossible to use VBO's. So I removed all other code except for the dglOpenGL. Thanks for the help guys.

  5. #5
    Good to know you solved it.

    I'd suggest that you only use dglOpengl. It's the best set of headers out there IMHO.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  6. #6
    PGD Staff / News Reporter phibermon's Avatar
    Join Date
    Sep 2009
    Location
    England
    Posts
    524
    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.
    When the moon hits your eye like a big pizza pie - that's an extinction level impact event.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •