diff options
author | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-05-18 23:58:59 +0000 |
---|---|---|
committer | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-05-18 23:58:59 +0000 |
commit | 723f4a5e4693afbf5654bd830e78db13df9020ca (patch) | |
tree | 854684a756a40da1e939a782f1510d497518b60d /src | |
parent | 6741901029cd322a4abf61a91ac34afabf9b093a (diff) |
More environment mapping stuff
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@28 84d2e878-0bd5-11dd-ad15-13eda11d74c5
Diffstat (limited to 'src')
-rw-r--r-- | src/model.c | 26 | ||||
-rw-r--r-- | src/render.c | 207 | ||||
-rw-r--r-- | src/types.h | 7 |
3 files changed, 173 insertions, 67 deletions
diff --git a/src/model.c b/src/model.c index bb8758f..5607e95 100644 --- a/src/model.c +++ b/src/model.c @@ -73,10 +73,19 @@ 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) { + int n, PrimitiveAttrib attribs, GLfloat r, GLfloat g, GLfloat b, char *texture, + GLfloat radius, GLfloat shininess) { Primitive *p; + /* Sanity check */ + if ( type == PRIMITIVE_HEMISPHERE ) { + if ( !(attribs & ATTRIB_RADIUS) ) { + fprintf(stderr, "Radius must be specified for all hemispheres in model '%s'\n", model->name); + return NULL; + } + } + p = malloc(sizeof(Primitive)); if ( p == NULL ) return NULL; @@ -112,6 +121,8 @@ static Primitive *model_add_primitive(Model *model, GLenum type, GLfloat *vertic p->col_g = g; p->col_b = b; p->texture = texture; + p->radius = radius; + p->shininess = shininess; model->attrib_total = model->attrib_total | attribs; model->primitives = realloc(model->primitives, sizeof(Primitive *) * (model->num_primitives+1)); @@ -162,6 +173,8 @@ static int model_load(ModelContext *ctx, const char *name, RenderContext *render GLfloat col_r = 0.0; GLfloat col_g = 0.0; GLfloat col_b = 0.0; + GLfloat radius = 0.0; + GLfloat shininess = 100.0; PrimitiveAttrib attribs; char *texture; @@ -197,7 +210,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); + attribs, col_r, col_g, col_b, texture, radius, shininess); num_vertices = 0; type = PRIMITIVE_TRIANGLES; attribs = ATTRIB_NONE; @@ -211,6 +224,9 @@ static int model_load(ModelContext *ctx, const char *name, RenderContext *render if ( strncmp(line, "TRIANGLES", 9) == 0 ) { type = PRIMITIVE_TRIANGLES; } + if ( strncmp(line, "HEMISPHERE", 10) == 0 ) { + type = PRIMITIVE_HEMISPHERE; + } if ( sscanf(line, "%f %f %f %f %f", &forget, &forget, &forget, &x, &y) == 5 ) { texx = x; texy = y; @@ -246,6 +262,12 @@ static int model_load(ModelContext *ctx, const char *name, RenderContext *render attribs = attribs | ATTRIB_COLOUR; col_r = r; col_g = g; col_b = b; } + if ( sscanf(line, "radius %f", &radius) == 1 ) { + attribs = attribs | ATTRIB_RADIUS; + } + if ( sscanf(line, "shiny %f", &shininess) == 1 ) { + attribs = attribs | ATTRIB_SHINY; + } if ( strncmp(line, "texture", 7) == 0 ) { if ( strlen(line) < 9 ) { fprintf(stderr, "Invalid texture specification\n"); diff --git a/src/render.c b/src/render.c index 9419413..beb9fb7 100644 --- a/src/render.c +++ b/src/render.c @@ -35,6 +35,7 @@ static GLhandleARB render_load_shader(const char *filename, GLenum type) { size_t len; FILE *fh; int l; + GLint status; fh = fopen(filename, "r"); if ( fh == NULL ) { @@ -48,47 +49,62 @@ static GLhandleARB render_load_shader(const char *filename, GLenum type) { shader = glCreateShaderObjectARB(type); glShaderSourceARB(shader, 1, &source, NULL); glCompileShaderARB(shader); - glGetInfoLogARB(shader, 4095, &l, text); - if ( l > 0 ) { - printf("%s\n", text); fflush(stdout); + glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); + if ( status == GL_FALSE ) { + glGetInfoLogARB(shader, 4095, &l, text); + if ( l > 0 ) { + printf("%s\n", text); fflush(stdout); + } } return shader; } -static void render_load_shaders(RenderContext *ctx) { +static void render_load_shaders(RenderContext *r) { - ctx->lighting_vert = render_load_shader(DATADIR"/shaders/lighting.vert", GL_VERTEX_SHADER_ARB); - ctx->lighting_frag = render_load_shader(DATADIR"/shaders/lighting.frag", GL_FRAGMENT_SHADER_ARB); - ctx->lighting_program = glCreateProgramObjectARB(); - glAttachObjectARB(ctx->lighting_program, ctx->lighting_vert); - glAttachObjectARB(ctx->lighting_program, ctx->lighting_frag); - glLinkProgramARB(ctx->lighting_program); + r->lighting_vert = render_load_shader(DATADIR"/shaders/lighting.vert", GL_VERTEX_SHADER_ARB); + r->lighting_frag = render_load_shader(DATADIR"/shaders/lighting.frag", GL_FRAGMENT_SHADER_ARB); + r->lighting_program = glCreateProgramObjectARB(); + glAttachObjectARB(r->lighting_program, r->lighting_vert); + glAttachObjectARB(r->lighting_program, r->lighting_frag); + glLinkProgramARB(r->lighting_program); } -static void render_delete_shaders(RenderContext *ctx) { +static void render_delete_shaders(RenderContext *r) { - glDetachObjectARB(ctx->lighting_program, ctx->lighting_frag); - glDetachObjectARB(ctx->lighting_program, ctx->lighting_vert); - glDeleteObjectARB(ctx->lighting_vert); - glDeleteObjectARB(ctx->lighting_frag); - glDeleteObjectARB(ctx->lighting_program); + glDetachObjectARB(r->lighting_program, r->lighting_frag); + glDetachObjectARB(r->lighting_program, r->lighting_vert); + glDeleteObjectARB(r->lighting_vert); + glDeleteObjectARB(r->lighting_frag); + glDeleteObjectARB(r->lighting_program); } +#define HEMI_ROUND_BITS 64 +#define HEMI_UP_BITS 32 +#define HEMI_NUM_VERTICES (4 * HEMI_ROUND_BITS * HEMI_UP_BITS) +#define ADD_VERTEX \ + r->hemisphere_v[3*i + 0] = xv; \ + r->hemisphere_v[3*i + 1] = yv; \ + r->hemisphere_v[3*i + 2] = zv; \ + r->hemisphere_n[3*i + 0] = xv; \ + r->hemisphere_n[3*i + 1] = yv; \ + r->hemisphere_n[3*i + 2] = zv; \ + i++; + /* OpenGL initial setup */ RenderContext *render_setup(int width, int height) { - RenderContext *ctx; + RenderContext *r; - ctx = malloc(sizeof(RenderContext)); - if ( ctx == NULL ) return NULL; + r = malloc(sizeof(RenderContext)); + if ( r == NULL ) return NULL; - ctx->width = width; - ctx->height = height; - ctx->aspect = (GLfloat)width/(GLfloat)height; + r->width = width; + r->height = height; + r->aspect = (GLfloat)width/(GLfloat)height; glClearColor(0.0, 0.0, 0.0, 1.0); @@ -104,38 +120,70 @@ RenderContext *render_setup(int width, int height) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* Create a small FBO for rendering reflections with */ - glGenFramebuffersEXT(1, &ctx->fbo); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, ctx->fbo); + glGenFramebuffersEXT(1, &r->fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, r->fbo); /* Add a (texture) colour buffer to the FBO */ - glGenTextures(1, &ctx->fbotex); - glBindTexture(GL_TEXTURE_2D, ctx->fbotex); + glGenTextures(1, &r->fbotex); + glBindTexture(GL_TEXTURE_2D, r->fbotex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, ctx->fbotex, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, r->fbotex, 0); /* Add a depth buffer to the FBO */ - glGenRenderbuffersEXT(1, &ctx->fbodepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, ctx->fbodepth); + glGenRenderbuffersEXT(1, &r->fbodepth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, r->fbodepth); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, 256, 256); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ctx->fbodepth); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, ctx->fbodepth); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, r->fbodepth); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, r->fbodepth); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - render_load_shaders(ctx); + /* 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)); + double step_up = M_PI_2/(double)HEMI_UP_BITS; + double step_round = 2*M_PI/(double)HEMI_ROUND_BITS; + int is, js; + int i = 0; + for ( is=0; is<HEMI_ROUND_BITS; is++ ) { + for ( js=0; js<HEMI_UP_BITS; js++ ) { + double theta, phi; + GLfloat xv, yv, zv; + theta = (2*M_PI/(double)HEMI_ROUND_BITS) * (double)is; + phi = (M_PI_2/(double)HEMI_UP_BITS) * (double)js; + xv = cos(theta)*cos(phi); + yv = sin(theta)*cos(phi); + zv = sin(phi); + ADD_VERTEX + xv = cos(theta+step_round)*cos(phi); + yv = sin(theta+step_round)*cos(phi); + zv = sin(phi); + ADD_VERTEX + xv = cos(theta+step_round)*cos(phi+step_up); + yv = sin(theta+step_round)*cos(phi+step_up); + zv = sin(phi+step_up); + ADD_VERTEX + xv = cos(theta)*cos(phi+step_up); + yv = sin(theta)*cos(phi+step_up); + zv = sin(phi+step_up); + ADD_VERTEX + } + } + + render_load_shaders(r); - ctx->num_textures = 0; + r->num_textures = 0; /* Load misc texture bits */ - texture_load(ctx, "radioactive"); - texture_load(ctx, "fuel"); + texture_load(r, "radioactive"); + texture_load(r, "fuel"); - return ctx; + return r; } -void render_shutdown(RenderContext *ctx) { - render_delete_shaders(ctx); - texture_free_all(ctx); +void render_shutdown(RenderContext *r) { + render_delete_shaders(r); + texture_free_all(r); } static GLenum render_gltype(PrimitiveType type) { @@ -150,7 +198,7 @@ static GLenum render_gltype(PrimitiveType type) { } -static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderContext *ctx) { +static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderContext *r) { int j; Model *m; @@ -175,37 +223,66 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC GLfloat c[] = {s*p->col_r, s*p->col_g, s*p->col_b}; glMaterialfv(GL_FRONT, GL_EMISSION, c); glColor3f(0.3, 0.3, 0.3); - glMaterialfv(GL_FRONT, GL_SPECULAR, black); } else if ( p->attribs & ATTRIB_COLOUR ) { glMaterialfv(GL_FRONT, GL_EMISSION, black); - glMaterialfv(GL_FRONT, GL_SPECULAR, black); glColor3f(p->col_r, p->col_g, p->col_b); } else { glMaterialfv(GL_FRONT, GL_EMISSION, black); - glMaterialfv(GL_FRONT, GL_SPECULAR, black); glColor3f(1.0, 1.0, 1.0); } + if ( p->attribs & ATTRIB_SHINY ) { + GLfloat white[] = {1.0, 1.0, 1.0}; + glMaterialfv(GL_FRONT, GL_SPECULAR, white); + glMaterialf(GL_FRONT, GL_SHININESS, p->shininess); + } else { + glMaterialfv(GL_FRONT, GL_SPECULAR, black); + } - /* Location and orientation */ - glPushMatrix(); - glTranslatef(x, y, z); - glRotatef(rad2deg(instance->yaw), 0.0, 0.0, -1.0); /* Minus sign defines +yaw as "right" */ + if ( p->type != PRIMITIVE_HEMISPHERE ) { + + /* Location and orientation */ + glPushMatrix(); + glTranslatef(x, y, z); + glRotatef(rad2deg(instance->yaw), 0.0, 0.0, -1.0); /* Minus sign defines +yaw as "right" */ - /* Texture */ - if ( p->texture != NULL ) { - Texture *texture; - texture = texture_lookup(ctx, p->texture); - if ( texture != NULL ) { - glBindTexture(GL_TEXTURE_2D, texture->texname); - glEnable(GL_TEXTURE_2D); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + /* Texture */ + 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); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } } - } - glVertexPointer(3, GL_FLOAT, 0, p->vertices); - glNormalPointer(GL_FLOAT, 0, p->normals); - glTexCoordPointer(2, GL_FLOAT, 0, p->texcoords); - glDrawArrays(render_gltype(p->type), 0, p->num_vertices); + glVertexPointer(3, GL_FLOAT, 0, p->vertices); + glNormalPointer(GL_FLOAT, 0, p->normals); + glTexCoordPointer(2, GL_FLOAT, 0, p->texcoords); + glDrawArrays(render_gltype(p->type), 0, p->num_vertices); + + } else { + + glPushMatrix(); + glTranslatef(x+p->vertices[0], y+p->vertices[1], z+p->vertices[2]); + glScalef(p->radius, p->radius, p->radius); + glEnable(GL_RESCALE_NORMAL); + glRotatef(rad2deg(instance->yaw), 0.0, 0.0, -1.0); /* Minus sign defines +yaw as "right" */ + glVertexPointer(3, GL_FLOAT, 0, r->hemisphere_v); + glNormalPointer(GL_FLOAT, 0, r->hemisphere_n); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glBindTexture(GL_TEXTURE_2D, r->fbotex); + glEnable(GL_TEXTURE_2D); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glDrawArrays(GL_QUADS, 0, HEMI_NUM_VERTICES); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_RESCALE_NORMAL); + + } glPopMatrix(); @@ -272,11 +349,11 @@ static void render_setup_lighting(Game *game) { GLfloat pos[] = {-1.0, -0.8, 1.3, 0.0}; GLfloat ambient[4]; - GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0}; - GLfloat specular[] = {0.8, 0.8, 0.8, 1.0}; - + GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; + GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; + glEnable(GL_LIGHTING); - + ambient[0] = 0.3; ambient[1] = 0.3; ambient[2] = 0.3; ambient[3] = 1.0; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_POSITION, pos); @@ -378,7 +455,7 @@ void render_draw(Game *game, Uint32 t) { glViewport(0, 0, 256, 256); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(70.0, 1.0, 0.1, 100.0); + gluPerspective(70.0, 1.0, 0.1, 180.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(game->lander->x, game->lander->y, game->lander->z, diff --git a/src/types.h b/src/types.h index fa8a524..3a62301 100644 --- a/src/types.h +++ b/src/types.h @@ -32,6 +32,8 @@ typedef enum { ATTRIB_NONE = 0, ATTRIB_COLOUR = 1<<0, /* Colour specified? */ ATTRIB_PULSE = 1<<1, /* Pulsating colour */ + ATTRIB_RADIUS = 1<<2, /* Radius is set */ + ATTRIB_SHINY = 1<<3, /* Primitive is shiny */ } PrimitiveAttrib; typedef enum { @@ -53,6 +55,8 @@ typedef struct { GLfloat col_g; GLfloat col_b; char *texture; + GLfloat radius; + GLfloat shininess; } Primitive; @@ -118,6 +122,9 @@ typedef struct { GLfloat aspect; int width; int height; + + GLfloat *hemisphere_v; + GLfloat *hemisphere_n; } RenderContext; |