From 04bd71265a51eb3c842c45b332a45575a8660e60 Mon Sep 17 00:00:00 2001 From: taw27 Date: Sun, 1 Jun 2008 19:11:41 +0000 Subject: Multiple portability fixes git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@57 84d2e878-0bd5-11dd-ad15-13eda11d74c5 --- src/Makefile.am | 2 +- src/game.c | 1 + src/main.c | 23 +----------- src/model.c | 19 ++++------ src/physics.c | 2 +- src/render.c | 114 ++++++++++++++++++++++++++++++++++++-------------------- src/texture.c | 4 +- src/types.h | 4 ++ 8 files changed, 91 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 6c89359..d3ccec8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = thrust3d thrust3d_SOURCES = main.c model.c render.c physics.c game.c texture.c utils.c audio.c -thrust3d_LDADD = @LIBS@ -lGLEW +thrust3d_LDADD = @LIBS@ AM_CFLAGS = -Wall -g AM_CPPFLAGS = -DDATADIR=\""$(datadir)"/thrust3d\" diff --git a/src/game.c b/src/game.c index 221ba23..1e262a9 100644 --- a/src/game.c +++ b/src/game.c @@ -253,6 +253,7 @@ Game *game_new(int width, int height) { free(g); return NULL; } + /* Note: render_setup() initialises GLEW, which must be done before loading models. */ /* Audio setup */ g->audio = audio_setup(); diff --git a/src/main.c b/src/main.c index 65fa217..80e5862 100644 --- a/src/main.c +++ b/src/main.c @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include "types.h" @@ -42,11 +40,6 @@ static void main_version() { printf("Thrust3D version "PACKAGE_VERSION", (c) 2008 Thomas White \n"); } -extern int physics_will_collide_face(GLfloat sx, GLfloat sy, GLfloat sz, GLfloat vx, GLfloat vy, GLfloat vz, - GLfloat nx, GLfloat ny, GLfloat nz, GLfloat *fvert, int nfvert, Uint32 dt, - ModelInstance *obj); -extern int physics_point_is_inside_hull(GLfloat cx, GLfloat cy, GLfloat cz, GLfloat *fvert, int nfvert, GLfloat nx, GLfloat ny, GLfloat nz); - int main(int argc, char *argv[]) { SDL_Event event; @@ -62,20 +55,6 @@ int main(int argc, char *argv[]) { width = 800; height = 600; video_flags = SDL_OPENGL; -#if 0 - /* FIXME: Testing */ - GLfloat testv[3*4]; - int ts; - testv[3*0+0] = 0.0; testv[3*0+1] = 0.0; testv[3*0+2] = 0.0; - testv[3*1+0] = 1.0; testv[3*1+1] = 0.0; testv[3*1+2] = 0.0; - testv[3*2+0] = 1.0; testv[3*2+1] = 1.0; testv[3*2+2] = 0.0; - testv[3*3+0] = 0.0; testv[3*3+1] = 1.0; testv[3*3+2] = 0.0; - ts = physics_point_is_inside_hull(-0.5, 0.5, 1.0, testv, 4, 0.0, 0.0, 1.0); - printf("Boundary test: %i\n", ts); - ts = physics_will_collide_face(-0.5, 0.5, 1.0, 0.0, 0.0, -0.02, 0.0, 0.0, 1.0, testv, 4, 100, NULL); - printf("Will collide: %i\n", ts); -#endif - while ((c = getopt(argc, argv, "hvr:f")) != -1) { switch ( c ) { @@ -231,7 +210,7 @@ int main(int argc, char *argv[]) { /* Sleep for a bit to avoid hogging the CPU. * This is a fudge - ideally this delay would adapt so that the CPU is not hogged when the GPU is the - * limiting factor, and be zero when the CPU is limiting. I don't know a sensible way to tell which + * limiting factor, and be zero when the CPU is limiting. I don't know of a sensible way to tell which * is the case. */ usleep(25000); diff --git a/src/model.c b/src/model.c index d182f32..2c3c895 100644 --- a/src/model.c +++ b/src/model.c @@ -13,8 +13,7 @@ #include #endif -#define GL_GLEXT_PROTOTYPES 1 -#include +#include #include #include #include @@ -75,8 +74,8 @@ static Model *model_new(const char *name) { static Primitive *model_add_primitive(Model *model, GLenum type, GLfloat *vertices, GLfloat *normals, GLfloat *texcoords, int n, PrimitiveAttrib attribs, GLfloat r, GLfloat g, GLfloat b, char *texture, - GLfloat radius, GLfloat shininess) { - + GLfloat radius, GLfloat shininess, int vbos) { +#include Primitive *p; /* Sanity check */ @@ -125,9 +124,10 @@ static Primitive *model_add_primitive(Model *model, GLenum type, GLfloat *vertic p->radius = radius; p->shininess = shininess; - if ( type != PRIMITIVE_HEMISPHERE ) { + if ( vbos && ( type != PRIMITIVE_HEMISPHERE ) ) { - /* Buffer object stuff */ + /* FIXME: Move this snippet to render.c is some tidy way */ + glGenBuffersARB(1, &p->vertices_buffer); glBindBufferARB(GL_ARRAY_BUFFER, p->vertices_buffer); glBufferDataARB(GL_ARRAY_BUFFER, 3*p->num_vertices*sizeof(GLfloat), p->vertices, GL_STATIC_DRAW); @@ -142,11 +142,6 @@ static Primitive *model_add_primitive(Model *model, GLenum type, GLfloat *vertic glBindBufferARB(GL_ARRAY_BUFFER, 0); - // free(p->vertices); - // free(p->normals); - // free(p->texcoords); - /* End buffer object stuff */ - } model->attrib_total = model->attrib_total | attribs; @@ -235,7 +230,7 @@ static int model_load(ModelContext *ctx, const char *name, RenderContext *render if ( line[0] == '\n' ) { if ( num_vertices > 0 ) { model_add_primitive(model, type, vertices, normals, texcoords, num_vertices, - attribs, col_r, col_g, col_b, texture, radius, shininess); + attribs, col_r, col_g, col_b, texture, radius, shininess, render->vbos); num_vertices = 0; type = PRIMITIVE_TRIANGLES; attribs = ATTRIB_NONE; diff --git a/src/physics.c b/src/physics.c index 120caff..c9f89f1 100644 --- a/src/physics.c +++ b/src/physics.c @@ -189,7 +189,7 @@ static int physics_check_collide(ModelInstance *obj, ModelInstance *other, Uint3 if ( physics_will_collide_face(sx, sy, sz, vx, vy, vz, nx, ny, nz, face, 4, dt, other) != 0 ) { - //printf("collides with %s/%p\n", other->model->name, other); + printf("collides with %s/%p\n", other->model->name, other); if ( (nx == 0.0) && (ny == 0.0) && ( nz == 1.0) ) { obj->vz = 0.0; obj->landed = 1; diff --git a/src/render.c b/src/render.c index d8ca276..e92abf5 100644 --- a/src/render.c +++ b/src/render.c @@ -114,7 +114,7 @@ static void render_delete_shaders(RenderContext *r) { glDeleteShader(r->lighting_vert); glDeleteShader(r->lighting_frag); glDeleteProgram(r->lighting_program); - + } #define HEMI_ROUND_BITS 16 @@ -141,6 +141,33 @@ RenderContext *render_setup(int width, int height) { glewInit(); + if ( GLEW_VERSION_1_5 || GLEW_ARB_vertex_buffer_object ) { + r->vbos = 1; + } else { + r->vbos = 0; + fprintf(stderr, "Vertex buffer objects are not supported by your graphics card (or maybe just by its driver).\n"); + fprintf(stderr, "Geometry performance may be less than optimal.\n"); + } + + if ( GLEW_EXT_framebuffer_object ) { + r->fbos = 1; + } else { + r->fbos = 0; + fprintf(stderr, "Framebuffer objects are not supported by your graphics card (or maybe just by its driver).\n"); + fprintf(stderr, "Reflections and GPU dynamic textures disabled.\n"); + } + + if ( ( GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader && GLEW_ARB_shader_objects && GLEW_ARB_shading_language_100 ) || GLEW_VERSION_2_0 ) { + r->shaders = 1; + } else { + r->shaders = 0; + fprintf(stderr, "Shaders are not supported by your graphics card (or maybe just by its driver).\n"); + fprintf(stderr, "Per-fragment lighting and GPU dynamic textures disabled.\n"); + } + if ( !r->fbos && !r->shaders ) { + fprintf(stderr, "This REALLY isn't going to be as pretty as it should be. Sorry.\n"); + } + r->width = width; r->height = height; r->aspect = (GLfloat)width/(GLfloat)height; @@ -158,7 +185,7 @@ RenderContext *render_setup(int width, int height) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if ( GLEW_EXT_framebuffer_object ) { + if ( r->fbos ) { /* Create a small FBO for rendering reflections with */ glGenFramebuffersEXT(1, &r->fbo); @@ -190,10 +217,8 @@ RenderContext *render_setup(int width, int height) { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, r->swirly_texture, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } else { - fprintf(stderr, "EXT_framebuffer_object not supported\n"); } - + /* Create coordinates for a hemisphere to reuse later */ r->hemisphere_v = malloc(3*HEMI_NUM_VERTICES*sizeof(GLfloat)); r->hemisphere_n = malloc(3*HEMI_NUM_VERTICES*sizeof(GLfloat)); @@ -236,7 +261,7 @@ RenderContext *render_setup(int width, int height) { } } - render_load_shaders(r); + if ( r->shaders ) render_load_shaders(r); r->num_textures = 0; @@ -249,7 +274,7 @@ RenderContext *render_setup(int width, int height) { } void render_shutdown(RenderContext *r) { - render_delete_shaders(r); + if ( r->shaders ) render_delete_shaders(r); texture_free_all(r); } @@ -287,7 +312,7 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC p = m->primitives[j]; - if ( p->attribs & ATTRIB_PULSE ) { + if ( ((p->attribs & ATTRIB_PULSE) && !(p->attribs & ATTRIB_SWIRLY)) || ((p->attribs & ATTRIB_SWIRLY) && !r->fbos) ) { float s; s = fabsf(0.4*cosf(t * 0.001)); GLfloat c[] = {s*p->col_r, s*p->col_g, s*p->col_b, 1.0}; @@ -303,7 +328,7 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC if ( p->attribs & ATTRIB_SHINY ) { GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; glMaterialfv(GL_FRONT, GL_SPECULAR, white); - glMaterialf(GL_FRONT, GL_SHININESS, p->shininess); + glMaterialf(GL_FRONT, GL_SHININESS, p->shininess); /* FIXME: Shader ignores this value */ } else { glMaterialfv(GL_FRONT, GL_SPECULAR, black); } @@ -317,39 +342,48 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC /* Texture */ if ( p->attribs & ATTRIB_SWIRLY ) { - glBindTexture(GL_TEXTURE_2D, r->swirly_texture); - glEnable(GL_TEXTURE_2D); - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_emits"), 1); + if ( r->fbos && r->shaders ) { + glBindTexture(GL_TEXTURE_2D, r->swirly_texture); + glEnable(GL_TEXTURE_2D); + glUniform1i(glGetUniformLocation(r->lighting_program, "texture_emits"), 1); + } else { + if ( r->shaders ) { + glUniform1i(glGetUniformLocation(r->lighting_program, "texture_enabled"), 0); + } /* else don't enable texturing */ + } } else if ( p->texture != NULL ) { Texture *texture; texture = texture_lookup(r, p->texture); if ( texture != NULL ) { glBindTexture(GL_TEXTURE_2D, texture->texname); glEnable(GL_TEXTURE_2D); - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_enabled"), 1); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_enabled"), 1); } else { - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_enabled"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_enabled"), 0); } } else { - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_enabled"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_enabled"), 0); + } + if ( r->vbos ) { + glBindBuffer(GL_ARRAY_BUFFER, p->vertices_buffer); + glVertexPointer(3, GL_FLOAT, 0, NULL); + glBindBuffer(GL_ARRAY_BUFFER, p->normals_buffer); + glNormalPointer(GL_FLOAT, 0, NULL); + glBindBuffer(GL_ARRAY_BUFFER, p->texcoords_buffer); + glTexCoordPointer(2, GL_FLOAT, 0, NULL); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } else { + glVertexPointer(3, GL_FLOAT, 0, p->vertices); + glNormalPointer(GL_FLOAT, 0, p->normals); + glTexCoordPointer(2, GL_FLOAT, 0, p->texcoords); } - - glBindBufferARB(GL_ARRAY_BUFFER, p->vertices_buffer); - glVertexPointer(3, GL_FLOAT, 0, NULL); - glBindBufferARB(GL_ARRAY_BUFFER, p->normals_buffer); - glNormalPointer(GL_FLOAT, 0, NULL); - glBindBufferARB(GL_ARRAY_BUFFER, p->texcoords_buffer); - glTexCoordPointer(2, GL_FLOAT, 0, NULL); glDrawArrays(render_gltype(p->type), 0, p->num_vertices); *nvert += p->num_vertices; - glBindBufferARB(GL_ARRAY_BUFFER, 0); - glDisable(GL_TEXTURE_2D); - glPopMatrix(); if ( p->attribs & ATTRIB_SWIRLY ) { - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_emits"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_emits"), 0); } } else { @@ -365,17 +399,17 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC glNormalPointer(GL_FLOAT, 0, r->hemisphere_n); glTexCoordPointer(2, GL_FLOAT, 0, r->hemisphere_t); - if ( GLEW_EXT_framebuffer_object ) { + if ( r->fbos ) { glBindTexture(GL_TEXTURE_2D, r->fbotex); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_enabled"), 1); - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_emits"), 1); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_enabled"), 1); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_emits"), 1); } glDrawArrays(GL_QUADS, 0, HEMI_NUM_VERTICES); *nvert += HEMI_NUM_VERTICES; - glUniform1iARB(glGetUniformLocationARB(r->lighting_program, "texture_emits"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(r->lighting_program, "texture_emits"), 0); glDisable(GL_TEXTURE_2D); @@ -598,7 +632,7 @@ void render_draw(Game *game, Uint32 t) { r = game->render; - if ( GLEW_EXT_framebuffer_object ) { + if ( r->fbos ) { /* First pass: Looking upwards */ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r->fbo); @@ -621,8 +655,8 @@ void render_draw(Game *game, Uint32 t) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r->swirly_fbo); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, 128, 128); - glUseProgramObjectARB(r->swirly_program); - glUniform1fARB(glGetUniformLocationARB(game->render->swirly_program, "time"), t); + if ( r->shaders ) glUseProgram(r->swirly_program); + if ( r->shaders ) glUniform1f(glGetUniformLocation(game->render->swirly_program, "time"), t); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -652,11 +686,11 @@ void render_draw(Game *game, Uint32 t) { game->lander->x, game->lander->y, game->lander->z, sqrtf(2.0)*sinf(game->lander->yaw)*sinf(game->view_angle), sqrtf(2.0)*cosf(game->lander->yaw)*sinf(game->view_angle), sqrtf(2.0)*cosf(game->view_angle)); - glUseProgramObjectARB(r->lighting_program); - glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "texture"), 0); - glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "texture_only"), 0); - glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "texture_enabled"), 1); - glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "fill_light_enabled"), 0); + if ( r->shaders ) glUseProgram(r->lighting_program); + if ( r->shaders ) glUniform1i(glGetUniformLocation(game->render->lighting_program, "texture"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(game->render->lighting_program, "texture_only"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(game->render->lighting_program, "texture_enabled"), 1); + if ( r->shaders ) glUniform1i(glGetUniformLocation(game->render->lighting_program, "fill_light_enabled"), 0); render_setup_lighting(game); render_draw_stuff(game, t); @@ -674,10 +708,10 @@ void render_draw(Game *game, Uint32 t) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); render_model_instance_draw(game->lander, t, r, NULL); glPopClientAttrib(); - glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "texture_enabled"), 0); + if ( r->shaders ) glUniform1i(glGetUniformLocation(game->render->lighting_program, "texture_enabled"), 0); render_draw_line(game->lander->x, game->lander->y, game->lander->z, game->lander->x, game->lander->y, game->lander->z-200.0); glDisable(GL_LIGHT2); - glUseProgramObjectARB(0); + if ( r->shaders ) glUseProgram(0); render_draw_2d(r, game); diff --git a/src/texture.c b/src/texture.c index b2aba03..36f6a8b 100644 --- a/src/texture.c +++ b/src/texture.c @@ -34,11 +34,11 @@ void texture_load(RenderContext *ctx, char *name) { png_bytep *row_pointers; unsigned int x; unsigned int y; - char tmp[64]; + char tmp[128]; uint8_t *texels; /* Open file */ - snprintf(tmp, 63, "%s/textures/%s.png", DATADIR, name); + snprintf(tmp, 127, "%s/textures/%s.png", DATADIR, name); fh = fopen(tmp, "rb"); if ( !fh ) { fprintf(stderr, "Couldn't open texture file '%s'\n", tmp); diff --git a/src/types.h b/src/types.h index 2059cbb..39238fd 100644 --- a/src/types.h +++ b/src/types.h @@ -113,6 +113,10 @@ typedef struct { typedef struct { + int shaders; + int vbos; + int fbos; + /* Lighting shaders */ GLuint lighting_vert; GLuint lighting_frag; -- cgit v1.2.3