aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-05-18 23:58:59 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-05-18 23:58:59 +0000
commit723f4a5e4693afbf5654bd830e78db13df9020ca (patch)
tree854684a756a40da1e939a782f1510d497518b60d
parent6741901029cd322a4abf61a91ac34afabf9b093a (diff)
More environment mapping stuff
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@28 84d2e878-0bd5-11dd-ad15-13eda11d74c5
-rw-r--r--data/models/lander7
-rw-r--r--src/model.c26
-rw-r--r--src/render.c207
-rw-r--r--src/types.h7
4 files changed, 177 insertions, 70 deletions
diff --git a/data/models/lander b/data/models/lander
index 0f2b5e4..56a4371 100644
--- a/data/models/lander
+++ b/data/models/lander
@@ -347,7 +347,8 @@ colour 0.0 0.5 0.2
-0.10 0.35 0.05
HEMISPHERE
-colour 0.0 0.5 0.2
- 0.00 0.00 0.50
-radius 1.0
+colour 0.07 0.07 0.07
+shiny 100.0
+ 0.00 0.00 0.20
+radius 0.25
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;