diff options
author | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-05-24 21:30:42 +0000 |
---|---|---|
committer | taw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5> | 2008-05-24 21:30:42 +0000 |
commit | 8684d5a1a6d18e32eb15324f19da18ae88472707 (patch) | |
tree | a14fd840242c533ec1cf2d949d43a526555efec5 | |
parent | 3e3436f1a84a3f418e9894356a6262118b30708f (diff) |
Loads of shader and lighting stuff
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@39 84d2e878-0bd5-11dd-ad15-13eda11d74c5
-rw-r--r-- | data/shaders/lighting.frag | 75 | ||||
-rw-r--r-- | data/shaders/lighting.vert | 39 | ||||
-rwxr-xr-x | scripts/shader-dev-mode.sh | 8 | ||||
-rw-r--r-- | src/game.c | 2 | ||||
-rw-r--r-- | src/main.c | 45 | ||||
-rw-r--r-- | src/model.c | 2 | ||||
-rw-r--r-- | src/render.c | 71 | ||||
-rw-r--r-- | src/types.h | 2 |
8 files changed, 152 insertions, 92 deletions
diff --git a/data/shaders/lighting.frag b/data/shaders/lighting.frag index ee1df5b..77102e9 100644 --- a/data/shaders/lighting.frag +++ b/data/shaders/lighting.frag @@ -9,43 +9,56 @@ * */ -varying vec4 col_ambi; -varying vec4 col_diff; -varying vec4 col_spec; -varying vec4 col_emit; -varying float shininess; - varying vec3 normal; -varying vec3 halfvc; + +varying vec3 light0vc; +varying vec3 light1vc; +varying vec3 light2vc; +varying vec3 light2hvc; uniform sampler2D texture; +uniform int fill_light_enabled; + +varying vec3 col_ambi_diff; +varying vec3 col_emit; void main() { - vec4 ambi; - vec4 diff; - vec4 spec; - vec3 light; - vec3 norml; - - /* Ambient contribution */ - ambi = col_ambi * gl_LightModel.ambient; - ambi += col_ambi * gl_LightSource[0].ambient; - ambi = vec4(0.0, 0.0, 0.0, 1.0); - - /* Diffuse contribution */ - light = vec3(normalize(gl_LightSource[0].position)); - norml = normalize(normal); - diff = col_diff * clamp(dot(light, normal), 0.0, 1.0); - - /* Specular contribution */ - spec = col_spec * clamp(pow(dot( vec3(normal), halfvc ), shininess), 0.0, 1.0); - spec = vec4(0.0, 0.0, 0.0, 1.0); - - gl_FragColor = vec4(min(col_emit.r + ambi.r + diff.r + spec.r, 1.0), - min(col_emit.g + ambi.g + diff.g + spec.g, 1.0), - min(col_emit.b + ambi.b + diff.b + spec.b, 1.0), - min(col_emit.a + ambi.a + diff.a + spec.a, 1.0)); + vec3 ambi; + vec3 emit; + vec3 diff = vec3(0.0, 0.0, 0.0); + vec3 spec = vec3(0.0, 0.0, 0.0); + + vec3 norm = normalize(normal); + + /* Ambient */ + ambi = col_ambi_diff * gl_LightModel.ambient.rgb; + + /* Emission */ + emit = col_emit; + + /* Spotlight (light 0) - diffuse only, positional, spotlight */ + float falloff = 1 - length(light0vc) * gl_LightSource[0].linearAttenuation; + float spot = max(dot(normalize(-light0vc), gl_LightSource[0].spotDirection), 0.0); + spot = pow(spot, gl_LightSource[0].spotExponent); + diff += col_ambi_diff * gl_LightSource[0].diffuse.rgb * spot * falloff * max(dot(normalize(light0vc).xyz, norm), 0.0); + + /* Background glow (light 1) - diffuse only, directional */ + diff += col_ambi_diff * gl_LightSource[1].diffuse.rgb * max(dot(vec3(light1vc), norm), 0.0); + + /* Fill-in light (light 2) - this is the only one which has a specular component */ + if ( fill_light_enabled == 1 ) { + /* Diffuse */ + diff += col_ambi_diff * gl_LightSource[2].diffuse.rgb * max(dot(vec3(light1vc), norm), 0.0); + /* Specular */ + float ndothv = max(dot(norm, normalize(light2hvc)), 0.0); + spec = vec3(1.0, 1.0, 1.0) * gl_LightSource[2].specular.rgb * pow(ndothv, 80.0); + } + + gl_FragColor = vec4(min(emit.r + ambi.r + diff.r + spec.r, 1.0), + min(emit.g + ambi.g + diff.g + spec.g, 1.0), + min(emit.b + ambi.b + diff.b + spec.b, 1.0), + 1.0); gl_FragColor *= texture2D(texture, gl_TexCoord[0].st); diff --git a/data/shaders/lighting.vert b/data/shaders/lighting.vert index eaa51c2..1817e9f 100644 --- a/data/shaders/lighting.vert +++ b/data/shaders/lighting.vert @@ -9,27 +9,36 @@ * */ -varying vec4 col_ambi; -varying vec4 col_diff; -varying vec4 col_spec; -varying vec4 col_emit; -varying float shininess; - varying vec3 normal; -varying vec3 halfvc; + +varying vec3 light0vc; +varying vec3 light1vc; +varying vec3 light2vc; +varying vec3 light2hvc; + +uniform int fill_light_enabled; + +varying vec3 col_ambi_diff; +varying vec3 col_emit; void main() { - /* Directions */ - normal = normalize(gl_NormalMatrix * gl_Normal); - halfvc = vec3(gl_LightSource[0].halfVector); + /* Spotlight - positional light */ + vec4 vert = gl_ModelViewMatrix * gl_Vertex; + light0vc = gl_LightSource[0].position.xyz - vert.xyz; + + /* Diffuse "background glow" - this can be normalised only once, here, since 'position' + * is really 'direction' and is the same for all vertices. */ + light1vc = normalize(vec3(gl_LightSource[1].position)); + + /* Fill-in light */ + light2vc = normalize(vec3(gl_LightSource[2].position)); + light2hvc = normalize(gl_LightSource[2].halfVector.xyz); /* Material properties */ - col_ambi = gl_FrontMaterial.ambient; - col_diff = gl_FrontMaterial.diffuse; - col_spec = gl_FrontMaterial.specular; - col_emit = gl_FrontMaterial.emission; - shininess = gl_FrontMaterial.shininess; + normal = gl_NormalMatrix * gl_Normal; + col_ambi_diff = gl_Color.rgb; + col_emit = gl_FrontMaterial.emission.rgb; /* Coordinates */ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; diff --git a/scripts/shader-dev-mode.sh b/scripts/shader-dev-mode.sh new file mode 100755 index 0000000..dfab8b4 --- /dev/null +++ b/scripts/shader-dev-mode.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +rm /usr/local/share/thrust3d/shaders/lighting.vert +ln -s $(pwd)/data/shaders/lighting.vert /usr/local/share/thrust3d/shaders/lighting.vert + +rm /usr/local/share/thrust3d/shaders/lighting.frag +ln -s $(pwd)/data/shaders/lighting.frag /usr/local/share/thrust3d/shaders/lighting.frag + @@ -240,8 +240,6 @@ Game *game_new(int width, int height) { g->view_dist = 5.0; g->paused = 0; g->pause_rel = 1; - g->frame_delay = 8000; - g->frame_delay_fiddled = 0; g->frames = 0; g->t_fps = SDL_GetTicks(); g->fps = 0; @@ -61,12 +61,16 @@ int main(int argc, char *argv[]) { switch ( c ) { case 'r' : { - if ( strcasecmp(optarg, "640") == 0 ) res = RES_640; - if ( strcasecmp(optarg, "800") == 0 ) res = RES_800; - if ( strcasecmp(optarg, "1280") == 0 ) res = RES_1280; - if ( strcasecmp(optarg, "1330") == 0 ) res = RES_1330; - if ( strcasecmp(optarg, "1440") == 0 ) res = RES_1440; - if ( strcasecmp(optarg, "1600") == 0 ) res = RES_1600; + if ( strcasecmp(optarg, "640") == 0 ) res = RES_640; + else if ( strcasecmp(optarg, "800") == 0 ) res = RES_800; + else if ( strcasecmp(optarg, "1280") == 0 ) res = RES_1280; + else if ( strcasecmp(optarg, "1330") == 0 ) res = RES_1330; + else if ( strcasecmp(optarg, "1440") == 0 ) res = RES_1440; + else if ( strcasecmp(optarg, "1600") == 0 ) res = RES_1600; + else { + fprintf(stderr, "Unrecognised resolution '%s'\n", optarg); + exit(1); + } break; } @@ -187,11 +191,11 @@ int main(int argc, char *argv[]) { render_draw(game, t); } - printf("%+7.4f %+7.4f %+7.4f %+5.1f deg %+7.5f %+7.5f %+7.5f %2i %2i %2i %3i fps\r", - game->lander->x, game->lander->y, game->lander->z, - rad2deg(game->lander->yaw), game->lander->vx, game->lander->vy, game->lander->vz, - game->cur_room_x, game->cur_room_y, game->cur_room_z, game->fps); - fflush(stdout); + //printf("%+7.4f %+7.4f %+7.4f %+5.1f deg %+7.5f %+7.5f %+7.5f %2i %2i %2i %3i fps\r", + // game->lander->x, game->lander->y, game->lander->z, + // rad2deg(game->lander->yaw), game->lander->vx, game->lander->vy, game->lander->vz, + // game->cur_room_x, game->cur_room_y, game->cur_room_z, game->fps); + //fflush(stdout); /* Calculate FPS every half a second */ game->frames++; @@ -199,21 +203,14 @@ int main(int argc, char *argv[]) { game->fps = (500*game->frames) / (t - game->t_fps); game->t_fps = t; game->frames = 0; - game->frame_delay_fiddled = 0; - } - - /* Attempt to hold output FPS close to some target value */ - if ( (!game->frame_delay_fiddled) && (game->fps < 30) ) { - game->frame_delay -= game->frame_delay/20; - game->frame_delay_fiddled = 1; - } - if ( (!game->frame_delay_fiddled) && (game->fps > 50) ) { - game->frame_delay += game->frame_delay/20; - game->frame_delay_fiddled = 1; } + game->radiation = game->fps / 50.0; - /* Sleep for a bit to avoid hogging the CPU. */ - usleep(game->frame_delay); + /* 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 + * is the case. */ + usleep(25000); } diff --git a/src/model.c b/src/model.c index 76e84c7..663a862 100644 --- a/src/model.c +++ b/src/model.c @@ -279,7 +279,7 @@ static int model_load(ModelContext *ctx, const char *name, RenderContext *render } /* Subdivide the previous face if requested */ - if ( sscanf(line, "subdivide %f %f", &x, &y) == 2 ) { + if ( sscanf(line, "ssubdivide %f %f", &x, &y) == 2 ) { if ( type == PRIMITIVE_QUADS ) { if ( (num_vertices % 4)==0 ) { GLfloat u, v; diff --git a/src/render.c b/src/render.c index 6e9d60f..d07f2fc 100644 --- a/src/render.c +++ b/src/render.c @@ -26,6 +26,8 @@ #include "texture.h" #include "utils.h" +#define PANEL_ALPHA 0.3 + /* Utility function to load and compile a shader, checking the info log */ static GLhandleARB render_load_shader(const char *filename, GLenum type) { @@ -53,6 +55,8 @@ static GLhandleARB render_load_shader(const char *filename, GLenum type) { glGetInfoLogARB(shader, 4095, &l, text); if ( l > 0 ) { printf("%s\n", text); fflush(stdout); + } else { + printf("Shader compilation failed.\n"); } } @@ -60,6 +64,28 @@ static GLhandleARB render_load_shader(const char *filename, GLenum type) { } +static int render_validate_shader(GLhandleARB shader) { + + GLint status; + int l; + char text[4096]; + + glValidateProgramARB(shader); + glGetObjectParameterivARB(shader, GL_OBJECT_VALIDATE_STATUS_ARB, &status); + if ( status == GL_FALSE ) { + glGetInfoLogARB(shader, 4095, &l, text); + if ( l > 0 ) { + printf("%s\n", text); fflush(stdout); + } else { + printf("Shader did not validate successfully.\n"); + } + return 0; + } + + return 1; + +} + static void render_load_shaders(RenderContext *r) { r->lighting_vert = render_load_shader(DATADIR"/shaders/lighting.vert", GL_VERTEX_SHADER_ARB); @@ -68,6 +94,7 @@ static void render_load_shaders(RenderContext *r) { glAttachObjectARB(r->lighting_program, r->lighting_vert); glAttachObjectARB(r->lighting_program, r->lighting_frag); glLinkProgramARB(r->lighting_program); + render_validate_shader(r->lighting_program); } @@ -81,8 +108,8 @@ static void render_delete_shaders(RenderContext *r) { } -#define HEMI_ROUND_BITS 64 -#define HEMI_UP_BITS 32 +#define HEMI_ROUND_BITS 16 +#define HEMI_UP_BITS 8 #define HEMI_NUM_VERTICES (4 * HEMI_ROUND_BITS * HEMI_UP_BITS) #define ADD_VERTEX \ r->hemisphere_v[3*i + 0] = xv; \ @@ -197,13 +224,16 @@ static GLenum render_gltype(PrimitiveType type) { } -static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderContext *r) { +static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderContext *r, int *nvert) { int j; Model *m; GLfloat x, y, z; GLfloat black[] = {0.0, 0.0, 0.0}; - + int wibble; + + if ( nvert == NULL ) nvert = &wibble; + m = instance->model; if ( m == NULL ) return 0; /* No model to draw */ x = instance->x; @@ -265,6 +295,7 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC glTexCoordPointer(2, GL_FLOAT, 0, NULL); //glTexCoordPointer(2, GL_FLOAT, 0, p->texcoords); glDrawArrays(render_gltype(p->type), 0, p->num_vertices); + *nvert += p->num_vertices; glBindBufferARB(GL_ARRAY_BUFFER, 0); glDisable(GL_TEXTURE_2D); @@ -293,6 +324,7 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDrawArrays(GL_QUADS, 0, HEMI_NUM_VERTICES); + *nvert += HEMI_NUM_VERTICES; glDisable(GL_TEXTURE_2D); @@ -306,7 +338,7 @@ static int render_model_instance_draw(ModelInstance *instance, Uint32 t, RenderC } } - + return 0; } @@ -328,6 +360,7 @@ static void render_draw_line(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLf static void render_draw_stuff(Game *game, Uint32 t) { int i; + int nvert = 0; glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); glEnableClientState(GL_VERTEX_ARRAY); @@ -352,12 +385,14 @@ static void render_draw_stuff(Game *game, Uint32 t) { z = room->rz - game->cur_room_z; glPushMatrix(); glTranslatef(10.0*x, 10.0*y, 10.0*z); - render_model_instance_draw(room->objects[j], t, game->render); + render_model_instance_draw(room->objects[j], t, game->render, &nvert); glPopMatrix(); } } + //printf("%i ***\n", nvert); + glPopClientAttrib(); } @@ -396,7 +431,7 @@ static void render_setup_lighting(Game *game) { glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, dir); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 20.0); - glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05); glEnable(GL_LIGHT0); pos[0] = -1.0; @@ -449,7 +484,7 @@ static void render_draw_2d(RenderContext *r, Game *game) { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } - glColor4f(1.0, 1.0, 1.0, 0.5); + glColor4f(1.0, 1.0, 1.0, PANEL_ALPHA); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0); /* Bottom left */ @@ -465,10 +500,10 @@ static void render_draw_2d(RenderContext *r, Game *game) { /* Radiation meter */ cg = 1.0 - game->radiation; glBegin(GL_QUADS); - glColor4f(1.0, 1.0, 0.0, 0.5); + glColor4f(1.0, 1.0, 0.0, PANEL_ALPHA); glVertex2f(-1.0, -0.8); /* Bottom left */ glVertex2f(-0.9, -0.8); /* Bottom right */ - glColor4f(0.8, cg, 0.0, 0.5+0.5*game->radiation); + glColor4f(0.8, cg, 0.0, PANEL_ALPHA); glVertex2f(-0.9, -0.8+(1.8*game->radiation)); /* Top right */ glVertex2f(-1.0, -0.8+(1.8*game->radiation)); /* Top left */ glEnd(); @@ -480,7 +515,7 @@ static void render_draw_2d(RenderContext *r, Game *game) { glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } - glColor4f(1.0, 1.0, 1.0, 0.5); + glColor4f(1.0, 1.0, 1.0, PANEL_ALPHA); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(0.9, -1.0); /* Bottom left */ @@ -498,10 +533,10 @@ static void render_draw_2d(RenderContext *r, Game *game) { cg = game->fuel; cb = 0.2 + 0.1*game->fuel; glBegin(GL_QUADS); - glColor4f(1.0, 0.0, 0.2, 0.5); + glColor4f(1.0, 0.0, 0.2, PANEL_ALPHA); glVertex2f(0.9, -0.8); /* Bottom left */ glVertex2f(1.0, -0.8); /* Bottom right */ - glColor4f(cr, cg, cb, 0.5); + glColor4f(cr, cg, cb, PANEL_ALPHA); glVertex2f(1.0, -0.8+(1.8*game->fuel)); /* Top right */ glVertex2f(0.9, -0.8+(1.8*game->fuel)); /* Top left */ glEnd(); @@ -546,12 +581,13 @@ 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, "fill_light_enabled"), 0); render_setup_lighting(game); render_draw_stuff(game, t); /* Finally, draw the lander */ -// glUseProgramObjectARB(r->lighting_program); -// glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "texture"), 0); GLfloat pos[] = { -1.0, 0.8, 4.0, 0.0 }; GLfloat diffuse[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 }; @@ -559,6 +595,7 @@ void render_draw(Game *game, Uint32 t) { glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT2, GL_SPECULAR, specular); glEnable(GL_LIGHT2); + glUniform1iARB(glGetUniformLocationARB(game->render->lighting_program, "fill_light_enabled"), 1); glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); @@ -566,13 +603,13 @@ void render_draw(Game *game, Uint32 t) { 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); - render_model_instance_draw(game->lander, t, r); + render_model_instance_draw(game->lander, t, r, NULL); glPopClientAttrib(); 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_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_LIGHT2); -// glUseProgramObjectARB(0); + glUseProgramObjectARB(0); render_draw_2d(r, game); diff --git a/src/types.h b/src/types.h index d0283bb..6d772f5 100644 --- a/src/types.h +++ b/src/types.h @@ -175,8 +175,6 @@ typedef struct { unsigned int reverse; Uint32 tlast; /* Time at which the last physics step was performed */ - int frame_delay; /* Delay between frames */ - int frame_delay_fiddled; /* frame_delay has been fiddled since the last FPS calculation */ ModelInstance *lander; |