Trouble getting buffer objects up and running!

Alexander Göransson <[email protected]> Sat, 3 Apr 2010 00:34:29 +0200
Newsgroups gmane.comp.lang.haskell.hopengl
Message-ID <[email protected]>
Hello!

I'm trying to port a C++ program that uses Vertex Buffer objects in
OpenGL 3.0. As of now it seems like i can't get any further ;(

Anyone who can help with as to what should be done next... I'm
attaching the C++ source and shader files as well as my haskell
source.

regards // Alexander

_______________________________________________
HOpenGL mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/hopengl
main.cpp (text/x-c++src, 8 KB)
#ifdef WIN32
#include <windows.h>
#endif

#include <GL/glew.h>
#include <GL/glut.h>

#include "glutil.h"
#include "vecmath.h"

#include <cstdlib>
#include <fstream>


// The shaderProgram holds the vertexShader and fragmentShader
GLuint shaderProgram;

// The vertexArrayObject here will hold the pointers to 
// the vertex data (in vertBuffer) and color data per vertex (in colorBuffer)
GLuint vertBuffer, colorBuffer, vertexArrayObject;	

static void initGL()
{
	//******* Load Extensions ************
	glewInit();  
	// Workaround for AMD, which hopefully will not be neccessary in the near future...
	if (!glBindFragDataLocation)
	{
		glBindFragDataLocation = glBindFragDataLocationEXT;
	}


	//******** Create Triangle ************

	// Define the positions for each of the three points of the triangle
	const float verts[] = {
	//	 X      Y     Z
			0.0f,   0.5f, 1.0f,		// v0
		 -0.5f,  -0.5f, 1.0f,		// v1
			0.5f,  -0.5f, 1.0f		// v2
	};
	
	// Define the colors for each of the three points of the triangle
	const float colors[] = {
	//  R     G		B
		1.0f, 1.0f, 1.0f,		// White
		1.0f, 1.0f, 1.0f,		// White
		1.0f, 1.0f, 1.0f		// White
	};
	
	// Create a handle for the vertex position buffer, see spec §2.9 Buffer Objects (http://www.cse.chalmers.se/edu/course/TDA361/glspec30.20080923.pdf#page=54&zoom=75)
	glGenBuffers( 1, &vertBuffer );
	// Set the newly created buffer as the current one
	glBindBuffer( GL_ARRAY_BUFFER, vertBuffer );
	// Send the vetex position data to the current buffer
	glBufferData( GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW );
	
	// Create a handle for the vertex color buffer
	glGenBuffers( 1, &colorBuffer );
	// Set the newly created buffer as the current one
	glBindBuffer( GL_ARRAY_BUFFER, colorBuffer );	
	// Send the vertex color data to the current buffer
	glBufferData( GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW );
	CHECK_GL_ERROR();
	//**************************************


	//**************Create Shaders******************
	// See OpenGL spec §2.20 http://www.cse.chalmers.se/edu/course/TDA361/glspec30.20080923.pdf#page=104&zoom=75
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

	// Invoke helper functions (in glutil.h/cpp) to load text files for vertex and fragment shaders.
	char *vs = textFileRead("simple.vert"); // On mac, use "../../simple.vert"
	char *fs = textFileRead("simple.frag"); // On mac, use "../../simple.frag"

	// workaround for const correctness.
	const char *vv = vs;
	const char *ff = fs;
	glShaderSource(vertexShader, 1, &vv, NULL);
	glShaderSource(fragmentShader, 1, &ff, NULL);

	// we are now done with the source and can free the file data.
	free(vs);
	free(fs);

	// Comile the shader, translates into internal representation and checks for errors.
	glCompileShader(vertexShader);
	int errorFlag = -1;
	// check for compiler errors in vertex shader.
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &errorFlag);
	if(!errorFlag) {
		std::string err = GetShaderInfoLog(vertexShader);
		fatal_error( err );
		return;
	}

	// Comile the shader, translates into internal representation and checks for errors.
	glCompileShader(fragmentShader);
	// check for compiler errors in fragment shader.
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &errorFlag);
	if(!errorFlag) {
		std::string err = GetShaderInfoLog(fragmentShader);
		fatal_error( err );
		return;
	}

	// Create a program object and attach the two shaders we have compiled, the program object contains
	// both vertex and fragment shaders as well as information about uniforms and attributes common to both.
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, fragmentShader);
	glAttachShader(shaderProgram, vertexShader);

	// Assigns the vertex attribute array index 0 to the in vertex shader in variable "vertex".
	glBindAttribLocation(shaderProgram, 0, "vertex"); 
	// ...and index 1 to "color".
	// NOTE: that these indices are used further down in the calls glVertexAttribPointer.
	glBindAttribLocation(shaderProgram, 1, "color");

	// This tells OpenGL which draw buffer the fragment shader out varaible 'fragmentColor' will end up in.
	// Since we only use one output and draw buffer this is actually redundant, as the default will be correct.
	glBindFragDataLocation(shaderProgram, 0, "fragmentColor");

	// Link the different shaders that are bound to this program, this creates a final shader that 
	// we can use to render geometry with.
	glLinkProgram(shaderProgram);

	// Check for linker errors, many errors, such as mismatched in and out variables between 
	// vertex/fragment shaders,  do not appear before linking.
	{
		GLint linkOk = 0;
		glGetProgramiv(shaderProgram, GL_LINK_STATUS, &linkOk);
		if(!linkOk) 
		{
			std::string err = GetShaderInfoLog(shaderProgram);
			fatal_error( err );
			return;
		}
	}

	// Now that the shader program has been linked, we no longer need these two intermediate objects and should delete them
	// Only the shader program needs to be retained for use while rendering
	glDeleteShader( vertexShader );
	glDeleteShader( fragmentShader );
	CHECK_GL_ERROR();
	//**********************************************

	//******* Connect triangle data with the vertex array object *******
	glGenVertexArrays(1, &vertexArrayObject);

	// Bind the vertex array object, following calls will affect this object.
	glBindVertexArray(vertexArrayObject);
	CHECK_GL_ERROR();

	// Makes vertBuffer the current array buffer for subsequent calls.
	glBindBuffer( GL_ARRAY_BUFFER, vertBuffer );
	// Attaches vertBuffer to vertexArrayObject, in the 0th attribute location, earlier bound to "vertex"
	glVertexAttribPointer(0, 3, GL_FLOAT, false/*normalized*/, 0/*stride*/, 0/*offset*/ );	

	// Makes colorBuffer the current array buffer for subsequent calls.
	glBindBuffer( GL_ARRAY_BUFFER, colorBuffer );
	// Attaches vertBuffer to vertexArrayObject, in the 1st attribute location, earlier bound to "color"
	glVertexAttribPointer(1, 3, GL_FLOAT, false/*normalized*/, 0/*stride*/, 0/*offset*/ );
	CHECK_GL_ERROR();

	// enable vertex attribute arrays 0 and 1 for the currently bound vertex array object.
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	CHECK_GL_ERROR();
}


static void drawScene(void)
{
	// Shader Program
	glUseProgram( shaderProgram );			// Set the shader program to use for this draw call
	CHECK_GL_ERROR();
	// Bind the vertex array object that contains all the vertex data.
	glBindVertexArray(vertexArrayObject);
	CHECK_GL_ERROR();
	glDrawArrays( GL_TRIANGLES, 0, 3 );				// Render 1 triangle
	CHECK_GL_ERROR();

	glUseProgram( 0 );						// "unsets" the current shader program. Not really necessary.
	CHECK_GL_ERROR();

	}

void display(void)
{
	glClearColor(0.2,0.2,0.8,1.0);						// Set clear color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the color buffer and the z-buffer

	int w = glutGet((GLenum)GLUT_WINDOW_WIDTH);
	int h = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
	glViewport(0, 0, w, h);						// Set viewport
	
	// We disable backface culling for this tutorial, otherwise care must be taken with the winding order
	// of the vertices. It is however a lot faster to enable culling when drawing large scenes.
	glDisable(GL_CULL_FACE);
	drawScene();

	glutSwapBuffers();  // swap front and back buffer. This frame will now been displayed.
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	/* open window of size 800x600 with double buffering, RGB colors, and Z-buffering */
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(512,512);
	glutCreateWindow("OpenGL Lab 1");
	/* the display function is called once when the gluMainLoop is called,
		* but also each time the window has to be redrawn due to window 
		* changes (overlap, resize, etc).  
		*/
	glutDisplayFunc(display);	// Set the main redraw function
	
	initGL();

	glutMainLoop();  /* start the program main loop */
	
	return 0;          
}
simple.frag (application/octet-stream, 217 B) - not displayed
simple.vert (application/octet-stream, 143 B) - not displayed
lab1.hs (text/x-haskell, 1.7 KB)
module Main where


import Control.Concurrent
import Control.Monad
import Data.IORef
import Foreign 
import Graphics.UI.GLUT


initGL = do
    initialDisplayMode $= [ RGBMode
                          , WithDepthBuffer
                          , DoubleBuffered ]
    -- allocate two recources in GPU memory
    [vbo, cbo] <- genObjectNames 2

    -- fill 2xForeign.Array with vert/col data
    vertPtr <- newArray verts
    let vertSize = sizeOf (head verts) * length verts

    colPtr <- newArray colors
    let colSize = sizeOf (head colors) * length colors

    -- bind vertices to gfx mem
    bindBuffer ArrayBuffer $= Just vbo
    bufferData ArrayBuffer $= ( fromIntegral vertSize
                              , vertPtr
                              , StaticDraw)
    -- bind colors to gfx mem
    bindBuffer ArrayBuffer $= Just cbo
    bufferData ArrayBuffer $= ( fromIntegral colSize
                              , colPtr
                              , StaticDraw)
        {- i am a long comment -}
    -- idleCallback $= Just idle
    displayCallback $= display 


main = do
    -- initialize and make window
    getArgsAndInitialize
    initialWindowSize $= Size 800 600
    createWindow "gogo gadget pipeline!"
    -- set callbacks etc.
    state <- initGL
    -- main loop
    mainLoop

display = do
    clear [ ColorBuffer
          , DepthBuffer ]
    flush
    swapBuffers

---------------------------------------
-- CONSTANTS
---------------------------------------
verts :: [ Vertex3 GLfloat ]
verts = [ Vertex3   0.0    0.5   1.0
        , Vertex3 (-0.5) (-0.5)  1.0
        , Vertex3   0.5  (-0.5)  1.0 ]

colors :: [ Color3 GLfloat ]
colors = [ Color3 1.0 1.0 1.0
         , Color3 1.0 1.0 1.0
         , Color3 1.0 1.0 1.0 ]