Monday, June 2, 2008

OpenGL, Glut, and Glew in Eclipse

I would like to do OpenGL development using Eclipse in Linux. Here is what worked for me, I hope it will be helpful for others who are also doing this. It is based on OpenGL programming in Eclipse - An excellent guide. I also used GLEW for pixel buffers, which took some time to figure out. This guide is written for Ubuntu 8.04 (Hardy Heron).

After installing Eclipse...

Install the CDT:
In Eclipse -> Help -> Software Updates -> Available Software -> open Ganymede -> check "C and C++ Development" -> click "Install" -> Next -> "I accept..." -> restart eclipse

Create a project:
File -> New -> Project -> (in "C++" folder) Select "C++ Project" -> Next -> ...Enter Project Name... , in "Project Types", in "Executable", Select "Empty Project" -> Finish -> "Open Associated Perspective?" - Yes

Create a new file:
File (or right click on project) -> New -> File -> Name: "main.cpp" -> Finish

Paste the following code into the file. This is a virtual video feedback system using a PBO and a texture - the scene is rendered into the texture, which is rendered back into the scene.
#include <GL/glew.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>

#define WINDOW_WIDTH 512
#define WINDOW_HEIGHT 512
#define imageWidth 512
#define imageHeight 512

float xrot, yrot, zrot;

GLuint texture;
GLuint pbo;

unsigned char *image;
int t = 0;
int a = 200;
int b = 240;
int c = 260;
float zoom;

void display() {
int i=0;
//do 2 iterations per frame so black/white don't alternate every frame
for (i=0; i<2; i++) {
//clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//transform the view
glLoadIdentity();

glTranslatef(0, 0, zoom);
glRotatef(xrot, 1, 0, 0);
glRotatef(yrot, 0, 1, 0);
glRotatef(zrot, 0, 0, 1);

if (i == 1)
glClearColor( (float)(t%a)/a, (float)(t%b)/b, (float)(t%c)/c, 1);
else
glClearColor( 0, 0, 0, 1);
t++;

glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, imageWidth, imageHeight, GL_RGBA,
GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);

glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(-1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(1, 0);
glVertex2f(1, -1);
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glEnd();
glDisable(GL_TEXTURE_2D);

zrot+=.001f;
zoom = sin((float)t/200)/200-2.416;

// activate destination buffer
glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo);

// read data into pbo. note: use BGRA format for optimal performance
glReadPixels( 0, 0, imageWidth, imageHeight, GL_RGBA, GL_UNSIGNED_BYTE,
NULL);

}
glutSwapBuffers();
glutPostRedisplay();
}
int main(int argc, char **argv) {
//initialize necessary GLUT things
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("");
glutIdleFunc(&display);
glClearColor( 1, 1, 1, 1);

//create the data to put into the texture
int size= imageWidth*imageHeight*4;
image = (unsigned char *) malloc(sizeof(unsigned char)*size);
int i;
for (i=0; i<size; i=i+1) image[i] = (i/256); //create the texture glGenTextures((GLuint)1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); //initialize the extentions needed for using a PBO glewInit(); if (!glewIsSupported("GL_VERSION_2_0 " "GL_ARB_pixel_buffer_object")) printf("ERROR: Support for necessary OpenGL extensions missing."); //create the PBO glGenBuffers(1, &pbo); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); //upload our host image data to the pixel buffer glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(unsigned char) * imageWidth*imageHeight*4, image, GL_STREAM_DRAW); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); //initialize the GL projection glMatrixMode(GL_PROJECTION); gluPerspective(45.0f, (GLfloat)WINDOW_WIDTH/(GLfloat)WINDOW_HEIGHT, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); //enter the main loop glutMainLoop(); return 1; }

Add libraries:
first, install what you don't already have on your system
sudo apt-get install build-essential -y
sudo apt-get install libglut3-dev -y
sudo apt-get install libglew-dev -y

in Eclipse -> Project -> Properties -> in "C/C++ Build", select "Settings" -> "GCC C++ Linker" -> Libraries -> Click the green "+" thing next to "Libraries (-l) -> Enter "glut" -> OK -> green "+" again -> enter "GLEW" -> OK -> OK

Build it:
ctrl+b

Run it:
Run -> Run as -> Local C/C++ Application

Screenshot

Hooray!

Links:
Nice OpenGL tutorials

6 comments:

hasim said...

thank you very much this was very helpfull :).

Dan said...

Thanks for this. I had two problems:
1) in eclipse 3.2, there are two different types of project that use "make." Your instructions only work if you select the one that automatacally makes the Makefile.
2)Using Firefox at least, the main.cpp source code is in a scroll box, and most of the end of the source loses the line breaks. it is not completely clears where to put them back in.

Luca said...

thank you so much!!!

Jayantika said...

I am a newbie to Linux as well as CUDA. I am currently not having a graphics card. Can you tell me how to bring the window at the end?
Also tell me how does Eclipse compiles cuda program?

curran said...

Hi Jayantika,

The window at the end is the result of compiling and running the program. You can run the program by, in the Eclipse menus, clicking Run -> Run as -> Local C/C++ Application.

I once got CUDA code to compile inside Eclipse by setting it to use the makefile included with the CUDA examples. So, maybe it's not even worth the setup, it's essentially no better than calling make in a terminal.

hope this helps! good luck with Linux and CUDA

Jayantika said...

Thank you so much !!