First VBO Program

I’m trying to get VBOs working - the code below is intended to draw a single white triangle. In fact, if I use the block of code marked “This works” (which uses Vertex and Index arrays not bound to VBOs), the triangle renders as expected. If I switch to the lines of code below marked “This does not work”, then I get nothing on screen. No errors are reported by glGetError. I’ve tried it on a GeForce 7600 and a GeForce 6150.

The code is meant to be linked against FLTK.

Much thanks for any assistance.

 
#define GL_GLEXT_PROTOTYPES // For OpenGL 1.5+ functionality
#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include <FL/gl.h>
#include <FL/glu.h>

#include "level1.hpp"
#include "plankrender.hpp"

#define PI     3.14159265f
#define Rad0   0.0f
#define Rad90  1.57079632f
#define Rad180 3.14159265f
#define Rad270 4.71238898f


class MyGlWindow : public Fl_Gl_Window
  {
  protected:
    void SetupViewport(void)
      {
      printf("OpenGL Vendor String: %s
",glGetString(GL_VENDOR));
      printf("OpenGL Renderer String: %s
",glGetString(GL_RENDERER));
      printf("OpenGL Version String: %s
",glGetString(GL_VERSION));
      glLoadIdentity();
      GLfloat height=h();
      GLfloat width=w(); 
      glViewport(0,0,(int)width,(int)height);
      if (height<1.0f) height=1.0f;
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(60.0f,width/height,1.0,400.0);      
      }
    GLuint BufObj[2];
    int Err;
    GLfloat V[9];
    GLushort Ind[3];
    void LoadScene(void)
      {
      V[0]=0.0f; V[1]=0.0f; V[2]=0.0f;
      V[3]=2.0f; V[4]=0.0f; V[5]=0.0f;
      V[6]=1.0f; V[7]=2.0f; V[8]=0.0f;
      Ind[0]=0;
      Ind[1]=1;
      Ind[2]=2;
      CheckError(1);
      glGenBuffers(2,BufObj);
      glBindBuffer(GL_ARRAY_BUFFER,BufObj[0]);
      glBufferData(GL_ARRAY_BUFFER,9*sizeof(GLfloat),V,GL_STATIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER,0);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,BufObj[1]);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER,3*sizeof(GLushort),Ind,GL_STATIC_DRAW);
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
      CheckError();
      }
    void UnloadScene(void)
      {
      CheckError();
      glDeleteBuffers(2,BufObj);
      CheckError();
      }
    void draw()
      {
      if (!valid())      // First time? init viewport, etc.
        {
        valid(1);
        SetupViewport();
        LoadScene();
        }
      glClear(GL_COLOR_BUFFER_BIT);
      glColor3f(1.0, 1.0, 1.0);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      glRotatef(CameraRot*180.0/PI,0.0f,1.0f,0.0f);
      glTranslatef(-Camera.X,-Camera.Y,-Camera.Z);
      CheckError();

// This works
      glEnableClientState(GL_VERTEX_ARRAY);                   CheckError();
      glVertexPointer(3,GL_FLOAT,0,V);                        CheckError();
      glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_SHORT,Ind);   CheckError();

// This does not work
//      glBindBuffer(GL_ARRAY_BUFFER,BufObj[0]);                CheckError();
//      glVertexPointer(3,GL_FLOAT,0,0);                        CheckError();
//      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,BufObj[1]);        CheckError();
//      glDrawElements(GL_TRIANGLES,3,GL_UNSIGNED_SHORT,0);     CheckError();

      Frame++;
      }
    void CheckError(bool PrintAlways=false)
      {
      GLenum err=glGetError();
      if (err!= GL_NO_ERROR) printf("GL Error: %s
",gluErrorString(err));
      else if (PrintAlways) printf("GL is clean
");
      }
    void resize(int X,int Y,int W,int H)
      {
      Fl_Gl_Window::resize(X,Y,W,H);
      SetupViewport();
      LoadScene();
      redraw();
      }
    int HandleKey(int key, const char *ascii)
      {
      if (!ascii) return 0;
      else if (*ascii=='s') Camera+=e3D(0.1*sin(Rad180+CameraRot), 0.0,0.1*sin(Rad90 +CameraRot));
      else if (*ascii=='w') Camera+=e3D(0.1*sin(Rad0  +CameraRot), 0.0,0.1*sin(Rad270+CameraRot));
      else if (*ascii=='a') Camera+=e3D(0.1*sin(Rad270+CameraRot), 0.0,0.1*sin(Rad180+CameraRot));
      else if (*ascii=='d') Camera+=e3D(0.1*sin(Rad90 +CameraRot), 0.0,0.1*sin(Rad0  +CameraRot));
      else if (*ascii=='q') Camera+=e3D( 0.0f, 0.1f, 0.0f);
      else if (*ascii=='e') Camera+=e3D( 0.0f,-0.1f, 0.0f);
      else if (*ascii=='z') CameraRot-=1.0f*PI/180.0;
      else if (*ascii=='c') CameraRot+=1.0f*PI/180.0;
      else if (*ascii=='x') { Camera=e3D(0.0f,0.0f,0.0f); CameraRot=0.0f; }
      }
    int handle(int Event)
      {
      switch(Event)
        {
        case FL_FOCUS: case FL_UNFOCUS: return 1;
        case FL_PUSH: return 1;
        case FL_KEYBOARD: return HandleKey(Fl::event_key(),Fl::event_text());
        default: return Fl_Gl_Window::handle(Event);
        }
      }
    static void Timer_CB(void *userdata)
      {
      MyGlWindow *gl=(MyGlWindow *)userdata;
      gl->redraw();
      Fl::repeat_timeout(1.0/30.0,Timer_CB,userdata);
      }
  public:
    MyGlWindow(int X, int Y, int W, int H, const char *L=0) : Fl_Gl_Window(X,Y,W,H,L), Frame(0), Camera(0.0f,0.0f,4.0f), CameraRot(0.0f)
      {
      Fl::add_timeout(1.0/30.0,Timer_CB,(void *)this);
      end();
      }
    int Frame;
    e3D Camera;
    float CameraRot;
  };


int main(void)
  {
  printf("Starting.
");
  Fl_Window win(500, 300);
  MyGlWindow mygl(10, 10, win.w()-20, win.h()-20);
  win.end();
  win.resizable(mygl);
  win.show();
  return(Fl::run());
  }

Make sure you’re still enabling GL_VERTEX_ARRAY, even for the VBO version. :slight_smile:

I found http://www.ozone3d.net/tutorials/opengl_vbo.php to be very helpful the first time I checked out VBO’s.

Thanks, HexCat, that did the trick. I explicitly left out the glEnableClientState(GL_VERTEX_ARRAY) because I thought VBOs are supposed to be “server side.” Am I thinking about this wrong?

They are server side. They did it to avoid introducing new API calls etc. Here’s a quote from the spec:

Should this extension sit on top of the existing vertex array
implementation, instead of introducing a new set of API calls?
    RESOLVED: YES.  This simplifies the API, and separating out the
    buffer binding from the offset/stride within the buffer leads to
    an elegant "BindBufferARB" command that can be used for other
    parts of GL like the pixel path.

Hello, I’m also trying to use VBO’s but I get many errors like these while compiling:

XXXX.cpp:XX: error: ‘glGenBuffers’ was not declared in this scope
XXXX.cpp:XX: error: ‘glBindBuffer’ was not declared in this scope
XXXX.cpp:XX: error: ‘glBufferData’ was not declared in this scope

Do you have any idea what is missing?
I have other glGenLists and other Lists methods in the same file and it’s working, the problem is only with the VBO functions.

some glxinfo dump:


OpenGL renderer string: GeForce Go 6200/PCI/SSE2
OpenGL version string: 2.1.2 NVIDIA 169.12
OpenGL extensions:
    GL_ARB_color_buffer_float, GL_ARB_depth_texture, GL_ARB_draw_buffers, 
    GL_ARB_fragment_program, GL_ARB_fragment_program_shadow, 
    GL_ARB_fragment_shader, GL_ARB_half_float_pixel, GL_ARB_imaging, 
    GL_ARB_multisample, GL_ARB_multitexture, GL_ARB_occlusion_query, 
    GL_ARB_pixel_buffer_object, GL_ARB_point_parameters, GL_ARB_point_sprite, 
    GL_ARB_shadow, GL_ARB_shader_objects, GL_ARB_shading_language_100, 
    GL_ARB_texture_border_clamp, GL_ARB_texture_compression, 
    GL_ARB_texture_cube_map, GL_ARB_texture_env_add, 
    GL_ARB_texture_env_combine, GL_ARB_texture_env_dot3, GL_ARB_texture_float, 
    GL_ARB_texture_mirrored_repeat, GL_ARB_texture_non_power_of_two, 
    GL_ARB_texture_rectangle, GL_ARB_transpose_matrix, 
    GL_ARB_vertex_buffer_object, GL_ARB_vertex_program, GL_ARB_vertex_shader, 
    GL_ARB_window_pos, GL_ATI_draw_buffers, GL_ATI_texture_float, 
    GL_ATI_texture_mirror_once, GL_S3_s3tc, GL_EXT_texture_env_add, 
    GL_EXT_abgr, GL_EXT_bgra, GL_EXT_blend_color, 
    GL_EXT_blend_equation_separate, GL_EXT_blend_func_separate, 
    GL_EXT_blend_minmax, GL_EXT_blend_subtract, GL_EXT_compiled_vertex_array, 
    GL_EXT_Cg_shader, GL_EXT_depth_bounds_test, GL_EXT_draw_range_elements, 
    GL_EXT_fog_coord, GL_EXT_framebuffer_blit, GL_EXT_framebuffer_multisample, 
    GL_EXT_framebuffer_object, GL_EXT_gpu_program_parameters, 
    GL_EXT_multi_draw_arrays, GL_EXT_packed_depth_stencil, 
    GL_EXT_packed_pixels, GL_EXT_pixel_buffer_object, GL_EXT_point_parameters, 
    GL_EXT_rescale_normal, GL_EXT_secondary_color, 
    GL_EXT_separate_specular_color, GL_EXT_shadow_funcs, 
    GL_EXT_stencil_two_side, GL_EXT_stencil_wrap, GL_EXT_texture3D, 
    GL_EXT_texture_compression_s3tc, GL_EXT_texture_cube_map, 
    GL_EXT_texture_edge_clamp, GL_EXT_texture_env_combine, 
    GL_EXT_texture_env_dot3, GL_EXT_texture_filter_anisotropic, 
    GL_EXT_texture_lod, GL_EXT_texture_lod_bias, GL_EXT_texture_mirror_clamp, 
    GL_EXT_texture_object, GL_EXT_texture_sRGB, GL_EXT_timer_query, 
    GL_EXT_vertex_array, GL_IBM_rasterpos_clip, 
    GL_IBM_texture_mirrored_repeat, GL_KTX_buffer_region, GL_NV_blend_square, 
    GL_NV_copy_depth_to_color, GL_NV_depth_clamp, GL_NV_fence, 
    GL_NV_float_buffer, GL_NV_fog_distance, GL_NV_fragment_program, 
    GL_NV_fragment_program_option, GL_NV_fragment_program2, 
    GL_NV_framebuffer_multisample_coverage, GL_NV_half_float, 
    GL_NV_light_max_exponent, GL_NV_multisample_filter_hint, 
    GL_NV_occlusion_query, GL_NV_packed_depth_stencil, GL_NV_pixel_data_range, 
    GL_NV_point_sprite, GL_NV_primitive_restart, GL_NV_register_combiners, 
    GL_NV_register_combiners2, GL_NV_texgen_reflection, 
    GL_NV_texture_compression_vtc, GL_NV_texture_env_combine4, 
    GL_NV_texture_expand_normal, GL_NV_texture_rectangle, 
    GL_NV_texture_shader, GL_NV_texture_shader2, GL_NV_texture_shader3, 
    GL_NV_vertex_array_range, GL_NV_vertex_array_range2, GL_NV_vertex_program, 
    GL_NV_vertex_program1_1, GL_NV_vertex_program2, 
    GL_NV_vertex_program2_option, GL_NV_vertex_program3, 
    GL_NVX_conditional_render, GL_SGIS_generate_mipmap, GL_SGIS_texture_lod, 
    GL_SGIX_depth_texture, GL_SGIX_shadow, GL_SUN_slice_accum

Do you know how to use extensions ? If not, use GLEW or GLEE to simplify your life.

First, consider making a new thread for new questions, it makes it easier for others to find the relevant threads later :slight_smile:

Anyway, I’m no c++ guru, but it sounds like you haven’t loaded the extensions. I hear GLEW is recommended.

Thank you both for the help. =)
I was already including the GL/glew.h :frowning:

Thank you all and sorry for “recycling” this topic with my problem

EDIT: I think I got it, I didn’t know I had to add -lGLEW to g++ :frowning: