aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-08-06 11:57:50 +0000
committertaw27 <taw27@84d2e878-0bd5-11dd-ad15-13eda11d74c5>2008-08-06 11:57:50 +0000
commitbe186c70322fc3e00b9e79c5a0c0f504fb7f3f17 (patch)
tree814b7dcb31b1019a0123fff36c599bb1ba70642d
parenta655a74010577609339013065eecdb9024f0aa1b (diff)
Simplify shaders by moving fill-in light to a separate program
git-svn-id: svn://cook.msm.cam.ac.uk:745/thrust3d/thrust3d@218 84d2e878-0bd5-11dd-ad15-13eda11d74c5
-rw-r--r--data/Makefile.am3
-rw-r--r--data/shaders/fill-light.frag84
-rw-r--r--data/shaders/fill-light.vert40
-rw-r--r--data/shaders/lighting.frag71
-rw-r--r--src/render.c29
-rw-r--r--src/types.h3
6 files changed, 178 insertions, 52 deletions
diff --git a/data/Makefile.am b/data/Makefile.am
index f4ec188..b818d11 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -4,7 +4,8 @@ models_DATA = models/floor models/lander models/randombox models/walle models/wa
models/pipe-horiz
shadersdir = $(datadir)/thrust3d/shaders
-shaders_DATA = shaders/lighting.vert shaders/lighting.frag shaders/swirlytron.vert shaders/swirlytron.frag
+shaders_DATA = shaders/lighting.vert shaders/lighting.frag shaders/swirlytron.vert shaders/swirlytron.frag \
+ shaders/fill-light.vert shaders/fill-light.frag
texturesdir = $(datadir)/thrust3d/textures
textures_DATA = textures/floor1.png textures/tiledwall.png textures/radioactive.png textures/fuel.png \
diff --git a/data/shaders/fill-light.frag b/data/shaders/fill-light.frag
new file mode 100644
index 0000000..b9aba4c
--- /dev/null
+++ b/data/shaders/fill-light.frag
@@ -0,0 +1,84 @@
+/*
+ * lighting.frag
+ *
+ * Lighting calculations
+ *
+ * (c) 2007-2008 Thomas White <taw27@cam.ac.uk>
+ *
+ * thrust3d - a silly game
+ *
+ */
+
+varying vec3 pos;
+varying vec3 normal;
+
+varying vec3 light2vc;
+
+uniform sampler2D texture;
+uniform sampler2D normalmap;
+
+uniform bool has_normals;
+uniform bool texture_enabled;
+uniform bool texture_emits;
+uniform float alpha;
+
+varying vec3 col_ambi_diff;
+varying vec3 col_emit;
+
+void main() {
+
+ vec3 ambi;
+ vec3 emit;
+ vec3 diff = vec3(0.0, 0.0, 0.0);
+ vec3 spec = vec3(0.0, 0.0, 0.0);
+ vec3 norm = normal;
+ float diff_fac, spec_fac;
+ vec3 L, E, R;
+
+ if ( has_normals ) {
+ norm += (texture2D(normalmap, gl_TexCoord[0].st).rgb - vec3(0.5, 0.5, 0.5)) / 2.0;
+ }
+
+ norm = normalize(norm);
+
+ /* Ambient */
+ ambi = col_ambi_diff * gl_LightModel.ambient.rgb;
+
+ /* Emission */
+ emit = col_emit;
+
+ /* Light 2: Fill-in for lander craft */
+ L = normalize(gl_LightSource[2].position.xyz - pos);
+ E = normalize(-pos);
+ R = normalize(-reflect(L, norm));
+ diff_fac = max(0.0, dot(normalize(light2vc).xyz, norm));
+ spec_fac = max(0.0, dot(R, E));
+ spec_fac = pow(spec_fac, 80.0);
+
+ diff += col_ambi_diff * gl_LightSource[2].diffuse.rgb * diff_fac;
+ spec += gl_LightSource[2].specular.rgb * spec_fac;
+
+ if ( texture_enabled ) {
+
+ vec3 tex = texture2D(texture, gl_TexCoord[0].st).rgb;
+
+ if ( texture_emits ) {
+ gl_FragColor = vec4(tex.r, tex.g, tex.b, alpha);
+ } else {
+ gl_FragColor = vec4(min(tex.r * (ambi.r + diff.r) + spec.r, 1.0),
+ min(tex.g * (ambi.g + diff.g) + spec.g, 1.0),
+ min(tex.b * (ambi.b + diff.b) + spec.b, 1.0),
+ alpha);
+ }
+
+ } else {
+
+ 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),
+ alpha);
+
+ }
+
+}
+
diff --git a/data/shaders/fill-light.vert b/data/shaders/fill-light.vert
new file mode 100644
index 0000000..38dcfc9
--- /dev/null
+++ b/data/shaders/fill-light.vert
@@ -0,0 +1,40 @@
+/*
+ * fill-light.vert
+ *
+ * Lighting calculations for the lander craft
+ *
+ * (c) 2007-2008 Thomas White <taw27@cam.ac.uk>
+ *
+ * thrust3d - a silly game
+ *
+ */
+
+varying vec3 pos;
+varying vec3 normal;
+
+varying vec3 light2vc;
+
+varying vec3 col_ambi_diff;
+varying vec3 col_emit;
+
+void main() {
+
+ vec4 vert;
+
+ vert = gl_ModelViewMatrix * gl_Vertex;
+ pos = vert.xyz;
+ normal = gl_NormalMatrix * gl_Normal;
+
+ /* Light 2: Fill-in light for lander */
+ light2vc = normalize(vec3(gl_LightSource[2].position));
+
+ /* Material properties */
+ col_ambi_diff = gl_Color.rgb;
+ col_emit = gl_FrontMaterial.emission.rgb;
+
+ /* Coordinates */
+ gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
+ gl_Position = ftransform();
+
+}
+
diff --git a/data/shaders/lighting.frag b/data/shaders/lighting.frag
index 7ec0d3e..39f39fc 100644
--- a/data/shaders/lighting.frag
+++ b/data/shaders/lighting.frag
@@ -37,6 +37,9 @@ void main() {
vec3 diff = vec3(0.0, 0.0, 0.0);
vec3 spec = vec3(0.0, 0.0, 0.0);
vec3 norm = normal;
+ float falloff, spot;
+ float diff_fac, spec_fac;
+ vec3 L, E, R;
if ( has_normals ) {
norm += (texture2D(normalmap, gl_TexCoord[0].st).rgb - vec3(0.5, 0.5, 0.5)) / 2.0;
@@ -49,53 +52,29 @@ void main() {
/* Emission */
emit = col_emit;
-
- if ( fill_light_enabled ) {
-
- float diff_fac, spec_fac;
- vec3 L, E, R;
-
- /* Light 2: Fill-in for lander craft */
- L = normalize(gl_LightSource[2].position.xyz - pos);
- E = normalize(-pos);
- R = normalize(-reflect(L, norm));
- diff_fac = max(0.0, dot(normalize(light2vc).xyz, norm));
- spec_fac = max(0.0, dot(R, E));
- spec_fac = pow(spec_fac, 80.0);
-
- diff += col_ambi_diff * gl_LightSource[2].diffuse.rgb * diff_fac;
- spec += gl_LightSource[2].specular.rgb * spec_fac;
-
- } else {
- float falloff, spot;
- float diff_fac, spec_fac;
- vec3 L, E, R;
-
- /* Light 0: Lander craft's spotlight */
- falloff = 1.0 / ( gl_LightSource[0].constantAttenuation
- + gl_LightSource[0].linearAttenuation * length(light0vc)
- + gl_LightSource[0].quadraticAttenuation * pow(length(light0vc), 2.0) );
-
- spot = max(dot(normalize(-light0vc), gl_LightSource[0].spotDirection), 0.0);
- spot = pow(spot, gl_LightSource[0].spotExponent);
-
- diff_fac = max(0.0, dot(normalize(light0vc).xyz, norm));
-
- L = normalize(gl_LightSource[0].position.xyz - pos);
- E = normalize(-pos);
- R = normalize(-reflect(L, norm));
- spec_fac = max(0.0, dot(R, E));
- spec_fac = pow(spec_fac, 80.0);
-
- diff += col_ambi_diff * gl_LightSource[0].diffuse.rgb * spot * falloff * diff_fac;
-
- spec += vec3(1.0, 1.0, 1.0) * gl_LightSource[0].specular.rgb * spot * falloff * spec_fac;
-
- /* Light 1: Diffuse background glow */
- diff += col_ambi_diff * gl_LightSource[1].diffuse.rgb * max(0.0, dot(vec3(light1vc), norm));
-
- }
+ /* Light 0: Lander craft's spotlight */
+ falloff = 1.0 / ( gl_LightSource[0].constantAttenuation
+ + gl_LightSource[0].linearAttenuation * length(light0vc)
+ + gl_LightSource[0].quadraticAttenuation * pow(length(light0vc), 2.0) );
+
+ spot = max(dot(normalize(-light0vc), gl_LightSource[0].spotDirection), 0.0);
+ spot = pow(spot, gl_LightSource[0].spotExponent);
+
+ diff_fac = max(0.0, dot(normalize(light0vc).xyz, norm));
+
+ L = normalize(gl_LightSource[0].position.xyz - pos);
+ E = normalize(-pos);
+ R = normalize(-reflect(L, norm));
+ spec_fac = max(0.0, dot(R, E));
+ spec_fac = pow(spec_fac, 80.0);
+
+ diff += col_ambi_diff * gl_LightSource[0].diffuse.rgb * spot * falloff * diff_fac;
+
+ spec += vec3(1.0, 1.0, 1.0) * gl_LightSource[0].specular.rgb * spot * falloff * spec_fac;
+
+ /* Light 1: Diffuse background glow */
+ diff += col_ambi_diff * gl_LightSource[1].diffuse.rgb * max(0.0, dot(vec3(light1vc), norm));
if ( texture_enabled ) {
diff --git a/src/render.c b/src/render.c
index ce25c5e..26d1dcc 100644
--- a/src/render.c
+++ b/src/render.c
@@ -40,6 +40,15 @@ static void render_load_shaders(RenderContext *r) {
shaderutils_link_program(r->lighting_program);
shaderutils_validate_program(r->lighting_program);
+ /* Fill-in light */
+ r->fill_vert = shaderutils_load_shader(DATADIR"/shaders/fill-light.vert", GL_VERTEX_SHADER);
+ r->fill_frag = shaderutils_load_shader(DATADIR"/shaders/fill-light.frag", GL_FRAGMENT_SHADER);
+ r->fill_program = glCreateProgram();
+ glAttachShader(r->fill_program, r->fill_vert);
+ glAttachShader(r->fill_program, r->fill_frag);
+ shaderutils_link_program(r->fill_program);
+ shaderutils_validate_program(r->fill_program);
+
/* Swirlyness */
r->swirly_vert = shaderutils_load_shader(DATADIR"/shaders/swirlytron.vert", GL_VERTEX_SHADER);
r->swirly_frag = shaderutils_load_shader(DATADIR"/shaders/swirlytron.frag", GL_FRAGMENT_SHADER);
@@ -58,6 +67,18 @@ static void render_delete_shaders(RenderContext *r) {
glDeleteShader(r->lighting_vert);
glDeleteShader(r->lighting_frag);
glDeleteProgram(r->lighting_program);
+
+ glDetachShader(r->fill_program, r->fill_frag);
+ glDetachShader(r->fill_program, r->fill_vert);
+ glDeleteShader(r->fill_vert);
+ glDeleteShader(r->fill_frag);
+ glDeleteProgram(r->fill_program);
+
+ glDetachShader(r->swirly_program, r->swirly_frag);
+ glDetachShader(r->swirly_program, r->swirly_vert);
+ glDeleteShader(r->swirly_vert);
+ glDeleteShader(r->swirly_frag);
+ glDeleteProgram(r->swirly_program);
}
@@ -604,7 +625,6 @@ void render_draw(Game *game, Uint32 t) {
shaderutils_setuni(game->render->lighting_program, "texture_only", 0);
shaderutils_setuni(game->render->lighting_program, "texture_enabled", 1);
shaderutils_setuni(game->render->lighting_program, "has_normals", 0);
- shaderutils_setuni(game->render->lighting_program, "fill_light_enabled", 0);
}
render_setup_lighting(game);
amb[0] = 0.02; amb[1] = 0.02; amb[2] = 0.02;
@@ -619,17 +639,16 @@ void render_draw(Game *game, Uint32 t) {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if ( r->shaders ) shaderutils_setuni(game->render->lighting_program, "fill_light_enabled", 1);
+ if ( r->shaders ) glUseProgram(game->render->fill_program);
render_model_instance_draw(game->lander, t, r, NULL, 1.0);
- if ( r->shaders ) shaderutils_setuni(game->render->lighting_program, "fill_light_enabled", 0);
glPopClientAttrib();
- if ( r->shaders ) shaderutils_setuni(game->render->lighting_program, "texture_enabled", 0);
+ if ( r->shaders ) glUseProgram(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);
/* Back faces (done last to make blending work properly) */
- if ( r->shaders ) glUseProgram(0); /* Speed things up a bit by not using per-fragment lighting */
+ /* Shaders still disabled (speeds this up a lot) */
glFrontFace(GL_CW);
glPolygonOffset(1.0, 1.0);
glEnable(GL_POLYGON_OFFSET_FILL);
diff --git a/src/types.h b/src/types.h
index f601d95..550d931 100644
--- a/src/types.h
+++ b/src/types.h
@@ -139,6 +139,9 @@ typedef struct {
GLuint lighting_vert;
GLuint lighting_frag;
GLuint lighting_program;
+ GLuint fill_vert;
+ GLuint fill_frag;
+ GLuint fill_program;
/* Textures */
Texture textures[MAX_TEXTURES];