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 ]