A Tale of OpenGL VBO Woe

Just starting out? Need help? Post your questions and find answers here.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

A Tale of OpenGL VBO Woe

Post by IdeasVacuum »

Try the two OpenGL samples below, originally created by ApplePi:

VBO_Test1.pb

Code: Select all

Structure TVertex
  x.f
  y.f
  z.f
EndStructure

#GL_COLOR_BUFFER_BIT                = $00004000
#GL_DEPTH_BUFFER_BIT                = $00000100
#GL_ARRAY_BUFFER                    = $8892
#GL_ELEMENT_ARRAY_BUFFER            = $8893
#GL_MODELVIEW                       = $1700
#GL_PROJECTION                      = $1701
#GL_SMOOTH                          = $1D01
#GL_DEPTH_TEST                      = $0B71
#GL_CULL_FACE                       = $0B44
#GL_STATIC_DRAW                     = $88E4
#GL_VERTEX_ARRAY                    = $8074
#GL_FLOAT                           = $1406
#GL_TRIANGLES                       = $0004
#GL_UNSIGNED_BYTE                   = $1401
#GL_UNSIGNED_SHORT                  = $1403
#GL_UNSIGNED_INT                    = $1405


OpenWindow(0, 10, 10, 640, 480, "OpenGL demo")
SetWindowColor(0, RGB(200,220,200))
OpenGLGadget(0, 20, 10, WindowWidth(0)-40 , WindowHeight(0)-20)
SetGadgetAttribute(0, #PB_OpenGL_SetContext, #True)

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
  Import "Opengl32.lib"
    wglGetProcAddress_(s.p-ascii) As "_wglGetProcAddress@4"
  EndImport
CompilerElse   
  Import "Opengl32.lib"
    wglGetProcAddress_(s.p-ascii) As "wglGetProcAddress"
  EndImport
CompilerEndIf

Prototype PfnGlGenBuffersProc(n.i, *buffers)
Global glGenBuffers.PfnGlGenBuffersProc
glGenBuffers = wglGetProcAddress_("glGenBuffers")

Prototype PfnGlBindbufferProc(target.l, buffer.i)
Global glBindBuffer.PfnGlBindbufferProc
glBindBuffer = wglGetProcAddress_("glBindBuffer")

Prototype PfnGlBufferDataProc(target.l, size.i, *Data_, usage.l)
Global glBufferData.PfnGlBufferDataProc
glBufferData = wglGetProcAddress_( "glBufferData" )

;Prototype PFNGLDRAWARRAYSPROC(mode.l, first.i, count.i)
;Global glDrawArrays.PFNGLDRAWARRAYSPROC
;glDrawArrays = wglGetProcAddress_("glDrawArrays")

glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_();
gluPerspective_(45.0, 800/600, 1.0, 60.0)
glMatrixMode_(#GL_MODELVIEW)
glTranslatef_(0, 0, -5)
glShadeModel_(#GL_SMOOTH)
glEnable_(#GL_DEPTH_TEST)
glEnable_(#GL_CULL_FACE)
glColor3f_(1.0, 0.7, 0.0)
glViewport_(0, 0, 800, 600)

Global BuffId.i,iiId.i

Dim Vertex.TVertex(3)
Vertex(0)\x = 1
Vertex(0)\y = -1
Vertex(0)\z = 0

Vertex(1)\x = -1
Vertex(1)\y = -1
Vertex(1)\z = 0

Vertex(2)\x = 1
Vertex(2)\y = 1
Vertex(2)\z = 0

Vertex(3)\x = -1
Vertex(3)\y = 1
Vertex(3)\z = 0
;=================================================================================
;=================================================================================
Dim index.l(5)
index(0) = 1
index(1) = 0
index(2) = 2
index(3) = 3
index(4) = 1
index(5) = 2


indexsize = 6*2 ;#GL_UNSIGNED_SHORT
indexsize = 6*4 ;#GL_UNSIGNED_INT

glGenBuffers(1, @BuffId)
glBindBuffer(#GL_ARRAY_BUFFER, BuffId)
glBufferData(#GL_ARRAY_BUFFER,SizeOf(TVertex)*4,@Vertex(0), #GL_STATIC_DRAW)
glBindBuffer(#GL_ARRAY_BUFFER,0)
glGenBuffers(1, @iiId)
glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, iiId)
glBufferData(#GL_ELEMENT_ARRAY_BUFFER, indexsize,@index(0),#GL_STATIC_DRAW)
glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, 0)

glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
Global rot.f = 1
glDisable_(#GL_CULL_FACE) ; to see the front and back faces

Repeat
              event = WindowEvent()
           If event = #PB_Event_CloseWindow
               quit = #True
           EndIf
          
         ;glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
         glClearColor_(0.2, 0.9, 0.2, 1)
         glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
          
         glEnableClientState_(#GL_VERTEX_ARRAY )
         glBindBuffer(#GL_ARRAY_BUFFER, BuffId)
         glVertexPointer_(3, #GL_FLOAT,0,0)
          
         glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, iiId)
         glPointSize_(20)
         glColor3d_(1,0,0)
         glRotatef_(rot.f, 0, 1, 0);
         ;glDrawElements_(#GL_POINTS,indexsize,#GL_UNSIGNED_INT,0)
         glDrawArrays_(#GL_POINTS, 0, 4)
         glBindBuffer(#GL_ELEMENT_ARRAY_BUFFER, 0);
         glBindBuffer(#GL_ARRAY_BUFFER,0);
         glDisableClientState_(#GL_VERTEX_ARRAY);
         
         SetGadgetAttribute(0, #PB_OpenGL_FlipBuffers, #True)

Until event = #PB_Event_CloseWindow
VBO_Test2.pb

Code: Select all

CompilerIf (#PB_Compiler_Processor = #PB_Processor_x86)
Import "Opengl32.lib"
 wglGetProcAddress_(s.p-ascii) As "_wglGetProcAddress@4"
EndImport
 CompilerElse   
Import "Opengl32.lib"
 wglGetProcAddress_(s.p-ascii) As "wglGetProcAddress"
EndImport
CompilerEndIf

Prototype PFNGLGENBUFFERSPROC ( n.i, *buffers)
Global glGenBuffers.PFNGLGENBUFFERSPROC
glGenBuffers = wglGetProcAddress_( "glGenBuffers" )
Prototype PFNGLBINDBUFFERPROC ( target.l, buffer.i)
Global glBindBuffer.PFNGLBINDBUFFERPROC
glBindBuffer = wglGetProcAddress_( "glBindBuffer" )
Prototype PFNGLBUFFERDATAPROC ( target.l, size.i, *Data_, usage.l)
Global glBufferData.PFNGLBUFFERDATAPROC
glBufferData = wglGetProcAddress_( "glBufferData" )

Prototype PFNGLGENVERTEXARRAYSPROC (n.i, *arrays)
Global glGenVertexArrays.PFNGLGENVERTEXARRAYSPROC
glGenVertexArrays = wglGetProcAddress_( "glGenVertexArrays" )

Prototype PFNGLBINDVERTEXARRAYPROC(n.i)
Global glBindVertexArray.PFNGLBINDVERTEXARRAYPROC
glBindVertexArray = wglGetProcAddress_( "glBindVertexArray" )

Prototype PFNGLENABLEVERTEXATTRIBARRAYPROC ( index.i )
Global glEnableVertexAttribArray.PFNGLENABLEVERTEXATTRIBARRAYPROC
glEnableVertexAttribArray = wglGetProcAddress_( "glEnableVertexAttribArray" )

Prototype PFNGLVERTEXATTRIBPOINTERPROC ( index.i, size.i, type.l, normalized.b, stride.i, *pointer )
Global glVertexAttribPointer.PFNGLVERTEXATTRIBPOINTERPROC
glVertexAttribPointer = wglGetProcAddress_( "glVertexAttribPointer" )

Prototype.i PFNGLCREATESHADERPROC ( type.l )
Global glCreateShader.PFNGLCREATESHADERPROC
glCreateShader = wglGetProcAddress_( "glCreateShader" )


Prototype PFNGLSHADERSOURCEPROC ( shader.i, count.i, *stringBuffer, *length )
Global glShaderSource.PFNGLSHADERSOURCEPROC
glShaderSource = wglGetProcAddress_( "glShaderSource" )

Prototype PFNGLCOMPILESHADERPROC ( shader.i )
Global glCompileShader.PFNGLCOMPILESHADERPROC
glCompileShader = wglGetProcAddress_( "glCompileShader" )

Prototype PFNGLATTACHSHADERPROC ( program.i, shader.i )
Global glAttachShader.PFNGLATTACHSHADERPROC
glAttachShader = wglGetProcAddress_( "glAttachShader" )


Prototype PFNGLLINKPROGRAMPROC ( program.i )
Global glLinkProgram.PFNGLLINKPROGRAMPROC
glLinkProgram = wglGetProcAddress_( "glLinkProgram" )

Prototype.i PFNGLCREATEPROGRAMPROC ( )
Global glCreateProgram.PFNGLCREATEPROGRAMPROC
glCreateProgram = wglGetProcAddress_( "glCreateProgram" )

Prototype PFNGLUSEPROGRAMPROC ( program.i )
Global glUseProgram.PFNGLUSEPROGRAMPROC
glUseProgram = wglGetProcAddress_( "glUseProgram" )

Prototype PFNGLDRAWARRAYSPROC ( mode.l, first.i, count.i )
Global glDrawArrays.PFNGLDRAWARRAYSPROC
glDrawArrays = wglGetProcAddress_( "glDrawArrays" )

Prototype PFNGLGETUNIFORMLOCATIONPROC ( program.i, name.p-ascii )
Global glGetUniformLocation.PFNGLGETUNIFORMLOCATIONPROC
glGetUniformLocation = wglGetProcAddress_( "glGetUniformLocation" )

Prototype PFNGLUNIFORMMATRIX4FVPROC ( location.i, count.i, transpose.b, *value )
Global glUniformMatrix4fv.PFNGLUNIFORMMATRIX4FVPROC
glUniformMatrix4fv = wglGetProcAddress_( "glUniformMatrix4fv" )



#GL_ARRAY_BUFFER = $8892
#GL_STATIC_DRAW = $88E4
#GL_VERTEX_SHADER = $8B31
#GL_FRAGMENT_SHADER = $8B30

Structure TVertex
  x.f
  y.f
  z.f
EndStructure


Structure Colors
  r.f
  g.f
  b.f
EndStructure

Dim matrix.f(3,3)
matrix(0,0)=1:   matrix(0,1)=0:matrix(0,2)=0:matrix(0,3)=0 ;// first column
matrix(1,0)=0:   matrix(1,1)=1:matrix(1,2)=0:matrix(1,3)=0 ;// second column
matrix(2,0)=0:   matrix(2,1)=0:matrix(2,2)=1:matrix(2,3)=0 ; // third column
matrix(3,0)=0:   matrix(3,1)=0:matrix(3,2)=0:matrix(3,3)=2 ;// fourth column

;the above is the simulation of this:
;GLfloat matrix[] = {
;      1.0f, 0.0f, 0.0f, 0.0f, // first column
;      0.0f, 1.0f, 0.0f, 0.0f, // second column
;      0.0f, 0.0f, 1.0f, 0.0f, // third column
;      -0.5f, 0.0f, 0.0f, 2.0f // fourth column
;   };

OpenWindow(0, 10, 10, 800, 600, "OpenGL demo ... color and translation with shader... use arrow keys and A/Z to translate in 3D space")
SetWindowColor(0, RGB(200,220,200))
OpenGLGadget(0, 20, 10, WindowWidth(0)-40 , WindowHeight(0)-20, #PB_OpenGL_Keyboard)
SetGadgetAttribute(0, #PB_OpenGL_SetContext, #True)

Global points_vbo.i, colors_vbo.i, vao.i

Dim Vertex.TVertex(2)
Dim color.Colors(2)
Vertex(0)\x = 0.0
Vertex(0)\y = 0.5
Vertex(0)\z = 0

Vertex(1)\x = 0.5
Vertex(1)\y = -0.5
Vertex(1)\z = 0

Vertex(2)\x = -0.5
Vertex(2)\y = -0.5
Vertex(2)\z = 0

color(0)\r = 1.0 :color(0)\g = 0.0 :color(0)\b = 0
color(1)\r = 0.0 :color(1)\g = 1.0 :color(1)\b = 0
color(2)\r = 0.0 :color(2)\g = 0.0 :color(2)\b = 1

Define vertex_shader.s
Define fragment_shader.s
Define *vbuff

;vertex shader source code
    vertex_shader = "#version 420"+#CRLF$
    vertex_shader + "layout(location = 0) in vec3 vertex_position;"+#CRLF$
    vertex_shader + "layout(location = 1) in vec3 vertex_colour;"+#CRLF$
    vertex_shader + "uniform mat4 matrix; // our matrix"+#CRLF$
    vertex_shader + "out vec3 colour;"+#CRLF$
    vertex_shader + "void main() {"+#CRLF$
    vertex_shader + "colour = vertex_colour;"+#CRLF$
    vertex_shader + "gl_Position = matrix * vec4(vertex_position, 1.0);"+#CRLF$
    vertex_shader + "}"
   
           
    ;fragment shader source code
    fragment_shader = "#version 420"+#CRLF$
    fragment_shader + "in vec3 colour;"+#CRLF$
    fragment_shader + "out vec4 frag_colour;"+#CRLF$
    fragment_shader + "void main() {"+#CRLF$
    fragment_shader + "frag_colour = vec4 (colour, 1.0);"+#CRLF$
    fragment_shader + "}"
       
    *vbuff = @vertex_shader
    *fbuff = @fragment_shader
   
glEnable_(#GL_DEPTH_TEST); // enable depth-testing
;glDepthFunc_(#GL_LESS); // depth-testing interprets a smaller value as "closer"

;=================================================================================
glGenBuffers(1, @points_vbo) ; Vertex Buffer Object

glBindBuffer(#GL_ARRAY_BUFFER, points_vbo )
glBufferData(#GL_ARRAY_BUFFER,9 * SizeOf(float),@Vertex(0), #GL_STATIC_DRAW)

glGenBuffers (1, @colors_vbo);
glBindBuffer (#GL_ARRAY_BUFFER, colors_vbo);
glBufferData (#GL_ARRAY_BUFFER, 9 * SizeOf (float), @color(0), #GL_STATIC_DRAW);

glGenVertexArrays (1, @vao);
glBindVertexArray (vao);
glBindBuffer (#GL_ARRAY_BUFFER, points_vbo);
glVertexAttribPointer (0, 3, #GL_FLOAT, #GL_FALSE, 0, #Null);
glBindBuffer (#GL_ARRAY_BUFFER, colors_vbo);
glVertexAttribPointer (1, 3, #GL_FLOAT, #GL_FALSE, 0, #Null);
;ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
;=================================================================================

Global vs = glCreateShader(#GL_VERTEX_SHADER);
glShaderSource(vs, 1, @*vbuff, #Null) ;
glCompileShader(vs);
Global fs = glCreateShader(#GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, @*fbuff, #Null);
glCompileShader(fs)                          ;

Global shader_programme = glCreateProgram();
glAttachShader(shader_programme, fs);
glAttachShader(shader_programme, vs);
glLinkProgram(shader_programme)     ;


glEnable_(#GL_CULL_FACE); // cull face
   glCullFace_(#GL_BACK); // cull back face
   glFrontFace_(#GL_CW); // GL_CCW for counter clock-wise
   
   rot.f = 1   
   SetActiveGadget(0)
   Repeat
    
     Event = WaitWindowEvent()
     If Event = #PB_Event_Gadget And EventGadget() = 0
   If EventType() = #PB_EventType_KeyDown
     
            key = GetGadgetAttribute(0,#PB_OpenGL_Key )
            ;If key = 38 ; Up arrow key
            If key = #PB_Shortcut_Up
               matrix(3,1) + 0.1
               
               ElseIf key = #PB_Shortcut_Down ; Down arrow key 
                 matrix(3,1) - 0.1
               ElseIf key = #PB_Shortcut_Left ; Left arrow key
                 matrix(3,0) - 0.1
               ElseIf key = #PB_Shortcut_Right ; Left arrow key
                 matrix(3,0) + 0.1
               ElseIf key = #PB_Shortcut_A ; Left arrow key
                 matrix(3,3) - 0.1
               ElseIf key = #PB_Shortcut_Z ; Left arrow key
                 matrix(3,3) + 0.1     
            ElseIf key = #PB_Shortcut_Escape ;  Esc key to exit

             quit = 1
            EndIf 
     EndIf
   EndIf 
   
    
  glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT);
  glRotatef_(rot, 0, 1, 0)                             ;
  matrix_location.l = glGetUniformLocation(shader_programme, "matrix");
   glUseProgram (shader_programme);
   glUniformMatrix4fv (matrix_location, 1, #GL_FALSE, @matrix(0,0));
   
   glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT);
   glViewport_(0, 0, 800, 600);
  ;glUseProgram(shader_programme) 
  glBindVertexArray(vao);
  ;draw points 0-3 from the currently bound VAO With current in-use shader
  glDrawArrays(#GL_TRIANGLES, 0, 3);
   
  SetGadgetAttribute(0, #PB_OpenGL_FlipBuffers, #True)
  Delay(16)
 
Until Event = #PB_Event_CloseWindow Or quit = 1
Test 1 works fine on my PC (Win7 x64) but Test 2 fails at glGenBuffers() [line 169]

To my dismay, the difference between success and failure is the place where the OpenGL Lib Prototyping is included. In Test 1, it is included after the OpenGL Gadget has been defined. In Test 2, Prototyping is included at the top of the file. Move that block of code to after the OpenGL Gadget has been defined and Test 2 works.......

My Project is large and fairly efficiently defined with Procedures - but you can't define a Prototype within a Procedure.......

Am I missing an obvious solution?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: A Tale of OpenGL VBO Woe

Post by Samuel »

The reason Test 2 is failing is because you're attempting to load OpenGL functions without a valid OpenGL context.

Something like this should work.

Code: Select all

;Define your prototypes.
Prototype PFNGLGENBUFFERSPROC ( n.i, *buffers)
Prototype PFNGLBINDBUFFERPROC ( target.l, buffer.i)
Prototype PFNGLBUFFERDATAPROC ( target.l, size.i, *Data_, usage.l)
etc....

;Create Window with a OpenGL Context.

;Call Procedure that uses wglGetProcAddress_() to load OpenGL functions.

;Rest of program.......
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: A Tale of OpenGL VBO Woe

Post by IdeasVacuum »

Thanks Samuel!

I will give that a go now :D
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: A Tale of OpenGL VBO Woe

Post by IdeasVacuum »

.... and indeed, that is a great solution, thank you again. 8)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply