aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/shaders/lighting.frag75
-rw-r--r--data/shaders/lighting.vert39
-rwxr-xr-xscripts/shader-dev-mode.sh8
-rw-r--r--src/game.c2
-rw-r--r--src/main.c45
-rw-r--r--src/model.c2
-rw-r--r--src/render.c71
-rw-r--r--src/types.h2
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
+
diff --git a/src/game.c b/src/game.c
index c7c2c68..221ba23 100644
--- a/src/game.c
+++ b/src/game.c
@@ -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;
diff --git a/src/main.c b/src/main.c
index f0016d1..440d54f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;