Oops! Fixed newly envmapped glass being scheduled as opaque.
[neverball] / share / solid_gl.c
index 9f135b3..2d83099 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <SDL.h>
 #include <SDL_rwops.h>
-#include <SDL_image.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -23,6 +22,7 @@
 
 #include "glext.h"
 #include "vec3.h"
+#include "image.h"
 #include "base_image.h"
 #include "solid_gl.h"
 #include "base_config.h"
@@ -103,7 +103,6 @@ static void sol_draw_mtrl(const struct s_file *fp, int i)
         glBlendFunc(GL_ONE, GL_ONE);
     else
         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
 }
 
 static void sol_draw_bill(const struct s_file *fp,
@@ -225,14 +224,20 @@ static void sol_draw_lump(const struct s_file *fp,
 }
 
 static void sol_draw_body(const struct s_file *fp,
-                          const struct s_body *bp, int fl)
+                          const struct s_body *bp, int fl, int decal)
 {
     int mi, li, gi;
 
+    if (decal)
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
     /* Iterate all materials of the correct opacity. */
 
     for (mi = 0; mi < fp->mc; mi++)
-        if (fp->mv[mi].fl & fl)
+        if ((fp->mv[mi].fl & fl) && (fp->mv[mi].fl & M_DECAL) == decal)
         {
             if (sol_enum_mtrl(fp, bp, mi))
             {
@@ -252,6 +257,9 @@ static void sol_draw_body(const struct s_file *fp,
                 glEnd();
             }
         }
+
+    if (decal)
+        glDisable(GL_POLYGON_OFFSET_FILL);
 }
 
 static void sol_draw_list(const struct s_file *fp,
@@ -278,12 +286,13 @@ void sol_draw(const struct s_file *fp)
 {
     int bi;
 
-    glPushAttrib(GL_TEXTURE_BIT      |
+    glPushAttrib(GL_ENABLE_BIT       |
+                 GL_TEXTURE_BIT      |
                  GL_LIGHTING_BIT     |
                  GL_COLOR_BUFFER_BIT |
                  GL_DEPTH_BUFFER_BIT);
     {
-        /* Render all obaque geometry into the color and depth buffers. */
+        /* Render all opaque geometry into the color and depth buffers. */
 
         for (bi = 0; bi < fp->bc; bi++)
             if (fp->bv[bi].ol)
@@ -353,10 +362,16 @@ static void sol_shad_lump(const struct s_file *fp,
 }
 
 static void sol_shad_body(const struct s_file *fp,
-                          const struct s_body *bp, int fl)
+                          const struct s_body *bp, int fl, int decal)
 {
     int mi, li, gi;
 
+    if (decal)
+    {
+        glEnable(GL_POLYGON_OFFSET_FILL);
+        glPolygonOffset(-1.0f, -2.0f);
+    }
+
     glBegin(GL_TRIANGLES);
     {
         for (mi = 0; mi < fp->mc; mi++)
@@ -369,6 +384,9 @@ static void sol_shad_body(const struct s_file *fp,
             }
     }
     glEnd();
+
+    if (decal)
+        glDisable(GL_POLYGON_OFFSET_FILL);
 }
 
 static void sol_shad_list(const struct s_file *fp,
@@ -435,25 +453,28 @@ static void sol_load_objects(struct s_file *fp, int s)
 {
     int i;
 
+    /* Here we sort geometry into display lists by material type. */
+
     for (i = 0; i < fp->bc; i++)
     {
         struct s_body *bp = fp->bv + i;
 
-        /* Draw all opaque geometry. */
+        /* Draw all opaque geometry, decals last. */
 
-        if (sol_enum_body(fp, bp, M_OPAQUE | M_ENVIRONMENT))
+        if (sol_enum_body(fp, bp, M_OPAQUE))
         {
             fp->bv[i].ol = glGenLists(1);
 
             glNewList(fp->bv[i].ol, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_OPAQUE | M_ENVIRONMENT);
+                sol_draw_body(fp, fp->bv+i, M_OPAQUE, 0);
+                sol_draw_body(fp, fp->bv+i, M_OPAQUE, M_DECAL);
             }
             glEndList();
         }
         else fp->bv[i].ol = 0;
 
-        /* Draw all translucent geometry. */
+        /* Draw all translucent geometry, decals first. */
 
         if (sol_enum_body(fp, bp, M_TRANSPARENT))
         {
@@ -461,7 +482,8 @@ static void sol_load_objects(struct s_file *fp, int s)
 
             glNewList(fp->bv[i].tl, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_TRANSPARENT);
+                sol_draw_body(fp, fp->bv+i, M_TRANSPARENT, M_DECAL);
+                sol_draw_body(fp, fp->bv+i, M_TRANSPARENT, 0);
             }
             glEndList();
         }
@@ -475,7 +497,7 @@ static void sol_load_objects(struct s_file *fp, int s)
 
             glNewList(fp->bv[i].rl, GL_COMPILE);
             {
-                sol_draw_body(fp, fp->bv + i, M_REFLECTIVE);
+                sol_draw_body(fp, fp->bv+i, M_REFLECTIVE, 0);
             }
             glEndList();
         }
@@ -489,7 +511,8 @@ static void sol_load_objects(struct s_file *fp, int s)
 
             glNewList(fp->bv[i].sl, GL_COMPILE);
             {
-                sol_shad_body(fp, fp->bv + i, M_SHADOWED);
+                sol_shad_body(fp, fp->bv+i, M_SHADOWED, 0);
+                sol_shad_body(fp, fp->bv+i, M_SHADOWED, M_DECAL);
             }
             glEndList();
         }
@@ -497,73 +520,40 @@ static void sol_load_objects(struct s_file *fp, int s)
     }
 }
 
-static SDL_Surface *sol_find_texture(const char *name)
+static GLuint sol_find_texture(const char *name)
 {
     char png[MAXSTR];
-    char tga[MAXSTR];
     char jpg[MAXSTR];
-    SDL_Surface *s;
+
+    GLuint o;
 
     /* Prefer a lossless copy of the texture over a lossy compression. */
 
     strncpy(png, name, PATHMAX); strcat(png, ".png");
-    strncpy(tga, name, PATHMAX); strcat(tga, ".tga");
     strncpy(jpg, name, PATHMAX); strcat(jpg, ".jpg");
 
     /* Check for a PNG. */
 
-    if ((s = IMG_Load(config_data(png))))
-        return s;
-
-    /* Check for a TGA, swapping channels if found. */
-
-    if ((s = IMG_Load(config_data(tga))))
-    {
-        image_swab(s);
-        return s;
-    }
+    if ((o = make_image_from_file(png)))
+        return o;
 
     /* Check for a JPG. */
 
-    if ((s = IMG_Load(config_data(jpg))))
-        return s;
+    if ((o = make_image_from_file(jpg)))
+        return o;
 
-    return NULL;
+    return 0;
 }
 
 static void sol_load_textures(struct s_file *fp, int k)
 {
-    SDL_Surface *s;
-    SDL_Surface *d;
-
     int i;
 
+    /* Load the image referenced by each material. */
+
     for (i = 0; i < fp->mc; i++)
-        if ((s = sol_find_texture(fp->mv[i].f)))
+        if ((fp->mv[i].o = sol_find_texture(fp->mv[i].f)))
         {
-            GLenum f = (s->format->BitsPerPixel == 32) ? GL_RGBA : GL_RGB;
-
-            glGenTextures(1, &fp->mv[i].o);
-            glBindTexture(GL_TEXTURE_2D, fp->mv[i].o);
-
-            if (k > 1)
-            {
-                /* Create a new buffer and copy the scaled image to it. */
-
-                if ((d = image_scale(s, k)))
-                {
-                    glTexImage2D(GL_TEXTURE_2D, 0, f, d->w, d->h, 0, f,
-                                 GL_UNSIGNED_BYTE, d->pixels);
-                    SDL_FreeSurface(d);
-                }
-            }
-            else
-                glTexImage2D(GL_TEXTURE_2D, 0, f, s->w, s->h, 0, f,
-                             GL_UNSIGNED_BYTE, s->pixels);
-
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
             /* Set the texture to clamp or repeat based on material type. */
 
             if (fp->mv[i].fl & M_CLAMPED)
@@ -576,8 +566,6 @@ static void sol_load_textures(struct s_file *fp, int k)
                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
             }
-
-            SDL_FreeSurface(s);
         }
 }
 
@@ -591,8 +579,7 @@ int sol_load_gl(struct s_file *fp, const char *filename, int k, int s)
         sol_load_objects (fp, s);
         return 1;
     }
-    else
-        return 0;
+    return 0;
 }
 
 /*---------------------------------------------------------------------------*/