summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKamil Kaminski <kamilkss@gmail.com>2011-07-27 11:47:44 -0500
committerKamil Kaminski <kamilkss@gmail.com>2011-07-27 11:47:44 -0500
commita1b4c92da5f1b9de5e9c289c0fd37ba060bf5377 (patch)
tree15149c7d317c9667ef24cda784c40879d275a526
downloadglvbo-a1b4c92da5f1b9de5e9c289c0fd37ba060bf5377.tar.gz
glvbo-a1b4c92da5f1b9de5e9c289c0fd37ba060bf5377.tar.bz2
glvbo-a1b4c92da5f1b9de5e9c289c0fd37ba060bf5377.zip
initial commit, ported from sdl repo
-rw-r--r--Makefile25
-rw-r--r--mingw3245
-rw-r--r--vbo.c450
3 files changed, 520 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3b3f939
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,25 @@
+PROG = vbo
+OBJS = $(PROG).o
+CC = gcc
+DBGFLAGS = -g -O0
+ifdef DEBUG
+ CFLAGS = $(DBGFLAGS) -Wall -std=c99
+else
+ CFLAGS = -Wall -std=c99 -O2 -march=native -mtune=native
+endif
+LDFLAGS = -lGLEW -lGL -lGLU -lm -lglut
+SDL_CFLAGS := $(shell sdl-config --cflags)
+SDL_LDFLAGS := $(shell sdl-config --libs)
+SDL_image_CFLAGS := $(shell pkg-config --cflags SDL_image)
+SDL_image_LDFLAGS := $(shell pkg-config --libs SDL_image)
+
+$(PROG): $(OBJS)
+ $(CC) $(LDFLAGS) $(SDL_LDFLAGS) $(SDL_image_LDFLAGS) $(OBJS) -o $(PROG)
+
+$(PROG).o: $(PROG).c
+ $(CC) -c $(CFLAGS) $(SDL_CFLAGS) $(SDL_image_CFLAGS) $(PROG).c
+
+.PHONY: clean
+
+clean:
+ rm -f *.o ./$(PROG)
diff --git a/mingw32 b/mingw32
new file mode 100644
index 0000000..b03c73d
--- /dev/null
+++ b/mingw32
@@ -0,0 +1,45 @@
+BIN = vbo
+SRC = vbo.c
+CC = gcc
+CFLAGS = -Wall -std=c99 -MD
+DBGFLAGS = -g -O0
+ifdef DEBUG
+ CFLAGS += $(DBGFLAGS)
+else
+ CFLAGS += -O2 -march=native -mtune=native
+endif
+LDFLAGS = -lglew32 -lopengl32 -lglu32 -lm -lfreeglut -lmingw32 -lsdlmain -lsdl \
+ -lsdl_image -mwindows
+
+OBJ_DIR = obj
+DEPS_DIR = obj
+BIN_DIR = .
+
+C_FILES = $(filter %.c, $(SRC))
+DEP_FILES = $(addprefix $(DEPS_DIR)\, $(addsuffix .d, $(notdir $(subst .c,,$(SRC)))))
+OBJ_FILES = $(addprefix $(OBJ_DIR)\, $(addsuffix .o, $(notdir $(subst .c,,$(SRC)))))
+
+INCL = -I/include
+
+define C_template
+$(1): $(2)
+ @mkdir -p $$(OBJ_DIR)
+ @mkdir -p $$(DEPS_DIR)
+ $$(CC) -c $$(CFLAGS) $$(INCL) $$< -o $$@
+endef
+
+all: $(BIN)
+
+$(foreach cfile, $(C_FILES), $(eval $(call C_template, $(OBJ_DIR)\$(notdir $(subst .c,,$(cfile))).o, $(cfile))))
+
+$(BIN): $(OBJ_FILES)
+ @mkdir -p $(BIN_DIR)
+ $(CC) -o $(BIN_DIR)/$@ $(OBJ_FILES) $(LDFLAGS)
+
+.PHONY: clean
+
+clean:
+ rm -rf $(OBJ_DIR)
+ rm -f $(BIN_DIR)/$(BIN).exe stdout.txt stderr.txt
+
+-include $(DEP_FILES)
diff --git a/vbo.c b/vbo.c
new file mode 100644
index 0000000..3206188
--- /dev/null
+++ b/vbo.c
@@ -0,0 +1,450 @@
+/* vbo.c
+ *
+ * Kamil Kaminski
+ * kkaminsk.com
+ *
+ * Example of using VBO
+ *
+ *
+ */
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <GL/glew.h>
+#include <GL/freeglut.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#define BUFFER_OFFSET(i) ((char *)NULL + (i))
+
+/* for simplicity we pack */
+#pragma pack(1)
+typedef struct vbo_slice
+{
+ GLfloat normal[3];
+ GLfloat texcoord[2];
+ GLubyte color[3];
+} vbo_slice_t;
+#pragma pack()
+
+/* globals */
+int program_running = 1;
+SDL_Surface *screen;
+GLuint buffer_objects[3];
+
+/* few light arrays */
+const GLfloat fNoLight[] = { 0.0f, 0.0f, 0.0f, 1.0f };
+const GLfloat fLowLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
+const GLfloat fMedLight[] = { 0.50f, 0.50f, 0.50f, 1.0f };
+const GLfloat fShinyLight[] = { 0.70f, 0.70f, 0.70f, 1.0f };
+const GLfloat fBrightLight[] = { 1.0f, 1.0f, 1.0f, 1.0f };
+
+/* light values and coordinates */
+const GLfloat lightPos[] = { -10.f, 5.0f, 5.0f, 1.0f };
+
+/* function prototypes */
+static void gltErrorCheck(void);
+static void resize(int, int);
+static void setup_opengl(void);
+static void keys(SDL_keysym *, unsigned int *);
+static void process_events(void);
+static void render(void);
+static void setup_sdl(void);
+static void setup_glew(void);
+static void setup_opengl(void);
+
+/* we have a separate buffer objects for vertex data, attributes, and indices
+ * gl*Pointer gets assiociated with currently binded buffer
+ * interleaved arrays improve cache performance, the key is locality
+ */
+static int gltGenVBOInterleaved(GLuint *bufferobjects, float *vert_arr,
+ float *texcoord_arr, float *norm_arr, unsigned char *color_arr,
+ unsigned short *indices_arr, size_t points_n, size_t indices_n)
+{
+ /* skip error check for now */
+
+ /* create an interleaved data structure, is it worth the cpu time? */
+ size_t attrib_buff_sz = ((points_n * (3+2) * sizeof(GLfloat)) +
+ (points_n * 3 * sizeof(GLubyte)));
+
+ if ((attrib_buff_sz % sizeof(vbo_slice_t)) != 0)
+ {
+ fprintf(stderr, "gen_vbo: fatal, vbo_slice_t appears to be padded!\n");
+ exit(-1);
+ }
+
+ size_t slices_n = attrib_buff_sz / sizeof(vbo_slice_t);
+
+ vbo_slice_t *vbo_slices_arr = (vbo_slice_t *) malloc(attrib_buff_sz);
+ if (!vbo_slices_arr)
+ {
+ perror("malloc");
+ exit(-1);
+ }
+
+ /* build interleaved data structure, may not be cache friendly */
+ int i;
+ for (i = 0; i < slices_n; i++)
+ {
+ vbo_slices_arr[i].normal[0] = norm_arr[i * 3 + 0];
+ vbo_slices_arr[i].normal[1] = norm_arr[i * 3 + 1];
+ vbo_slices_arr[i].normal[2] = norm_arr[i * 3 + 2];
+ vbo_slices_arr[i].texcoord[0] = texcoord_arr[i * 2 + 0];
+ vbo_slices_arr[i].texcoord[1] = texcoord_arr[i * 2 + 1];
+ vbo_slices_arr[i].color[0] = color_arr[i * 3 + 0];
+ vbo_slices_arr[i].color[1] = color_arr[i * 3 + 1];
+ vbo_slices_arr[i].color[2] = color_arr[i * 3 + 2];
+ }
+
+ glGenBuffers(3, bufferobjects);
+
+ /* vertex data */
+ glBindBuffer(GL_ARRAY_BUFFER, bufferobjects[0]);
+ glBufferData(GL_ARRAY_BUFFER, points_n * 3 * sizeof(float), (const GLvoid *) vert_arr, GL_STATIC_DRAW);
+
+ /* attribute data, normals, texcoords, and color */
+ glBindBuffer(GL_ARRAY_BUFFER, bufferobjects[1]);
+ glBufferData(GL_ARRAY_BUFFER, attrib_buff_sz, (const GLvoid *) vbo_slices_arr, GL_STATIC_DRAW);
+
+ /* indices data */
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferobjects[2]);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short) * indices_n, (const GLvoid *) indices_arr, GL_STATIC_DRAW);
+
+ return 0;
+}
+
+static int gltDrawVBOInterleaved(GLuint *bufferobjects, size_t indices_n)
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ /* vertex data */
+ glBindBuffer(GL_ARRAY_BUFFER, bufferobjects[0]);
+ glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
+
+ /* attribute data, normals, texcoords, and color */
+ glBindBuffer(GL_ARRAY_BUFFER, bufferobjects[1]);
+ glNormalPointer(GL_FLOAT, sizeof(vbo_slice_t), BUFFER_OFFSET(0));
+ glClientActiveTexture(GL_TEXTURE0);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(vbo_slice_t), BUFFER_OFFSET(sizeof(GLfloat) * 3));
+ glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(vbo_slice_t), BUFFER_OFFSET(sizeof(GLfloat) * 5));
+
+ /* indices data */
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferobjects[2]);
+ glDrawElements(GL_TRIANGLES, indices_n, GL_UNSIGNED_SHORT, 0);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ return 0;
+}
+
+static void gltErrorCheck(void)
+{
+ GLenum err_code;
+ const GLubyte *err_str;
+
+ while ((err_code = glGetError()) != GL_NO_ERROR)
+ {
+ err_str = gluErrorString(err_code);
+ fprintf(stderr, "OpenGL error: %s\n", err_str);
+ }
+}
+
+static void resize(int w, int h)
+{
+ printf("window: resizing to %dx%d\n", w, h);
+ GLfloat fAspect = (GLfloat) w / (GLfloat) h;
+ if (h == 0)
+ h = 1;
+ glViewport(0, 0, w, h);
+
+ /* reset coordinate system */
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ /* produce the perspective projection */
+ /* void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) */
+ gluPerspective(40.0f, fAspect, 1.0, 40.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ /* this needs to be ran again, glut does it for you I suppose */
+ SDL_SetVideoMode(w, h, 32, SDL_OPENGL | SDL_RESIZABLE);
+}
+
+static void setup_opengl(void)
+{
+ /* setup fog */
+ glEnable(GL_FOG);
+ glFogfv(GL_FOG_COLOR, fLowLight); /* set fog color to match background */
+ glFogf(GL_FOG_START, 4.0f);
+ glFogf(GL_FOG_END, 20.0f);
+ glFogi(GL_FOG_MODE, GL_LINEAR); /* fog equation */
+
+ glEnable(GL_DEPTH_TEST); /* hidden surface removal, aka Z-buffer */
+ glFrontFace(GL_CCW); /* counter clock-wise polygons face out */
+ glEnable(GL_CULL_FACE); /* do not calculate inside of a pyramid */
+
+ /* enable lighting, primitives now need to define color properties */
+ glEnable(GL_LIGHTING);
+
+ /* global illumination, ambient RGBA intensity of the entire scene */
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fLowLight);
+
+ /* setup and enable light 0 */
+ glLightfv(GL_LIGHT0, GL_AMBIENT, fMedLight);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, fShinyLight);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, fBrightLight);
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
+ glEnable(GL_LIGHT0);
+
+ /* set material properties to follow all glColor values */
+ /* all primitives specified after the glMaterial call are affected by the
+ * last values set, until another call to glMaterial is made */
+ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+
+ /* enable color tracking, should be called after glColorMaterial */
+ glEnable(GL_COLOR_MATERIAL);
+
+ /* set globally, sets specular reflection to a white color,
+ * this call follows all subsequent primitives */
+ glMaterialfv(GL_FRONT, GL_SPECULAR, fBrightLight);
+
+ /* default (0), by increasing this value you reduce the size and increase
+ * the focus of the specular highlight, causing a shiny spot to appear */
+ glMateriali(GL_FRONT, GL_SHININESS, 64);
+
+ /* multisampling for polygons, conflicts with *polygon* anti-aliasing */
+ /* enabled by default, that's what man page says, hmmm! */
+ glEnable(GL_MULTISAMPLE);
+
+ /* AA is disabled, but we will keep the blending function and hints though */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
+ glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
+
+ /* anisotropic filtering */
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+
+ /* how OpenGL combines the colors from texels with the color of the underlying
+ * geometry is controlled by the texture environment mode */
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ /* once texture is loaded and enabled, it will applied to every primitive
+ * that specifies coordinates, ORLY? */
+ glEnable(GL_TEXTURE_2D);
+
+ /* specular highlights for textured items */
+ glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
+ /* gray background */
+ glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+}
+
+static void keys(SDL_keysym *keysym, unsigned int *keys_held)
+{
+ switch (keysym->sym)
+ {
+ case SDLK_ESCAPE:
+ program_running = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+/* process SDL events */
+static void process_events(void)
+{
+ SDL_Event event;
+ unsigned static int keys_held[323];
+ SDLKey sym;
+
+ while (SDL_PollEvent(&event))
+ {
+ sym = event.key.keysym.sym;
+
+ switch (event.type)
+ {
+ case SDL_KEYUP:
+ {
+ /* reset the key to 0 */
+ keys_held[sym] = 0;
+ break;
+ }
+ case SDL_KEYDOWN:
+ {
+ keys_held[sym] = 1;
+ keys(&event.key.keysym, keys_held);
+ break;
+ }
+ case SDL_VIDEORESIZE:
+ {
+ resize(event.resize.w, event.resize.h);
+ break;
+ }
+ case SDL_QUIT:
+ {
+ program_running = 0;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+static void render(void)
+{
+ /* clear the window with current clearing color */
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ /* save the matrix state */
+ glPushMatrix();
+ {
+ /* draw ground using immiediate mode */
+ glDisable(GL_MULTISAMPLE);
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+
+ GLfloat fExtent = 20.0f;
+ GLfloat fStep = 0.5f;
+ GLfloat y = -0.4f;
+ GLfloat iLine;
+
+ glLineWidth(1.0f);
+ glBegin(GL_LINES);
+ for (iLine = -fExtent; iLine <= fExtent; iLine += fStep)
+ {
+ glVertex3f(iLine, y, fExtent);
+ glVertex3f(iLine, y, -fExtent);
+ glVertex3f(fExtent, y, iLine);
+ glVertex3f(-fExtent, y, iLine);
+ }
+ glEnd();
+
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_BLEND);
+ glEnable(GL_MULTISAMPLE);
+ /* end of ground */
+
+ glPushMatrix();
+ /* draw vbo */
+ glTranslatef(0.0f, 0.0f, -4.0f);
+ gltDrawVBOInterleaved(buffer_objects, 3);
+ glPopMatrix();
+ }
+ /* restore the matrix state */
+ glPopMatrix();
+
+ /* buffer swap */
+ SDL_GL_SwapBuffers();
+}
+
+static void setup_sdl(void)
+{
+ if (SDL_Init(SDL_INIT_VIDEO) < 0 )
+ {
+ fprintf(stderr, "SDL: unable to init, %s\n", SDL_GetError());
+ exit(-1);
+ }
+ atexit(SDL_Quit);
+ SDL_WM_SetCaption("SDL", NULL);
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+
+ if ((screen = SDL_SetVideoMode(640, 480, 32, SDL_OPENGL | SDL_RESIZABLE)) == NULL)
+ {
+ fprintf(stderr, "SDL: unable to set video mode: %s\n", SDL_GetError());
+ exit(-1);
+ }
+
+ SDL_EnableUNICODE(1);
+ /* SDL doesn't trigger off a ResizeEvent at startup, but as we need this
+ * for OpenGL, we do this ourselves */
+ SDL_Event resizeEvent;
+ resizeEvent.type = SDL_VIDEORESIZE;
+ resizeEvent.resize.w = 640;
+ resizeEvent.resize.h = 480;
+ SDL_PushEvent(&resizeEvent);
+}
+
+static void setup_glew(void)
+{
+ /* initalize glew */
+ GLenum glewerr = glewInit();
+ if (GLEW_OK != glewerr)
+ {
+ fprintf(stderr, "GLEW error: %s\n", glewGetErrorString(glewerr));
+ exit(-1);
+ }
+ else
+ fprintf(stdout, "GLEW: using version %s\n", glewGetString(GLEW_VERSION));
+
+ /* display OpenGL version */
+ GLint major;
+ GLint minor;
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MINOR_VERSION, &minor);
+ fprintf(stdout, "GLEW: initialized OpenGL %d.%d\n", major, minor);
+}
+
+int main(int argc, char **argv)
+{
+ setup_sdl();
+ setup_glew();
+ setup_opengl();
+ gltErrorCheck();
+
+ /* setup a vbo */
+ float vert_arr[9] = { 0.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.5f, 0.66f, 0.0f };
+
+ float norm_arr[9] = { 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 1.0f };
+
+ float texcoord_arr[6] = { 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.5f, 1.0f };
+
+ unsigned char color_arr[9] = { 255, 0, 0,
+ 0, 255, 0,
+ 0, 0, 255 };
+
+ unsigned short indices_arr[3] = { 0, 1, 2 };
+
+ gltGenVBOInterleaved(buffer_objects, vert_arr, texcoord_arr, norm_arr, color_arr,
+ indices_arr, 3, 3);
+ gltErrorCheck();
+
+ while (program_running)
+ {
+ process_events();
+ render();
+ }
+
+ gltErrorCheck();
+ glDeleteBuffers(3, buffer_objects);
+ if (screen)
+ SDL_FreeSurface(screen);
+
+ puts("bye!");
+
+ return 0;
+}
+