R_LoadTexture functions take a palette pointer now
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 14 Oct 2002 19:05:23 +0000 (19:05 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Mon, 14 Oct 2002 19:05:23 +0000 (19:05 +0000)
there are many palettes available now (d_8to24table renamed to palette_complete)
R_LoadTexture is gone, use R_LoadTexture2D instead
bumpmaps are now generated for models and maps (sigh, so much reworking of their loaders)

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2526 d7cf8633-e32d-0410-b094-e92efae38249

31 files changed:
cl_main.c
cl_parse.c
cl_particles.c
cl_video.c
gl_backend.c
gl_draw.c
gl_models.c
gl_rsurf.c
gl_textures.c
glquake.h
image.c
image.h
menu.c
model_alias.c
model_brush.c
model_brush.h
model_shared.c
model_shared.h
model_sprite.c
palette.c
palette.h
quakedef.h
r_crosshairs.c
r_explosion.c
r_light.c
r_shadow.c
r_sky.c
r_textures.h
render.h
sbar.c
vid_shared.c

index c483a33..1e04c31 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -707,7 +707,7 @@ static void CL_RelinkNetworkEntities()
                {
                        // * 4 for the expansion from 0-255 to 0-1023 range,
                        // / 255 to scale down byte colors
-                       VectorMA(dlightcolor, ent->state_current.glowsize * (4.0f / 255.0f), (qbyte *)&d_8to24table[ent->state_current.glowcolor], dlightcolor);
+                       VectorMA(dlightcolor, ent->state_current.glowsize * (4.0f / 255.0f), (qbyte *)&palette_complete[ent->state_current.glowcolor], dlightcolor);
                }
                // LordHavoc: customizable trail
                if (ent->render.flags & RENDER_GLOWTRAIL)
index 608b3ef..bcb3a51 100644 (file)
@@ -1304,7 +1304,7 @@ void CL_ParseTempEntity (void)
                colorStart = MSG_ReadByte ();
                colorLength = MSG_ReadByte ();
                CL_ParticleExplosion2 (pos, colorStart, colorLength);
-               tempcolor = (qbyte *)&d_8to24table[(rand()%colorLength) + colorStart];
+               tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
                CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
                S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
                break;
index d092dc3..c858654 100644 (file)
@@ -1406,7 +1406,7 @@ static void R_InitParticleTexture (void)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 #else
-       particlefonttexture = R_LoadTexture (particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       particlefonttexture = R_LoadTexture2D(particletexturepool, "particlefont", 256, 256, particletexturedata, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 #endif
 }
 
index 857d5d8..ba88b34 100644 (file)
@@ -159,7 +159,7 @@ void CL_VideoStart(char *filename)
        cl_videosoundresampledata = NULL;
 
        cl_videotexturepool = R_AllocTexturePool();
-       cl_videotexture = R_LoadTexture(cl_videotexturepool, "videotexture", cl_videoimagewidth, cl_videoimageheight, NULL, TEXTYPE_RGBA, TEXF_FRAGMENT);
+       cl_videotexture = R_LoadTexture2D(cl_videotexturepool, "videotexture", cl_videoimagewidth, cl_videoimageheight, NULL, TEXTYPE_RGBA, TEXF_FRAGMENT, NULL);
 }
 
 void CL_VideoStop(void)
index 65b2c4a..c9d9ec8 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "quakedef.h"
+#include "image.h"
 
 cvar_t gl_mesh_maxverts = {0, "gl_mesh_maxverts", "1024"};
 cvar_t gl_mesh_floatcolors = {0, "gl_mesh_floatcolors", "1"};
index c3ade96..c18954b 100644 (file)
--- a/gl_draw.c
+++ b/gl_draw.c
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "quakedef.h"
+#include "image.h"
 
 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
 
@@ -76,7 +77,7 @@ static rtexture_t *draw_generatemousepointer(void)
                        buffer[i][3] = 255;
                }
        }
-       return R_LoadTexture(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 }
 
 // must match NUMCROSSHAIRS in r_crosshairs.c
@@ -193,7 +194,7 @@ static rtexture_t *draw_generatecrosshair(int num)
                        data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
                }
        }
-       return R_LoadTexture(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 }
 
 /*
@@ -223,11 +224,11 @@ cachepic_t        *Draw_CachePic (char *path)
        cachepichash[hashkey] = pic;
 
        // load the pic from disk
-       pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, false, true);
+       pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
        if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
        {
                // compatibility with older versions
-               pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, false, true);
+               pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, TEXF_ALPHA | TEXF_PRECACHE);
                // failed to find gfx/whatever.tga or similar, try the wad
                if (pic->tex == NULL && (p = W_GetLumpName (path + 4)))
                {
@@ -239,10 +240,10 @@ cachepic_t        *Draw_CachePic (char *path)
                                for (i = 0;i < 128 * 128;i++)
                                        if (pix[i] == 0)
                                                pix[i] = 255;
-                               pic->tex = R_LoadTexture (drawtexturepool, path, 128, 128, pix, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
+                               pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, pix, TEXTYPE_PALETTE, TEXF_ALPHA | TEXF_PRECACHE, palette_complete);
                        }
                        else
-                               pic->tex = R_LoadTexture (drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_QPALETTE, TEXF_ALPHA | TEXF_PRECACHE);
+                               pic->tex = R_LoadTexture2D(drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_PALETTE, TEXF_ALPHA | TEXF_PRECACHE, palette_complete);
                }
        }
        if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
@@ -305,7 +306,7 @@ cachepic_t *Draw_NewPic(char *picname, int width, int height, int alpha, qbyte *
        pic->height = height;
        if (pic->tex)
                R_FreeTexture(pic->tex);
-       pic->tex = R_LoadTexture (drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0);
+       pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
        return pic;
 }
 
index c5c4c71..4126c63 100644 (file)
@@ -299,11 +299,11 @@ void R_DrawQ1Q2AliasModelCallback (const void *calldata1, int calldata2)
        {
                // 128-224 are backwards ranges
                c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
-               bcolor = (qbyte *) (&d_8to24table[c]);
+               bcolor = (qbyte *) (&palette_complete[c]);
                pantsfullbright = c >= 224;
                VectorScale(bcolor, (1.0f / 255.0f), pantscolor);
                c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
-               bcolor = (qbyte *) (&d_8to24table[c]);
+               bcolor = (qbyte *) (&palette_complete[c]);
                shirtfullbright = c >= 224;
                VectorScale(bcolor, (1.0f / 255.0f), shirtcolor);
        }
@@ -589,7 +589,7 @@ void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
        R_Mesh_ResizeCheck(ent->model->numverts);
        R_LerpMDLMD2Vertices(ent, varray_vertex, aliasvert_normals);
        Mod_BuildTextureVectorsAndNormals(ent->model->numverts, ent->model->numtris, varray_vertex, ent->model->mdlmd2data_texcoords, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals);
-       R_Shadow_RenderLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, skinframe->base, r_notexture, NULL, NULL);
+       R_Shadow_RenderLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, skinframe->base, skinframe->gloss, skinframe->nmap, NULL);
 }
 
 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
index aa5c405..a587d65 100644 (file)
@@ -807,19 +807,21 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
        float f, colorscale;
        const surfmesh_t *mesh;
        rmeshstate_t m;
-       float alpha = ent->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
+       float alpha = ent->alpha * (surf->flags & SURF_WATERALPHA ? r_wateralpha.value : 1);
        float modelorg[3];
+       texture_t *texture;
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
 
        R_Mesh_Matrix(&ent->matrix);
 
        memset(&m, 0, sizeof(m));
-       if (ent->effects & EF_ADDITIVE)
+       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
+       if (texture->rendertype == SURFRENDER_ADD)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
        }
-       else if (surf->currenttexture->fogtexture != NULL || alpha < 1)
+       else if (texture->rendertype == SURFRENDER_ALPHA)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
@@ -829,7 +831,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ZERO;
        }
-       m.tex[0] = R_GetTexture(surf->currenttexture->texture);
+       m.tex[0] = R_GetTexture(texture->texture);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -861,7 +863,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2)
                memset(&m, 0, sizeof(m));
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
-               m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
+               m.tex[0] = R_GetTexture(texture->fogtexture);
                R_Mesh_State(&m);
                for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                {
@@ -879,7 +881,7 @@ static void RSurfShader_Water(const entity_render_t *ent, const texture_t *textu
 {
        const msurface_t *surf;
        vec3_t center;
-       if ((r_wateralpha.value < 1 && !(texture->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || texture->fogtexture)
+       if (texture->rendertype != SURFRENDER_OPAQUE)
        {
                for (surf = firstsurf;surf;surf = surf->texturechain)
                {
@@ -902,14 +904,16 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
+       texture_t *texture;
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
-       if (ent->effects & EF_ADDITIVE)
+       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
+       if (texture->rendertype == SURFRENDER_ADD)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
        }
-       else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
+       else if (texture->rendertype == SURFRENDER_ALPHA)
        {
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
@@ -919,7 +923,7 @@ static void RSurfShader_Wall_Pass_BaseVertex(const entity_render_t *ent, const m
                m.blendfunc1 = GL_ONE;
                m.blendfunc2 = GL_ZERO;
        }
-       m.tex[0] = R_GetTexture(surf->currenttexture->texture);
+       m.tex[0] = R_GetTexture(texture->texture);
        colorscale = r_colorscale;
        if (gl_combine.integer)
        {
@@ -952,11 +956,13 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
+       texture_t *texture;
+       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
+       m.tex[0] = R_GetTexture(texture->glowtexture);
        R_Mesh_State(&m);
        GL_UseColorArray();
        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
@@ -974,11 +980,13 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface
        const surfmesh_t *mesh;
        rmeshstate_t m;
        float modelorg[3];
+       texture_t *texture;
+       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_SRC_ALPHA;
        m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
+       m.tex[0] = R_GetTexture(texture->fogtexture);
        R_Mesh_State(&m);
        GL_UseColorArray();
        for (mesh = surf->mesh;mesh;mesh = mesh->chain)
@@ -1286,9 +1294,11 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata
 {
        const entity_render_t *ent = calldata1;
        const msurface_t *surf = ent->model->surfaces + calldata2;
+       texture_t *texture;
+       texture = surf->texinfo->texture->currentframe[ent->frame != 0];
        R_Mesh_Matrix(&ent->matrix);
        RSurfShader_Wall_Pass_BaseVertex(ent, surf);
-       if (surf->currenttexture->glowtexture)
+       if (texture->glowtexture)
                RSurfShader_Wall_Pass_Glow(ent, surf);
        if (fogenabled)
                RSurfShader_Wall_Pass_Fog(ent, surf);
@@ -1434,7 +1444,7 @@ void R_PrepareSurfaces(entity_render_t *ent)
                t = model->textures + i;
                if (ent->effects & EF_ADDITIVE)
                        t->rendertype = SURFRENDER_ADD;
-               else if (ent->alpha < 1 || t->flags & SURF_WATERALPHA || t->fogtexture != NULL)
+               else if (ent->alpha < 1 || (t->flags & SURF_WATERALPHA && r_wateralpha.value < 1) || t->fogtexture != NULL)
                        t->rendertype = SURFRENDER_ALPHA;
                else
                        t->rendertype = SURFRENDER_OPAQUE;
@@ -1964,7 +1974,7 @@ void R_Model_Brush_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, v
                                                {
                                                        R_Mesh_ResizeCheck(mesh->numverts);
                                                        memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4]));
-                                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->texture, r_notexture, NULL, NULL);
+                                                       R_Shadow_RenderLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->texture, t->glosstexture, t->nmaptexture, NULL);
                                                }
                                        }
                                }
index aa421f9..a502f81 100644 (file)
@@ -1,5 +1,6 @@
 
 #include "quakedef.h"
+#include "image.h"
 
 cvar_t r_max_size = {CVAR_SAVE, "r_max_size", "2048"};
 cvar_t r_max_scrapsize = {CVAR_SAVE, "r_max_scrapsize", "256"};
@@ -36,11 +37,11 @@ typedef struct
 }
 textypeinfo_t;
 
-static textypeinfo_t textype_qpalette       = {TEXTYPE_QPALETTE, 1, 4, GL_RGBA, 3};
-static textypeinfo_t textype_rgb            = {TEXTYPE_RGB     , 3, 3, GL_RGB , 3};
-static textypeinfo_t textype_rgba           = {TEXTYPE_RGBA    , 4, 4, GL_RGBA, 3};
-static textypeinfo_t textype_qpalette_alpha = {TEXTYPE_QPALETTE, 1, 4, GL_RGBA, 4};
-static textypeinfo_t textype_rgba_alpha     = {TEXTYPE_RGBA    , 4, 4, GL_RGBA, 4};
+static textypeinfo_t textype_palette       = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 3};
+static textypeinfo_t textype_rgb           = {TEXTYPE_RGB    , 3, 3, GL_RGB , 3};
+static textypeinfo_t textype_rgba          = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 3};
+static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE, 1, 4, GL_RGBA, 4};
+static textypeinfo_t textype_rgba_alpha    = {TEXTYPE_RGBA   , 4, 4, GL_RGBA, 4};
 
 // a tiling texture (most common type)
 #define GLIMAGETYPE_TILE 0
@@ -110,6 +111,8 @@ typedef struct gltexture_s
        textypeinfo_t *textype;
        // one of the GLTEXTURETYPE_ values
        int texturetype;
+       // palette if the texture is TEXTYPE_PALETTE
+       const unsigned int *palette;
 }
 gltexture_t;
 
@@ -139,8 +142,8 @@ static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags)
        {
                switch(textype)
                {
-               case TEXTYPE_QPALETTE:
-                       return &textype_qpalette_alpha;
+               case TEXTYPE_PALETTE:
+                       return &textype_palette_alpha;
                case TEXTYPE_RGB:
                        Host_Error("R_GetTexTypeInfo: RGB format has no alpha, TEXF_ALPHA not allowed\n");
                        return NULL;
@@ -155,8 +158,8 @@ static textypeinfo_t *R_GetTexTypeInfo(int textype, int flags)
        {
                switch(textype)
                {
-               case TEXTYPE_QPALETTE:
-                       return &textype_qpalette;
+               case TEXTYPE_PALETTE:
+                       return &textype_palette;
                case TEXTYPE_RGB:
                        return &textype_rgb;
                case TEXTYPE_RGBA:
@@ -614,12 +617,12 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
                        memset(resizebuffer, 255, glt->width * glt->height * glt->image->depth * glt->image->bytesperpixel);
                        prevbuffer = resizebuffer;
                }
-               else if (glt->textype->textype == TEXTYPE_QPALETTE)
+               else if (glt->textype->textype == TEXTYPE_PALETTE)
                {
                        // promote paletted to RGBA, so we only have to worry about RGB and
                        // RGBA in the rest of this code
                        R_MakeResizeBufferBigger(glt->image->width * glt->image->height * glt->image->depth * glt->image->bytesperpixel);
-                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, d_8to24table);
+                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, glt->palette);
                        prevbuffer = colorconvertbuffer;
                }
 
@@ -664,11 +667,11 @@ static void R_Upload(gltexture_t *glt, qbyte *data)
        }
        else
        {
-               if (glt->textype->textype == TEXTYPE_QPALETTE)
+               if (glt->textype->textype == TEXTYPE_PALETTE)
                {
                        // promote paletted to RGBA, so we only have to worry about RGB and
                        // RGBA in the rest of this code
-                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, d_8to24table);
+                       Image_Copy8bitRGBA(prevbuffer, colorconvertbuffer, glt->width * glt->height * glt->depth, glt->palette);
                        prevbuffer = colorconvertbuffer;
                }
 
@@ -906,7 +909,7 @@ static void R_UploadTexture (gltexture_t *glt)
                Con_Printf("R_UploadTexture: Texture %s already uploaded and destroyed.  Can not upload original image again.  Uploaded blank texture.\n", glt->identifier);
 }
 
-static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, char *identifier, int width, int height, int depth, int sides, int flags, int textype, int texturetype, qbyte *data)
+static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, int sides, int flags, int textype, int texturetype, const qbyte *data, const unsigned int *palette)
 {
        int i, size;
        gltexture_t *glt;
@@ -938,7 +941,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, char *identifier
        // clear the alpha flag if the texture has no transparent pixels
        switch(textype)
        {
-       case TEXTYPE_QPALETTE:
+       case TEXTYPE_PALETTE:
                if (flags & TEXF_ALPHA)
                {
                        flags &= ~TEXF_ALPHA;
@@ -946,7 +949,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, char *identifier
                        {
                                for (i = 0;i < size;i++)
                                {
-                                       if (data[i] == 255)
+                                       if (((qbyte *)&palette[data[i]])[3] == 255)
                                        {
                                                flags |= TEXF_ALPHA;
                                                break;
@@ -998,6 +1001,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, char *identifier
        glt->textype = texinfo;
        glt->texturetype = texturetype;
        glt->inputdatasize = size;
+       glt->palette = palette;
 
        if (data)
        {
@@ -1015,29 +1019,24 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, char *identifier
        return (rtexture_t *)glt;
 }
 
-rtexture_t *R_LoadTexture(rtexturepool_t *rtexturepool, char *identifier, int width, int height, qbyte *data, int textype, int flags)
+rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, const char *identifier, int width, const qbyte *data, int textype, int flags, const unsigned int *palette)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, textype, GLTEXTURETYPE_2D, data);
+       return R_SetupTexture(rtexturepool, identifier, width, 1, 1, 1, flags, textype, GLTEXTURETYPE_1D, data, palette);
 }
 
-rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, char *identifier, int width, qbyte *data, int textype, int flags)
+rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const qbyte *data, int textype, int flags, const unsigned int *palette)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, 1, 1, 1, flags, textype, GLTEXTURETYPE_1D, data);
+       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, textype, GLTEXTURETYPE_2D, data, palette);
 }
 
-rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, char *identifier, int width, int height, qbyte *data, int textype, int flags)
+rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const qbyte *data, int textype, int flags, const unsigned int *palette)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, textype, GLTEXTURETYPE_2D, data);
+       return R_SetupTexture(rtexturepool, identifier, width, height, depth, 1, flags, textype, GLTEXTURETYPE_3D, data, palette);
 }
 
-rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, char *identifier, int width, int height, int depth, qbyte *data, int textype, int flags)
+rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const qbyte *data, int textype, int flags, const unsigned int *palette)
 {
-       return R_SetupTexture(rtexturepool, identifier, width, height, depth, 1, flags, textype, GLTEXTURETYPE_3D, data);
-}
-
-rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, char *identifier, int width, qbyte *data, int textype, int flags)
-{
-       return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, textype, GLTEXTURETYPE_CUBEMAP, data);
+       return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
 }
 
 int R_TextureHasAlpha(rtexture_t *rt)
index 182e43e..f68e815 100644 (file)
--- a/glquake.h
+++ b/glquake.h
@@ -114,6 +114,7 @@ typedef double GLclampd;
 #define GL_TEXTURE_WRAP_S                      0x2802
 #define GL_TEXTURE_WRAP_T                      0x2803
 #define GL_TEXTURE_WRAP_R                      0x8072
+#define GL_TEXTURE_BORDER_COLOR                        0x1004
 #define GL_TEXTURE_MAG_FILTER                  0x2800
 #define GL_TEXTURE_MIN_FILTER                  0x2801
 #define GL_UNPACK_ALIGNMENT                    0x0CF5
@@ -410,9 +411,10 @@ extern void (GLAPIENTRY *qglStencilMask)(GLuint mask);
 extern void (GLAPIENTRY *qglStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
 extern void (GLAPIENTRY *qglClearStencil)(GLint s);
 
-//extern void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
+extern void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
 extern void (GLAPIENTRY *qglTexEnvi)(GLenum target, GLenum pname, GLint param);
-//extern void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+extern void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+extern void (GLAPIENTRY *qglTexParameterfv)(GLenum target, GLenum pname, GLfloat *params);
 extern void (GLAPIENTRY *qglTexParameteri)(GLenum target, GLenum pname, GLint param);
 
 extern void (GLAPIENTRY *qglGenTextures)(GLsizei n, GLuint *textures);
diff --git a/image.c b/image.c
index d78d1f5..dce3b36 100644 (file)
--- a/image.c
+++ b/image.c
@@ -1,10 +1,11 @@
 
 #include "quakedef.h"
+#include "image.h"
 
 int            image_width;
 int            image_height;
 
-void Image_GammaRemapRGB(qbyte *in, qbyte *out, int pixels, qbyte *gammar, qbyte *gammag, qbyte *gammab)
+void Image_GammaRemapRGB(const qbyte *in, qbyte *out, int pixels, const qbyte *gammar, const qbyte *gammag, const qbyte *gammab)
 {
        while (pixels--)
        {
@@ -17,7 +18,7 @@ void Image_GammaRemapRGB(qbyte *in, qbyte *out, int pixels, qbyte *gammar, qbyte
 }
 
 // note: pal must be 32bit color
-void Image_Copy8bitRGBA(qbyte *in, qbyte *out, int pixels, int *pal)
+void Image_Copy8bitRGBA(const qbyte *in, qbyte *out, int pixels, const unsigned int *pal)
 {
        int *iout = (void *)out;
        while (pixels >= 8)
@@ -83,10 +84,11 @@ typedef struct
 LoadPCX
 ============
 */
-qbyte* LoadPCX (qbyte *f, int matchwidth, int matchheight)
+qbyte* LoadPCX (const qbyte *f, int matchwidth, int matchheight)
 {
        pcx_t pcx;
-       qbyte *palette, *a, *b, *image_rgba, *fin, *pbuf, *enddata;
+       qbyte *a, *b, *image_rgba, *pbuf;
+       const qbyte *palette, *fin, *enddata;
        int x, y, x2, dataByte;
 
        if (loadsize < sizeof(pcx) + 768)
@@ -205,11 +207,12 @@ TargaHeader               targa_header;
 LoadTGA
 =============
 */
-qbyte *LoadTGA (qbyte *f, int matchwidth, int matchheight)
+qbyte *LoadTGA (const qbyte *f, int matchwidth, int matchheight)
 {
        int x, y, row_inc;
        unsigned char red, green, blue, alpha, run, runlen;
-       qbyte *pixbuf, *image_rgba, *fin, *enddata;
+       qbyte *pixbuf, *image_rgba;
+       const qbyte *fin, *enddata;
 
        if (loadsize < 18+3)
                return NULL;
@@ -421,7 +424,7 @@ qbyte *LoadTGA (qbyte *f, int matchwidth, int matchheight)
 LoadLMP
 ============
 */
-qbyte *LoadLMP (qbyte *f, int matchwidth, int matchheight)
+qbyte *LoadLMP (const qbyte *f, int matchwidth, int matchheight)
 {
        qbyte *image_rgba;
        int width, height;
@@ -458,7 +461,7 @@ qbyte *LoadLMP (qbyte *f, int matchwidth, int matchheight)
                Con_Printf("LoadLMP: not enough memory for %i by %i image\n", image_width, image_height);
                return NULL;
        }
-       Image_Copy8bitRGBA(f + 8, image_rgba, image_width * image_height, d_8to24table);
+       Image_Copy8bitRGBA(f + 8, image_rgba, image_width * image_height, palette_complete);
        return image_rgba;
 }
 
@@ -467,7 +470,7 @@ qbyte *LoadLMP (qbyte *f, int matchwidth, int matchheight)
 LoadLMP
 ============
 */
-qbyte *LoadLMPAs8Bit (qbyte *f, int matchwidth, int matchheight)
+qbyte *LoadLMPAs8Bit (const qbyte *f, int matchwidth, int matchheight)
 {
        qbyte *image_8bit;
        int width, height;
@@ -508,9 +511,9 @@ qbyte *LoadLMPAs8Bit (qbyte *f, int matchwidth, int matchheight)
        return image_8bit;
 }
 
-void Image_StripImageExtension (char *in, char *out)
+void Image_StripImageExtension (const char *in, char *out)
 {
-       char *end, *temp;
+       const char *end, *temp;
        end = in + strlen(in);
        if ((end - in) >= 4)
        {
@@ -525,7 +528,7 @@ void Image_StripImageExtension (char *in, char *out)
                strcpy(out, in);
 }
 
-qbyte *loadimagepixels (char *filename, qboolean complain, int matchwidth, int matchheight)
+qbyte *loadimagepixels (const char *filename, qboolean complain, int matchwidth, int matchheight)
 {
        qbyte *f, *data;
        char basename[256], name[256], *c;
@@ -579,9 +582,9 @@ qbyte *loadimagepixels (char *filename, qboolean complain, int matchwidth, int m
        return NULL;
 }
 
-int image_makemask (qbyte *in, qbyte *out, int size)
+int image_makemask (const qbyte *in, qbyte *out, int size)
 {
-       int             i, count;
+       int i, count;
        count = 0;
        for (i = 0;i < size;i++)
        {
@@ -595,7 +598,7 @@ int image_makemask (qbyte *in, qbyte *out, int size)
        return count;
 }
 
-qbyte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight)
+qbyte* loadimagepixelsmask (const char *filename, qboolean complain, int matchwidth, int matchheight)
 {
        qbyte *in, *data;
        in = data = loadimagepixels(filename, complain, matchwidth, matchheight);
@@ -610,55 +613,78 @@ qbyte* loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, i
        }
 }
 
-rtexture_t *loadtextureimage (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
+rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
 {
        qbyte *data;
        rtexture_t *rt;
        if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
                return 0;
-       rt = R_LoadTexture (pool, filename, image_width, image_height, data, TEXTYPE_RGBA, TEXF_ALPHA | (mipmap ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
+       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
        Mem_Free(data);
        return rt;
 }
 
-rtexture_t *loadtextureimagemask (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
+rtexture_t *loadtextureimagemask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
 {
        qbyte *data;
        rtexture_t *rt;
        if (!(data = loadimagepixelsmask (filename, complain, matchwidth, matchheight)))
                return 0;
-       rt = R_LoadTexture (pool, filename, image_width, image_height, data, TEXTYPE_RGBA, TEXF_ALPHA | (mipmap ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
+       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
        Mem_Free(data);
        return rt;
 }
 
 rtexture_t *image_masktex;
-rtexture_t *loadtextureimagewithmask (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache)
+rtexture_t *image_nmaptex;
+rtexture_t *loadtextureimagewithmask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags)
 {
-       int count;
        qbyte *data;
-       char *filename2;
        rtexture_t *rt;
        image_masktex = NULL;
+       image_nmaptex = NULL;
        if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
                return 0;
-       rt = R_LoadTexture (pool, filename, image_width, image_height, data, TEXTYPE_RGBA, TEXF_ALPHA | (mipmap ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
-       count = image_makemask(data, data, image_width * image_height);
-       if (count)
-       {
-               filename2 = Mem_Alloc(tempmempool, strlen(filename) + 6);
-               sprintf(filename2, "%s_mask", filename);
-               image_masktex = R_LoadTexture (pool, filename2, image_width, image_height, data, TEXTYPE_RGBA, TEXF_ALPHA | (mipmap ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
-               Mem_Free(filename2);
-       }
+
+       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
+
+       if (flags & TEXF_ALPHA && image_makemask(data, data, image_width * image_height))
+               image_masktex = R_LoadTexture2D(pool, va("%s_mask", filename), image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
+
        Mem_Free(data);
        return rt;
 }
 
-qboolean Image_WriteTGARGB_preflipped (char *filename, int width, int height, qbyte *data)
+rtexture_t *loadtextureimagewithmaskandnmap (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags, float bumpscale)
+{
+       qbyte *data, *data2;
+       rtexture_t *rt;
+       image_masktex = NULL;
+       image_nmaptex = NULL;
+       if (!(data = loadimagepixels (filename, complain, matchwidth, matchheight)))
+               return 0;
+
+       data2 = Mem_Alloc(tempmempool, image_width * image_height * 4);
+
+       rt = R_LoadTexture2D(pool, filename, image_width, image_height, data, TEXTYPE_RGBA, flags, NULL);
+
+       Image_HeightmapToNormalmap(data, data2, image_width, image_height, (flags & TEXF_CLAMP) != 0, bumpscale);
+       image_nmaptex = R_LoadTexture2D(pool, va("%s_nmap", filename), image_width, image_height, data2, TEXTYPE_RGBA, flags, NULL);
+
+       if (flags & TEXF_ALPHA && image_makemask(data, data2, image_width * image_height))
+               image_masktex = R_LoadTexture2D(pool, va("%s_mask", filename), image_width, image_height, data2, TEXTYPE_RGBA, flags, NULL);
+
+       Mem_Free(data2);
+
+       Mem_Free(data);
+       return rt;
+}
+
+qboolean Image_WriteTGARGB_preflipped (const char *filename, int width, int height, const qbyte *data)
 {
        qboolean ret;
-       qbyte *buffer, *in, *out, *end;
+       qbyte *buffer, *out;
+       const qbyte *in, *end;
 
        buffer = Mem_Alloc(tempmempool, width*height*3 + 18);
 
@@ -686,10 +712,11 @@ qboolean Image_WriteTGARGB_preflipped (char *filename, int width, int height, qb
        return ret;
 }
 
-void Image_WriteTGARGB (char *filename, int width, int height, qbyte *data)
+void Image_WriteTGARGB (const char *filename, int width, int height, const qbyte *data)
 {
        int y;
-       qbyte *buffer, *in, *out, *end;
+       qbyte *buffer, *out;
+       const qbyte *in, *end;
 
        buffer = Mem_Alloc(tempmempool, width*height*3 + 18);
 
@@ -719,10 +746,11 @@ void Image_WriteTGARGB (char *filename, int width, int height, qbyte *data)
        Mem_Free(buffer);
 }
 
-void Image_WriteTGARGBA (char *filename, int width, int height, qbyte *data)
+void Image_WriteTGARGBA (const char *filename, int width, int height, const qbyte *data)
 {
        int y;
-       qbyte *buffer, *in, *out, *end;
+       qbyte *buffer, *out;
+       const qbyte *in, *end;
 
        buffer = Mem_Alloc(tempmempool, width*height*4 + 18);
 
@@ -753,9 +781,9 @@ void Image_WriteTGARGBA (char *filename, int width, int height, qbyte *data)
        Mem_Free(buffer);
 }
 
-qboolean Image_CheckAlpha(qbyte *data, int size, qboolean rgba)
+qboolean Image_CheckAlpha(const qbyte *data, int size, qboolean rgba)
 {
-       qbyte *end;
+       const qbyte *end;
        if (rgba)
        {
                // check alpha bytes
@@ -773,7 +801,7 @@ qboolean Image_CheckAlpha(qbyte *data, int size, qboolean rgba)
        return 0;
 }
 
-static void Image_Resample32LerpLine (qbyte *in, qbyte *out, int inwidth, int outwidth)
+static void Image_Resample32LerpLine (const qbyte *in, qbyte *out, int inwidth, int outwidth)
 {
        int             j, xi, oldx = 0, f, fstep, endx, lerp;
        fstep = (int) (inwidth*65536.0f/outwidth);
@@ -804,7 +832,7 @@ static void Image_Resample32LerpLine (qbyte *in, qbyte *out, int inwidth, int ou
        }
 }
 
-static void Image_Resample24LerpLine (qbyte *in, qbyte *out, int inwidth, int outwidth)
+static void Image_Resample24LerpLine (const qbyte *in, qbyte *out, int inwidth, int outwidth)
 {
        int             j, xi, oldx = 0, f, fstep, endx, lerp;
        fstep = (int) (inwidth*65536.0f/outwidth);
@@ -839,10 +867,11 @@ qbyte *resamplerow2 = NULL;
 mempool_t *resamplemempool = NULL;
 
 #define LERPBYTE(i) r = resamplerow1[i];out[i] = (qbyte) ((((resamplerow2[i] - r) * lerp) >> 16) + r)
-void Image_Resample32Lerp(void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
 {
        int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4;
-       qbyte *inrow, *out;
+       qbyte *out;
+       const qbyte *inrow;
        out = outdata;
        fstep = (int) (inheight*65536.0f/outheight);
 
@@ -933,7 +962,7 @@ void Image_Resample32Lerp(void *indata, int inwidth, int inheight, void *outdata
        }
 }
 
-void Image_Resample32Nearest(void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+void Image_Resample32Nearest(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
 {
        int i, j;
        unsigned frac, fracstep;
@@ -970,10 +999,11 @@ void Image_Resample32Nearest(void *indata, int inwidth, int inheight, void *outd
        }
 }
 
-void Image_Resample24Lerp(void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+void Image_Resample24Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
 {
        int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth3 = inwidth * 3, outwidth3 = outwidth * 3;
-       qbyte *inrow, *out;
+       qbyte *out;
+       const qbyte *inrow;
        out = outdata;
        fstep = (int) (inheight*65536.0f/outheight);
 
@@ -1057,7 +1087,7 @@ void Image_Resample24Lerp(void *indata, int inwidth, int inheight, void *outdata
        }
 }
 
-void Image_Resample24Nolerp(void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
+void Image_Resample24Nolerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
 {
        int i, j, f, inwidth3 = inwidth * 3;
        unsigned frac, fracstep;
@@ -1097,7 +1127,7 @@ void Image_Resample24Nolerp(void *indata, int inwidth, int inheight, void *outda
 Image_Resample
 ================
 */
-void Image_Resample (void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int bytesperpixel, int quality)
+void Image_Resample (const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int bytesperpixel, int quality)
 {
        if (indepth != 1 || outdepth != 1)
                Sys_Error("Image_Resample: 3D resampling not supported\n");
@@ -1130,7 +1160,7 @@ void Image_Resample (void *indata, int inwidth, int inheight, int indepth, void
 }
 
 // in can be the same as out
-void Image_MipReduce(qbyte *in, qbyte *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth, int bytesperpixel)
+void Image_MipReduce(const qbyte *in, qbyte *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth, int bytesperpixel)
 {
        int x, y, nextrow;
        if (*depth != 1 || destdepth != 1)
@@ -1258,3 +1288,59 @@ void Image_MipReduce(qbyte *in, qbyte *out, int *width, int *height, int *depth,
        }
 }
 
+void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale)
+{
+       int x, y;
+       const unsigned char *p0, *p1, *p2;
+       unsigned char *out;
+       float iwidth, iheight, ibumpscale, n[3];
+       iwidth = 1.0f / width;
+       iheight = 1.0f / height;
+       ibumpscale = (255.0f * 3.0f) / (bumpscale * 16.0f);
+       out = outpixels;
+       for (y = 0;y < height;y++)
+       {
+               for (x = 0;x < width;x++)
+               {
+                       p0 = inpixels + (y * width + x) * 4;
+                       if (x == width - 1)
+                       {
+                               if (clamp)
+                                       p1 = inpixels + (y * width + x) * 4;
+                               else
+                                       p1 = inpixels + (y * width) * 4;
+                       }
+                       else
+                               p1 = inpixels + (y * width + x + 1) * 4;
+                       if (y == height - 1)
+                       {
+                               if (clamp)
+                                       p2 = inpixels + (y * width + x) * 4;
+                               else
+                                       p2 = inpixels + x * 4;
+                       }
+                       else
+                               p2 = inpixels + ((y + 1) * width + x) * 4;
+                       /*
+                       dv[0][0] = iwidth;
+                       dv[0][1] = 0;
+                       dv[0][2] = ((p1[0] + p1[1] + p1[2]) * ibumpscale) - ((p0[0] + p0[1] + p0[2]) * ibumpscale);
+                       dv[1][0] = 0;
+                       dv[1][1] = iheight;
+                       dv[1][2] = ((p2[0] + p2[1] + p2[2]) * ibumpscale) - ((p0[0] + p0[1] + p0[2]) * ibumpscale);
+                       n[0] = dv[0][1]*dv[1][2]-dv[0][2]*dv[1][1];
+                       n[1] = dv[0][2]*dv[1][0]-dv[0][0]*dv[1][2];
+                       n[2] = dv[0][0]*dv[1][1]-dv[0][1]*dv[1][0];
+                       */
+                       n[0] = ((p0[0] + p0[1] + p0[2]) - (p1[0] + p1[1] + p1[2]));
+                       n[1] = ((p0[0] + p0[1] + p0[2]) - (p2[0] + p2[1] + p2[2]));
+                       n[2] = ibumpscale;
+                       VectorNormalize(n);
+                       out[0] = 128.0f + n[0] * 127.0f;
+                       out[1] = 128.0f + n[1] * 127.0f;
+                       out[2] = 128.0f + n[2] * 127.0f;
+                       out[3] = 255;
+                       out += 4;
+               }
+       }
+}
diff --git a/image.h b/image.h
index c73d48a..5ff6738 100644 (file)
--- a/image.h
+++ b/image.h
@@ -3,50 +3,54 @@
 #define IMAGE_H
 
 // applies gamma correction to RGB pixels, in can be the same as out
-void Image_GammaRemapRGB(qbyte *in, qbyte *out, int pixels, qbyte *gammar, qbyte *gammag, qbyte *gammab);
+void Image_GammaRemapRGB(const qbyte *in, qbyte *out, int pixels, const qbyte *gammar, const qbyte *gammag, const qbyte *gammab);
 
 // converts 8bit image data to RGBA, in can not be the same as out
-void Image_Copy8bitRGBA(qbyte *in, qbyte *out, int pixels, int *pal);
+void Image_Copy8bitRGBA(const qbyte *in, qbyte *out, int pixels, const unsigned int *pal);
 
 // makes a RGBA mask from RGBA input, in can be the same as out
-int image_makemask (qbyte *in, qbyte *out, int size);
+int image_makemask (const qbyte *in, qbyte *out, int size);
 
 // loads a texture, as pixel data
-qbyte *loadimagepixels (char* filename, qboolean complain, int matchwidth, int matchheight);
+qbyte *loadimagepixels (const char *filename, qboolean complain, int matchwidth, int matchheight);
 
 // loads a texture, as a texture
-rtexture_t *loadtextureimage (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+rtexture_t *loadtextureimage (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags);
 
 // loads a texture's alpha mask, as pixel data
-qbyte *loadimagepixelsmask (char* filename, qboolean complain, int matchwidth, int matchheight);
+qbyte *loadimagepixelsmask (const char *filename, qboolean complain, int matchwidth, int matchheight);
 
 // loads a texture's alpha mask, as a texture
-rtexture_t *loadtextureimagemask (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+rtexture_t *loadtextureimagemask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags);
 
 // loads a texture and it's alpha mask at once (NULL if it has no translucent pixels)
 rtexture_t *image_masktex;
-rtexture_t *loadtextureimagewithmask (rtexturepool_t *pool, char* filename, int matchwidth, int matchheight, qboolean complain, qboolean mipmap, qboolean precache);
+rtexture_t *image_nmaptex;
+rtexture_t *loadtextureimagewithmask (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags);
+rtexture_t *loadtextureimagewithmaskandnmap (rtexturepool_t *pool, const char *filename, int matchwidth, int matchheight, qboolean complain, int flags, float bumpscale);
 
 // writes a RGB TGA that is already upside down (which TGA wants)
-qboolean Image_WriteTGARGB_preflipped (char *filename, int width, int height, qbyte *data);
+qboolean Image_WriteTGARGB_preflipped (const char *filename, int width, int height, const qbyte *data);
 
 // writes a RGB TGA
-void Image_WriteTGARGB (char *filename, int width, int height, qbyte *data);
+void Image_WriteTGARGB (const char *filename, int width, int height, const qbyte *data);
 
 // writes a RGBA TGA
-void Image_WriteTGARGBA (char *filename, int width, int height, qbyte *data);
+void Image_WriteTGARGBA (const char *filename, int width, int height, const qbyte *data);
 
 // returns true if the image has some translucent pixels
-qboolean Image_CheckAlpha(qbyte *data, int size, qboolean rgba);
+qboolean Image_CheckAlpha(const qbyte *data, int size, qboolean rgba);
 
 // resizes the image (in can not be the same as out)
-void Image_Resample (void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int bytesperpixel, int quality);
+void Image_Resample (const void *indata, int inwidth, int inheight, int indepth, void *outdata, int outwidth, int outheight, int outdepth, int bytesperpixel, int quality);
 
 // scales the image down by a power of 2 (in can be the same as out)
-void Image_MipReduce(qbyte *in, qbyte *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth, int bytesperpixel);
+void Image_MipReduce(const qbyte *in, qbyte *out, int *width, int *height, int *depth, int destwidth, int destheight, int destdepth, int bytesperpixel);
 
 // only used by menuplyr coloring
-qbyte *LoadLMPAs8Bit (qbyte *f, int matchwidth, int matchheight);
+qbyte *LoadLMPAs8Bit (const qbyte *f, int matchwidth, int matchheight);
+
+void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale);
 
 #endif
 
diff --git a/menu.c b/menu.c
index fe2e8d9..879761a 100644 (file)
--- a/menu.c
+++ b/menu.c
@@ -18,6 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 */
 #include "quakedef.h"
+#include "image.h"
 
 void (*vid_menudrawfn)(void);
 void (*vid_menukeyfn)(int key);
@@ -971,7 +972,7 @@ void M_MenuPlayerTranslate (qbyte *translation, int top, int bottom)
        M_BuildTranslationTable (menuplyr_top*16, menuplyr_bottom*16);
 
        for (i = 0;i < menuplyr_width * menuplyr_height;i++)
-               trans[i] = d_8to24table[translation[pixels[i]]];
+               trans[i] = palette_complete[translation[pixels[i]]];
 
        Draw_NewPic("gfx/menuplyr.lmp", menuplyr_width, menuplyr_height, true, (qbyte *)trans);
 }
index 9b62402..112df18 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "quakedef.h"
+#include "image.h"
 
 static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
 
@@ -155,92 +156,52 @@ static void Mod_MDL_LoadFrames (qbyte * datapointer, int inverts, int outverts,
        }
 }
 
-static rtexture_t *GL_SkinSplitShirt(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache)
+static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int precache)
 {
-       int i, pixels, passed;
-       qbyte pixeltest[16];
-       for (i = 0;i < 16;i++)
-               pixeltest[i] = (bits & (1 << i)) != 0;
-       pixels = width*height;
-       passed = 0;
-       while(pixels--)
-       {
-               if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
-               {
-                       passed++;
-                       // turn to white while copying
-                       if (*in >= 128 && *in < 224) // backwards ranges
-                               *out = (*in & 15) ^ 15;
-                       else
-                               *out = *in & 15;
-               }
-               else
-                       *out = 0;
-               in++;
-               out++;
-       }
-       if (passed)
-               return R_LoadTexture (loadmodel->texturepool, name, width, height, out - width*height, TEXTYPE_QPALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
-       else
-               return NULL;
-}
-
-static rtexture_t *GL_SkinSplit(qbyte *in, qbyte *out, int width, int height, int bits, char *name, int precache)
-{
-       int i, pixels, passed;
-       qbyte pixeltest[16];
-       for (i = 0;i < 16;i++)
-               pixeltest[i] = (bits & (1 << i)) != 0;
-       pixels = width*height;
-       passed = 0;
-       while(pixels--)
-       {
-               if (pixeltest[*in >> 4] && *in != 0 && *in != 255)
-               {
-                       passed++;
-                       *out = *in;
-               }
-               else
-                       *out = 0;
-               in++;
-               out++;
-       }
-       if (passed)
-               return R_LoadTexture (loadmodel->texturepool, name, width, height, out - width*height, TEXTYPE_QPALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0));
-       else
-               return NULL;
+       int i;
+       for (i = 0;i < width*height;i++)
+               if (((qbyte *)&palette[in[i]])[3] > 0)
+                       return R_LoadTexture2D (loadmodel->texturepool, name, width, height, in, TEXTYPE_PALETTE, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), palette);
+       return NULL;
 }
 
 static int Mod_LoadExternalSkin (char *basename, skinframe_t *skinframe, int precache)
 {
-       skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, r_mipskins.integer, precache);
-       skinframe->fog    = image_masktex;
+       skinframe->base   = loadtextureimagewithmaskandnmap(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
        if (!skinframe->base)
-       {
-               skinframe->base   = loadtextureimagewithmask(loadmodel->texturepool, basename, 0, 0, false, r_mipskins.integer, precache);
-               skinframe->fog    = image_masktex;
-       }
-       skinframe->pants  = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, r_mipskins.integer, precache);
-       skinframe->shirt  = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, r_mipskins.integer, precache);
-       skinframe->glow   = loadtextureimage(loadmodel->texturepool, va("%s_glow"  , basename), 0, 0, false, r_mipskins.integer, precache);
+               skinframe->base   = loadtextureimagewithmaskandnmap(loadmodel->texturepool, basename, 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
+       skinframe->fog    = image_masktex;
+       skinframe->nmap   = image_nmaptex;
+       skinframe->gloss  = loadtextureimage(loadmodel->texturepool, va("%s_gloss" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
+       skinframe->pants  = loadtextureimage(loadmodel->texturepool, va("%s_pants" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
+       skinframe->shirt  = loadtextureimage(loadmodel->texturepool, va("%s_shirt" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
+       skinframe->glow   = loadtextureimage(loadmodel->texturepool, va("%s_glow"  , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0));
        skinframe->merged = NULL;
        return skinframe->base != NULL || skinframe->pants != NULL || skinframe->shirt != NULL || skinframe->glow != NULL;
 }
 
-static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, qbyte *skintemp, int width, int height, skinframe_t *skinframe, int precache)
+static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int height, skinframe_t *skinframe, int precache)
 {
-       if (!skindata || !skintemp)
+       qbyte *temp1, *temp2;
+       if (!skindata)
                return false;
-       skinframe->pants  = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0040, va("%s_pants", basename), false); // pants
-       skinframe->shirt  = GL_SkinSplitShirt(skindata, skintemp, width, height, 0x0002, va("%s_shirt", basename), false); // shirt
-       skinframe->glow   = GL_SkinSplit     (skindata, skintemp, width, height, 0xC000, va("%s_glow", basename), precache); // glow
+       temp1 = Mem_Alloc(loadmodel->mempool, width * height * 8);
+       temp2 = temp1 + width * height * 4;
+       Image_Copy8bitRGBA(skindata, temp1, width * height, palette_nofullbrights);
+       Image_HeightmapToNormalmap(temp1, temp2, width, height, false, 1);
+       skinframe->nmap   = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, (r_mipskins.integer ? TEXF_MIPMAP : 0) | (precache ? TEXF_PRECACHE : 0), NULL);
+       Mem_Free(temp1);
+       skinframe->gloss  = NULL;
+       skinframe->pants  = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, false); // pants
+       skinframe->shirt  = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, false); // shirt
+       skinframe->glow   = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, precache); // glow
        if (skinframe->pants || skinframe->shirt)
        {
-               skinframe->base   = GL_SkinSplit (skindata, skintemp, width, height, 0x3FBD, va("%s_normal", basename), false); // normal (no special colors)
-               skinframe->merged = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_body", basename), precache); // body (normal + pants + shirt, but not glow)
+               skinframe->base   = GL_TextureForSkinLayer(skindata, width, height, va("%s_normal", basename), palette_nocolormapnofullbrights, false); // normal (no special colors)
+               skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_body", basename), palette_nofullbrights, precache); // body (normal + pants + shirt, but not glow)
        }
        else
-               skinframe->base   = GL_SkinSplit (skindata, skintemp, width, height, 0x3FFF, va("%s_base", basename), precache); // no special colors
+               skinframe->base   = GL_TextureForSkinLayer(skindata, width, height, va("%s_base", basename), palette_nofullbrights, precache); // no special colors
        // quake model skins don't have alpha
        skinframe->fog = NULL;
        return true;
@@ -267,7 +228,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        float                                   scales, scalet, scale[3], translate[3], interval;
        qbyte                                   *datapointer, *startframes, *startskins;
        char                                    name[MAX_QPATH];
-       qbyte                                   *skintemp = NULL;
        skinframe_t                             tempskinframe;
        animscene_t                             *tempskinscenes;
        skinframe_t                             *tempskinframes;
@@ -368,7 +328,6 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
        }
 
        // load the skins
-       skintemp = Mem_Alloc(tempmempool, skinwidth * skinheight);
        loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
        loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, totalskins * sizeof(skinframe_t));
        totalskins = 0;
@@ -411,12 +370,11 @@ void Mod_LoadAliasModel (model_t *mod, void *buffer)
                        else
                                sprintf (name, "%s_%i", loadmodel->name, i);
                        if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0))
-                               Mod_LoadInternalSkin(name, (qbyte *)datapointer, skintemp, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0);
+                               Mod_LoadInternalSkin(name, (qbyte *)datapointer, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0);
                        datapointer += skinwidth * skinheight;
                        totalskins++;
                }
        }
-       Mem_Free(skintemp);
        // check for skins that don't exist in the model, but do exist as external images
        // (this was added because yummyluv kept pestering me about support for it)
        for (;;)
@@ -652,16 +610,18 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
        inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
        if (loadmodel->numskins)
        {
-               loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
-               loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, sizeof(skinframe_t) * loadmodel->numskins);
+               loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins + sizeof(skinframe_t) * loadmodel->numskins);
+               loadmodel->skinframes = (void *)(loadmodel->skinscenes + loadmodel->numskins);
                for (i = 0;i < loadmodel->numskins;i++)
                {
                        loadmodel->skinscenes[i].firstframe = i;
                        loadmodel->skinscenes[i].framecount = 1;
                        loadmodel->skinscenes[i].loop = true;
                        loadmodel->skinscenes[i].framerate = 10;
-                       loadmodel->skinframes[i].base = loadtextureimagewithmask (loadmodel->texturepool, inskin, 0, 0, true, r_mipskins.integer, true);
+                       loadmodel->skinframes[i].base = loadtextureimagewithmaskandnmap (loadmodel->texturepool, inskin, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1);
                        loadmodel->skinframes[i].fog = image_masktex;
+                       loadmodel->skinframes[i].nmap = image_nmaptex;
+                       loadmodel->skinframes[i].gloss = NULL;
                        loadmodel->skinframes[i].pants = NULL;
                        loadmodel->skinframes[i].shirt = NULL;
                        loadmodel->skinframes[i].glow = NULL;
@@ -1046,7 +1006,7 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer)
        //      zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
                shadername = (void *) (pheader->lump_shaders.start + pbase);
                for (i = 0;i < pheader->numshaders;i++)
-                       loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, r_mipskins.integer, true);
+                       loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0));
        }
 
        {
index d5fe31f..665483c 100644 (file)
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
 #include "quakedef.h"
+#include "image.h"
 
 // note: model_shared.c sets up r_notexture, and r_surf_notexture
 
@@ -90,7 +91,7 @@ void Mod_BrushStartup (void)
                                data[y][x][3] = 255;
                        }
                }
-               detailtextures[i] = R_LoadTexture(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE);
+               detailtextures[i] = R_LoadTexture2D(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
        }
 }
 
@@ -211,8 +212,13 @@ static void Mod_LoadTextures (lump_t *l)
        miptex_t *dmiptex;
        texture_t *tx, *tx2, *anims[10], *altanims[10];
        dmiptexlump_t *m;
-       qbyte *data, *mtdata, *data2;
+       qbyte *data, *mtdata;
        char name[256];
+       qbyte *basepixels, *bumppixels, *nmappixels, *glosspixels, *glowpixels, *maskpixels;
+       int basepixels_width, basepixels_height, bumppixels_width, bumppixels_height;
+       int nmappixels_width, nmappixels_height, glosspixels_width, glosspixels_height;
+       int glowpixels_width, glowpixels_height, maskpixels_width, maskpixels_height;
+       rtexture_t *detailtexture;
 
        loadmodel->textures = NULL;
 
@@ -290,6 +296,14 @@ static void Mod_LoadTextures (lump_t *l)
                        Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name);
                }
 
+               basepixels = NULL;
+               bumppixels = NULL;
+               nmappixels = NULL;
+               glosspixels = NULL;
+               glowpixels = NULL;
+               maskpixels = NULL;
+               detailtexture = NULL;
+
                // LordHavoc: HL sky textures are entirely different than quake
                if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128)
                {
@@ -315,98 +329,142 @@ static void Mod_LoadTextures (lump_t *l)
                                        R_InitSky (mtdata, 1);
                        }
                }
-               else if ((tx->texture = loadtextureimagewithmask(loadmodel->texturepool, tx->name, 0, 0, false, true, true)))
-               {
-                       tx->fogtexture = image_masktex;
-                       strcpy(name, tx->name);
-                       strcat(name, "_glow");
-                       tx->glowtexture = loadtextureimage(loadmodel->texturepool, name, 0, 0, false, true, true);
-               }
                else
                {
-                       if (loadmodel->ishlbsp)
+                       basepixels = loadimagepixels(tx->name, false, 0, 0);
+                       if (basepixels)
+                       {
+                               strcpy(name, tx->name);
+                               strcat(name, "_glow");
+                               glowpixels = loadimagepixels(name, false, 0, 0);
+                       }
+                       else
                        {
-                               if (mtdata && (data = W_ConvertWAD3Texture(dmiptex)))
+                               if (loadmodel->ishlbsp)
                                {
-                                       // texture included
-                                       tx->texture = R_LoadTexture (loadmodel->texturepool, tx->name, image_width, image_height, data, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
-                                       if (R_TextureHasAlpha(tx->texture))
+                                       // internal texture overrides wad
+                                       if (mtdata && (basepixels = W_ConvertWAD3Texture(dmiptex)) != NULL)
                                        {
-                                               // make mask texture
-                                               for (j = 0;j < image_width * image_height;j++)
-                                                       data[j*4+0] = data[j*4+1] = data[j*4+2] = 255;
-                                               strcpy(name, tx->name);
-                                               strcat(name, "_fog");
-                                               tx->fogtexture = R_LoadTexture (loadmodel->texturepool, name, image_width, image_height, data, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
+                                               basepixels_width = image_width;
+                                               basepixels_height = image_height;
                                        }
-                                       Mem_Free(data);
-                               }
-                               else if ((data = W_GetTexture(tx->name)))
-                               {
-                                       // get the size from the wad texture
-                                       tx->width = image_width;
-                                       tx->height = image_height;
-                                       tx->texture = R_LoadTexture (loadmodel->texturepool, tx->name, image_width, image_height, data, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
-                                       if (R_TextureHasAlpha(tx->texture))
+                                       else if ((basepixels = W_GetTexture(tx->name)) != NULL)
                                        {
-                                               // make mask texture
-                                               for (j = 0;j < image_width * image_height;j++)
-                                                       data[j*4+0] = data[j*4+1] = data[j*4+2] = 255;
-                                               strcpy(name, tx->name);
-                                               strcat(name, "_fog");
-                                               tx->fogtexture = R_LoadTexture (loadmodel->texturepool, name, image_width, image_height, data, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
+                                               // get the size from the wad texture
+                                               tx->width = basepixels_width = image_width;
+                                               tx->height = basepixels_height = image_height;
                                        }
-                                       Mem_Free(data);
                                }
                                else
                                {
-                                       tx->width = 16;
-                                       tx->height = 16;
-                                       tx->texture = r_notexture;
-                               }
-                       }
-                       else
-                       {
-                               if (mtdata) // texture included
-                               {
-                                       int fullbrights;
-                                       data = mtdata;
-                                       fullbrights = false;
-                                       if (r_fullbrights.value && tx->name[0] != '*')
+                                       if (mtdata) // texture included
                                        {
-                                               for (j = 0;j < tx->width*tx->height;j++)
+                                               if (r_fullbrights.integer && tx->name[0] != '*')
                                                {
-                                                       if (data[j] >= 224) // fullbright
+                                                       basepixels_width = tx->width;
+                                                       basepixels_height = tx->height;
+                                                       basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
+                                                       Image_Copy8bitRGBA(mtdata, basepixels, basepixels_width * basepixels_height, palette_nofullbrights);
+                                                       for (j = 0;j < tx->width*tx->height;j++)
+                                                               if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright
+                                                                       break;
+                                                       if (j < tx->width * tx->height)
                                                        {
-                                                               fullbrights = true;
-                                                               break;
+                                                               glowpixels_width = tx->width;
+                                                               glowpixels_height = tx->height;
+                                                               glowpixels = Mem_Alloc(loadmodel->mempool, glowpixels_width * glowpixels_height * 4);
+                                                               Image_Copy8bitRGBA(mtdata, glowpixels, glowpixels_width * glowpixels_height, palette_onlyfullbrights);
                                                        }
                                                }
+                                               else
+                                               {
+                                                       basepixels_width = tx->width;
+                                                       basepixels_height = tx->height;
+                                                       basepixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
+                                                       Image_Copy8bitRGBA(mtdata, basepixels, tx->width * tx->height, palette_complete);
+                                               }
                                        }
-                                       if (fullbrights)
-                                       {
-                                               data2 = Mem_Alloc(loadmodel->mempool, tx->width*tx->height);
-                                               for (j = 0;j < tx->width*tx->height;j++)
-                                                       data2[j] = data[j] >= 224 ? 0 : data[j]; // no fullbrights
-                                               tx->texture = R_LoadTexture (loadmodel->texturepool, tx->name, tx->width, tx->height, data2, TEXTYPE_QPALETTE, TEXF_MIPMAP | TEXF_PRECACHE);
-                                               strcpy(name, tx->name);
-                                               strcat(name, "_glow");
-                                               for (j = 0;j < tx->width*tx->height;j++)
-                                                       data2[j] = data[j] >= 224 ? data[j] : 0; // only fullbrights
-                                               tx->glowtexture = R_LoadTexture (loadmodel->texturepool, name, tx->width, tx->height, data2, TEXTYPE_QPALETTE, TEXF_MIPMAP | TEXF_PRECACHE);
-                                               Mem_Free(data2);
-                                       }
-                                       else
-                                               tx->texture = R_LoadTexture (loadmodel->texturepool, tx->name, tx->width, tx->height, data, TEXTYPE_QPALETTE, TEXF_MIPMAP | TEXF_PRECACHE);
                                }
-                               else // no texture, and no external replacement texture was found
+                       }
+               }
+
+               if (basepixels)
+               {
+                       for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
+                               if (basepixels[j] < 255)
+                                       break;
+                       if (j < basepixels_width * basepixels_height * 4)
+                       {
+                               maskpixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
+                               maskpixels_width = basepixels_width;
+                               maskpixels_height = basepixels_height;
+                               for (j = 0;j < basepixels_width * basepixels_height * 4;j += 4)
                                {
-                                       tx->width = 16;
-                                       tx->height = 16;
-                                       tx->texture = r_notexture;
+                                       maskpixels[j+0] = 255;
+                                       maskpixels[j+1] = 255;
+                                       maskpixels[j+2] = 255;
+                                       maskpixels[j+3] = basepixels[j+3];
                                }
                        }
+
+                       if (!bumppixels)
+                       {
+                               bumppixels = Mem_Alloc(loadmodel->mempool, basepixels_width * basepixels_height * 4);
+                               bumppixels_width = basepixels_width;
+                               bumppixels_height = basepixels_height;
+                               memcpy(bumppixels, basepixels, bumppixels_width * bumppixels_height * 4);
+                       }
+
+                       if (!nmappixels && bumppixels)
+                       {
+                               nmappixels = Mem_Alloc(loadmodel->mempool, bumppixels_width * bumppixels_height * 4);
+                               nmappixels_width = bumppixels_width;
+                               nmappixels_height = bumppixels_height;
+                               Image_HeightmapToNormalmap(bumppixels, nmappixels, nmappixels_width, nmappixels_height, false, 1);
+                       }
+               }
+
+               if (!detailtexture)
+                       detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
+
+               if (basepixels)
+               {
+                       tx->texture = R_LoadTexture2D (loadmodel->texturepool, tx->name, basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
+                       if (nmappixels)
+                               tx->nmaptexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", tx->name), basepixels_width, basepixels_height, basepixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
+                       if (glosspixels)
+                               tx->glosstexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", tx->name), glosspixels_width, glosspixels_height, glosspixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
+                       if (glowpixels)
+                               tx->glowtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_glow", tx->name), glowpixels_width, glowpixels_height, glowpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
+                       if (maskpixels)
+                               tx->fogtexture = R_LoadTexture2D (loadmodel->texturepool, va("%s_mask", tx->name), maskpixels_width, maskpixels_height, maskpixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
+                       tx->detailtexture = detailtexture;
                }
+               else
+               {
+                       // no texture found
+                       tx->width = 16;
+                       tx->height = 16;
+                       tx->texture = r_notexture;
+                       tx->nmaptexture = NULL;
+                       tx->glosstexture = NULL;
+                       tx->glowtexture = NULL;
+                       tx->fogtexture = NULL;
+                       tx->detailtexture = NULL;
+               }
+
+               if (basepixels)
+                       Mem_Free(basepixels);
+               if (bumppixels)
+                       Mem_Free(bumppixels);
+               if (nmappixels)
+                       Mem_Free(nmappixels);
+               if (glosspixels)
+                       Mem_Free(glosspixels);
+               if (glowpixels)
+                       Mem_Free(glowpixels);
+               if (maskpixels)
+                       Mem_Free(maskpixels);
 
                if (tx->name[0] == '*')
                {
@@ -433,7 +491,6 @@ static void Mod_LoadTextures (lump_t *l)
                        tx->shader = &Cshader_wall_lightmap;
                }
 
-               tx->detailtexture = detailtextures[i % NUM_DETAILTEXTURES];
                // start out with no animation
                tx->currentframe[0] = tx;
                tx->currentframe[1] = tx;
@@ -2203,12 +2260,12 @@ void Mod_GenerateWallMesh (msurface_t *surf, int vertexonly)
                if (r_miplightmaps.integer)
                {
                        surf->lightmaptexturestride = (surf->extents[0]>>4)+1;
-                       surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE);
+                       surf->lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
                }
                else
                {
                        surf->lightmaptexturestride = R_CompatibleFragmentWidth((surf->extents[0]>>4)+1, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, 0);
-                       surf->lightmaptexture = R_LoadTexture(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE);
+                       surf->lightmaptexture = R_LoadTexture2D(loadmodel->texturepool, NULL, surf->lightmaptexturestride, (surf->extents[1]>>4)+1, NULL, loadmodel->lightmaprgba ? TEXTYPE_RGBA : TEXTYPE_RGB, TEXF_FRAGMENT | TEXF_PRECACHE, NULL);
                }
                R_FragmentLocation(surf->lightmaptexture, NULL, NULL, &ubase, &vbase, &uscale, &vscale);
                uscale = (uscale - ubase) * 16.0 / ((surf->extents[0] & ~15) + 16);
index c2eed62..3d031e7 100644 (file)
@@ -113,6 +113,10 @@ typedef struct texture_s
        rtexture_t *fogtexture;
        // detail texture (usually not used if transparent)
        rtexture_t *detailtexture;
+       // normalmap for bumpmap shading
+       rtexture_t *nmaptexture;
+       // color filtering for glossy surfaces
+       rtexture_t *glosstexture;
 
        // shader to use for this texture
        Cshader_t *shader;
@@ -191,7 +195,6 @@ typedef struct msurface_s
        short extents[2];
 
        mtexinfo_t *texinfo;
-       texture_t *currenttexture; // updated (animated) during early surface processing each frame
 
        // index into d_lightstylevalue array, 255 means not used (black)
        qbyte styles[MAXLIGHTMAPS];
index 8c7342a..10d3762 100644 (file)
@@ -63,7 +63,7 @@ void Mod_SetupNoTexture(void)
        }
 
        r_notexturepool = R_AllocTexturePool();
-       r_notexture = R_LoadTexture(r_notexturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP);
+       r_notexture = R_LoadTexture2D(r_notexturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
 }
 
 extern void Mod_BrushStartup (void);
index 0523fb3..f013bb2 100644 (file)
@@ -53,6 +53,8 @@ typedef struct skinframe_s
        rtexture_t *glow; // glow only
        rtexture_t *merged; // original texture minus glow
        rtexture_t *fog; // white texture with alpha of the base texture, NULL if not transparent
+       rtexture_t *nmap; // normalmap (bumpmap for dot3)
+       rtexture_t *gloss; // glossmap (for dot3)
 }
 skinframe_t;
 
index 0d96a24..732b8c6 100644 (file)
@@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 // on the same machine.
 
 #include "quakedef.h"
+#include "image.h"
 
 cvar_t r_mipsprites = {CVAR_SAVE, "r_mipsprites", "1"};
 
@@ -181,7 +182,7 @@ static void Mod_Sprite_SharedSetup(qbyte *datapointer, int version, int *palette
                                        sprintf (name, "%s_%i_%i", tempname, i, j);
                                else
                                        sprintf (name, "%s_%i", tempname, i);
-                               loadmodel->sprdata_frames[realframes].texture = loadtextureimagewithmask(loadmodel->texturepool, name, 0, 0, false, r_mipsprites.integer, true);
+                               loadmodel->sprdata_frames[realframes].texture = loadtextureimagewithmask(loadmodel->texturepool, name, 0, 0, false, (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE);
                                loadmodel->sprdata_frames[realframes].fogtexture = image_masktex;
 
                                if (!loadmodel->sprdata_frames[realframes].texture)
@@ -192,7 +193,7 @@ static void Mod_Sprite_SharedSetup(qbyte *datapointer, int version, int *palette
                                        else //if (version == SPRITE_VERSION || version == SPRITEHL_VERSION)
                                                Image_Copy8bitRGBA(datapointer, pixbuf, width*height, palette);
 
-                                       loadmodel->sprdata_frames[realframes].texture = R_LoadTexture (loadmodel->texturepool, name, width, height, pixbuf, TEXTYPE_RGBA, TEXF_ALPHA | (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
+                                       loadmodel->sprdata_frames[realframes].texture = R_LoadTexture2D (loadmodel->texturepool, name, width, height, pixbuf, TEXTYPE_RGBA, TEXF_ALPHA | (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_PRECACHE, NULL);
 
                                        // make fog version (just alpha)
                                        for (k = 0;k < width*height;k++)
@@ -205,7 +206,7 @@ static void Mod_Sprite_SharedSetup(qbyte *datapointer, int version, int *palette
                                                sprintf (name, "%s_%i_%ifog", tempname, i, j);
                                        else
                                                sprintf (name, "%s_%ifog", tempname, i);
-                                       loadmodel->sprdata_frames[realframes].fogtexture = R_LoadTexture (loadmodel->texturepool, name, width, height, pixbuf, TEXTYPE_RGBA, TEXF_ALPHA | (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
+                                       loadmodel->sprdata_frames[realframes].fogtexture = R_LoadTexture2D (loadmodel->texturepool, name, width, height, pixbuf, TEXTYPE_RGBA, TEXF_ALPHA | (r_mipsprites.integer ? TEXF_MIPMAP : 0) | TEXF_PRECACHE, NULL);
 
                                        Mem_Free(pixbuf);
                                }
@@ -262,7 +263,7 @@ void Mod_LoadSpriteModel (model_t *mod, void *buffer)
                loadmodel->sprnum_type = LittleLong (pinqsprite->type);
                loadmodel->synctype = LittleLong (pinqsprite->synctype);
 
-               Mod_Sprite_SharedSetup(datapointer, LittleLong (pinqsprite->version), d_8to24table);
+               Mod_Sprite_SharedSetup(datapointer, LittleLong (pinqsprite->version), palette_complete);
        }
        else if (version == SPRITEHL_VERSION)
        {
index c7dd2e8..7dbc82f 100644 (file)
--- a/palette.c
+++ b/palette.c
@@ -1,7 +1,15 @@
 
 #include "quakedef.h"
 
-unsigned int d_8to24table[256];
+unsigned int palette_complete[256];
+unsigned int palette_nofullbrights[256];
+unsigned int palette_onlyfullbrights[256];
+unsigned int palette_nocolormapnofullbrights[256];
+unsigned int palette_pantsaswhite[256];
+unsigned int palette_shirtaswhite[256];
+unsigned int palette_alpha[256];
+unsigned int palette_font[256];
+
 qbyte host_basepal[768];
 
 cvar_t v_gamma = {CVAR_SAVE, "v_gamma", "1"};
@@ -13,18 +21,82 @@ cvar_t v_hwgamma = {0, "v_hwgamma", "1"};
 void Palette_Setup8to24(void)
 {
        int i;
+       int fullbright_start, fullbright_end;
+       int pants_start, pants_end;
+       int shirt_start, shirt_end;
+       int reversed_start, reversed_end;
        qbyte *in, *out;
+       qbyte *colormap;
 
        in = host_basepal;
-       out = (qbyte *) d_8to24table; // d_8to24table is accessed as 32bit for speed reasons, but is created as 8bit bytes
-       for (i=0 ; i<255 ; i++)
+       out = (qbyte *) palette_complete; // palette is accessed as 32bit for speed reasons, but is created as 8bit bytes
+       for (i = 0;i < 255;i++)
        {
                *out++ = *in++;
                *out++ = *in++;
                *out++ = *in++;
                *out++ = 255;
        }
-       d_8to24table[255] = 0; // completely transparent black
+       palette_complete[255] = 0; // completely transparent black
+
+       // FIXME: fullbright_start should be read from colormap.lmp
+       colormap = COM_LoadFile("gfx/colormap.lmp", true);
+       if (colormap && com_filesize >= 16385)
+               fullbright_start = 256 - colormap[16384];
+       else
+               fullbright_start = 256;
+       if (colormap)
+               Mem_Free(colormap);
+       fullbright_end = 256;
+       pants_start = 96;
+       pants_end = 112;
+       shirt_start = 16;
+       shirt_end = 32;
+       reversed_start = 128;
+       reversed_end = 224;
+
+       memset(palette_nofullbrights, 0, sizeof(palette_nofullbrights));
+       for (i = 0;i < fullbright_start;i++)
+               palette_nofullbrights[i] = palette_complete[i];
+
+       memset(palette_onlyfullbrights, 0, sizeof(palette_onlyfullbrights));
+       for (i = fullbright_start;i < fullbright_end;i++)
+               palette_onlyfullbrights[i] = palette_complete[i];
+
+       for (i = 0;i < 256;i++)
+               palette_nocolormapnofullbrights[i] = palette_complete[i];
+       for (i = pants_start;i < pants_end;i++)
+               palette_nocolormapnofullbrights[i] = 0;
+       for (i = shirt_start;i < shirt_end;i++)
+               palette_nocolormapnofullbrights[i] = 0;
+       for (i = fullbright_start;i < fullbright_end;i++)
+               palette_nocolormapnofullbrights[i] = 0;
+
+       memset(palette_pantsaswhite, 0, sizeof(palette_pantsaswhite));
+       for (i = pants_start;i < pants_end;i++)
+       {
+               if (i >= reversed_start && i < reversed_end)
+                       palette_pantsaswhite[i] = 15 - (i - pants_start);
+               else
+                       palette_pantsaswhite[i] = i - pants_start;
+       }
+
+       memset(palette_shirtaswhite, 0, sizeof(palette_shirtaswhite));
+       for (i = shirt_start;i < shirt_end;i++)
+       {
+               if (i >= reversed_start && i < reversed_end)
+                       palette_shirtaswhite[i] = 15 - (i - shirt_start);
+               else
+                       palette_shirtaswhite[i] = i - shirt_start;
+       }
+
+       memset(palette_alpha, 0, sizeof(palette_alpha));
+       for (i = 0;i < 255;i++)
+               palette_alpha[i] = 0xFFFFFFFF;
+
+       memset(palette_font, 0, sizeof(palette_font));
+       for (i = 1;i < 255;i++)
+               palette_font[i] = palette_complete[i];
 }
 
 
index 8013e98..e1dcfda 100644 (file)
--- a/palette.h
+++ b/palette.h
@@ -8,8 +8,14 @@ extern cvar_t v_brightness;
 extern cvar_t v_overbrightbits;
 extern cvar_t v_hwgamma;
 
-extern unsigned int d_8to24table[256];
-//extern qbyte d_15to8table[32768];
+extern unsigned int palette_complete[256];
+extern unsigned int palette_nofullbrights[256];
+extern unsigned int palette_onlyfullbrights[256];
+extern unsigned int palette_nocolormapnofullbrights[256];
+extern unsigned int palette_pantsaswhite[256];
+extern unsigned int palette_shirtaswhite[256];
+extern unsigned int palette_alpha[256];
+extern unsigned int palette_font[256];
 
 extern qboolean hardwaregammasupported;
 
index 86529c7..dc1be09 100644 (file)
@@ -243,7 +243,6 @@ void fractalnoise(unsigned char *noise, int size, int startgrid);
 void fractalnoisequick(unsigned char *noise, int size, int startgrid);
 
 #include "palette.h"
-#include "image.h"
 
 void Sys_Shared_Init(void);
 
index 7e7bf70..e660f08 100644 (file)
@@ -76,7 +76,7 @@ void R_GetCrosshairColor(float *out)
        }
        else
                i = 15;
-       color = (qbyte *) &d_8to24table[i];
+       color = (qbyte *) &palette_complete[i];
        if (crosshair_flashspeed.value >= 0.01f)
                base = (sin(realtime * crosshair_flashspeed.value * (M_PI*2.0f)) * crosshair_flashrange.value);
        else
index 168a9ff..aa08b1b 100644 (file)
@@ -80,11 +80,11 @@ void r_explosion_start(void)
                        data[y][x][3] = bound(0, a, 255);
                }
        }
-       explosiontexture = R_LoadTexture (explosiontexturepool, "explosiontexture", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
+       explosiontexture = R_LoadTexture2D(explosiontexturepool, "explosiontexture", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
        for (y = 0;y < 128;y++)
                for (x = 0;x < 128;x++)
                        data[y][x][0] = data[y][x][1] = data[y][x][2] = 255;
-       explosiontexturefog = R_LoadTexture (explosiontexturepool, "explosiontexturefog", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE);
+       explosiontexturefog = R_LoadTexture2D(explosiontexturepool, "explosiontexturefog", 128, 128, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL);
        // note that explosions survive the restart
 }
 
index b33418c..e233ff7 100644 (file)
--- a/r_light.c
+++ b/r_light.c
@@ -53,7 +53,7 @@ void r_light_start(void)
                        pixels[y][x][3] = 255;
                }
        }
-       lightcorona = R_LoadTexture (lighttexturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE);
+       lightcorona = R_LoadTexture2D(lighttexturepool, "lightcorona", 32, 32, &pixels[0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
 }
 
 void r_light_shutdown(void)
index eca072c..f648a5e 100644 (file)
@@ -292,7 +292,7 @@ float r_shadow_atten1, r_shadow_atten2, r_shadow_atten5;
 static void R_Shadow_Make3DTextures(void)
 {
        int x, y, z, d;
-       float v[3], intensity, ilen, length;
+       float v[3], intensity, ilen, length, bordercolor[4];
        qbyte data[ATTEN3DSIZE][ATTEN3DSIZE][ATTEN3DSIZE][4];
        if (r_light_quality.integer != 1 || !gl_texture3d)
                return;
@@ -318,7 +318,12 @@ static void R_Shadow_Make3DTextures(void)
                        }
                }
        }
-       r_shadow_normalsattenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "normalsattenuation", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+       r_shadow_normalsattenuationtexture = R_LoadTexture3D(r_shadow_texturepool, "normalsattenuation", ATTEN3DSIZE, ATTEN3DSIZE, ATTEN3DSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
+       bordercolor[0] = 0.5f;
+       bordercolor[1] = 0.5f;
+       bordercolor[2] = 0.5f;
+       bordercolor[3] = 1.0f;
+       qglTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, bordercolor);
 }
 
 static void R_Shadow_MakeTextures(void)
@@ -341,7 +346,7 @@ static void R_Shadow_MakeTextures(void)
                        data[0][y][x][3] = 255;
                }
        }
-       r_shadow_blankbumptexture = R_LoadTexture(r_shadow_texturepool, "blankbump", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE);
+       r_shadow_blankbumptexture = R_LoadTexture2D(r_shadow_texturepool, "blankbump", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
        for (side = 0;side < 6;side++)
        {
                for (y = 0;y < 128;y++)
@@ -391,7 +396,7 @@ static void R_Shadow_MakeTextures(void)
                        }
                }
        }
-       r_shadow_normalscubetexture = R_LoadTextureCubeMap(r_shadow_texturepool, "normalscube", 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+       r_shadow_normalscubetexture = R_LoadTextureCubeMap(r_shadow_texturepool, "normalscube", 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
        for (y = 0;y < 128;y++)
        {
                for (x = 0;x < 128;x++)
@@ -410,7 +415,7 @@ static void R_Shadow_MakeTextures(void)
                        data[0][y][x][3] = 255;
                }
        }
-       r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP);
+       r_shadow_attenuation2dtexture = R_LoadTexture2D(r_shadow_texturepool, "attenuation2d", 128, 128, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
        R_Shadow_Make3DTextures();
 }
 
@@ -525,9 +530,32 @@ void R_Shadow_GenTexCoords_Diffuse_Attenuation3D(float *out, int numverts, const
        for (i = 0;i < numverts;i++, vertex += 4, svectors += 4, tvectors += 4, normals += 4, out += 4)
        {
                VectorSubtract(vertex, relativelightorigin, lightvec);
-               out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
-               out[1] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
-               out[2] = 0.5f + DotProduct(normals, lightvec) * iradius;
+               if (r_shadow6.integer != 0)
+               {
+                       VectorClear(lightvec);
+                       if (r_shadow6.integer > 0)
+                               lightvec[(r_shadow6.integer - 1) % 3] = 64;
+                       else
+                               lightvec[((-r_shadow6.integer) - 1) % 3] = -64;
+               }
+               if (r_shadow4.integer & 8)
+                       lightvec[0] = -lightvec[0];
+               if (r_shadow4.integer & 16)
+                       lightvec[1] = -lightvec[1];
+               if (r_shadow4.integer & 32)
+                       lightvec[2] = -lightvec[2];
+               if (r_shadow4.integer & 1)
+                       out[0] = 0.5f - DotProduct(svectors, lightvec) * iradius;
+               else
+                       out[0] = 0.5f + DotProduct(svectors, lightvec) * iradius;
+               if (r_shadow4.integer & 2)
+                       out[1] = 0.5f - DotProduct(tvectors, lightvec) * iradius;
+               else
+                       out[2] = 0.5f + DotProduct(tvectors, lightvec) * iradius;
+               if (r_shadow4.integer & 4)
+                       out[2] = 0.5f - DotProduct(normals, lightvec) * iradius;
+               else
+                       out[2] = 0.5f + DotProduct(normals, lightvec) * iradius;
        }
 }
 
@@ -618,6 +646,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        m.texcombinergb[1] = GL_DOT3_RGB_ARB;
                        m.texcombinergb[2] = GL_MODULATE;
                        m.texcombinergb[3] = GL_MODULATE;
+                       m.texrgbscale[2] = 2;
                        R_Mesh_TextureState(&m);
                        R_Shadow_GenTexCoords_Diffuse_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, lightradius);
                        if (m.texcubemap[3])
@@ -634,6 +663,7 @@ void R_Shadow_RenderLighting(int numverts, int numtriangles, const int *elements
                        m.texcombinergb[1] = GL_DOT3_RGB_ARB;
                        m.texcombinergb[2] = GL_MODULATE;
                        m.texcombinergb[3] = GL_MODULATE;
+                       m.texrgbscale[2] = 2;
                        R_Mesh_TextureState(&m);
                        R_Shadow_GenTexCoords_Specular_Attenuation3D(varray_texcoord[1], numverts, varray_vertex, svectors, tvectors, normals, relativelightorigin, relativeeyeorigin, lightradius);
                        R_Mesh_Draw(numverts, numtriangles, elements);
diff --git a/r_sky.c b/r_sky.c
index 6f1cb06..63f2820 100644 (file)
--- a/r_sky.c
+++ b/r_sky.c
@@ -1,5 +1,6 @@
 
 #include "quakedef.h"
+#include "image.h"
 
 cvar_t r_sky = {CVAR_SAVE, "r_sky", "1"};
 qboolean skyavailable_quake;
@@ -73,7 +74,7 @@ int R_SetSkyBox(const char *sky)
                                continue;
                        }
                }
-               skyboxside[i] = R_LoadTexture(skytexturepool, va("skyboxside%d", i), image_width, image_height, image_rgba, TEXTYPE_RGBA, TEXF_PRECACHE);
+               skyboxside[i] = R_LoadTexture2D(skytexturepool, va("skyboxside%d", i), image_width, image_height, image_rgba, TEXTYPE_RGBA, TEXF_CLAMP | TEXF_PRECACHE, NULL);
                Mem_Free(image_rgba);
        }
 
@@ -122,8 +123,8 @@ static void R_SkyBox(void)
        varray_vertex[i * 4 + 0] = (x) * 16.0f;\
        varray_vertex[i * 4 + 1] = (y) * 16.0f;\
        varray_vertex[i * 4 + 2] = (z) * 16.0f;\
-       varray_texcoord[0][i * 4 + 0] = (s) * (254.0f/256.0f) + (1.0f/256.0f);\
-       varray_texcoord[0][i * 4 + 1] = (t) * (254.0f/256.0f) + (1.0f/256.0f);
+       varray_texcoord[0][i * 4 + 0] = (s);\
+       varray_texcoord[0][i * 4 + 1] = (t);
 
        memset(&m, 0, sizeof(m));
        m.blendfunc1 = GL_ONE;
@@ -357,7 +358,7 @@ void R_InitSky (qbyte *src, int bytesperpixel)
                        for (j=0 ; j<128 ; j++)
                        {
                                p = src[i*256 + j + 128];
-                               rgba = &d_8to24table[p];
+                               rgba = &palette_complete[p];
                                trans[(i*128) + j] = *rgba;
                                r += ((qbyte *)rgba)[0];
                                g += ((qbyte *)rgba)[1];
@@ -373,7 +374,7 @@ void R_InitSky (qbyte *src, int bytesperpixel)
 
        memcpy(skyupperlayerpixels, trans, 128*128*4);
 
-       solidskytexture = R_LoadTexture (skytexturepool, "sky_solidtexture", 128, 128, (qbyte *) trans, TEXTYPE_RGBA, TEXF_PRECACHE);
+       solidskytexture = R_LoadTexture2D(skytexturepool, "sky_solidtexture", 128, 128, (qbyte *) trans, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
 
        if (bytesperpixel == 4)
        {
@@ -391,14 +392,14 @@ void R_InitSky (qbyte *src, int bytesperpixel)
                                if (p == 0)
                                        trans[(i*128) + j] = transpix;
                                else
-                                       trans[(i*128) + j] = d_8to24table[p];
+                                       trans[(i*128) + j] = palette_complete[p];
                        }
                }
        }
 
        memcpy(skylowerlayerpixels, trans, 128*128*4);
 
-       alphaskytexture = R_LoadTexture (skytexturepool, "sky_alphatexture", 128, 128, (qbyte *) trans, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE);
+       alphaskytexture = R_LoadTexture2D(skytexturepool, "sky_alphatexture", 128, 128, (qbyte *) trans, TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
 }
 
 void R_ResetQuakeSky(void)
index 48f6220..5cf3753 100644 (file)
@@ -18,8 +18,8 @@
 // used for checking if textures mismatch
 #define TEXF_IMPORTANTBITS (TEXF_ALPHA | TEXF_MIPMAP | TEXF_FRAGMENT | TEXF_CLAMP)
 
-// 8bit quake paletted
-#define TEXTYPE_QPALETTE 1
+// 8bit paletted
+#define TEXTYPE_PALETTE 1
 // 24bit RGB
 #define TEXTYPE_RGB 2
 // 32bit RGBA
@@ -52,11 +52,11 @@ int R_CompatibleFragmentWidth(int width, int textype, int flags);
 
 // add a texture to a pool and optionally precache (upload) it
 // (note: data == NULL is perfectly acceptable)
-rtexture_t *R_LoadTexture(rtexturepool_t *rtexturepool, char *identifier, int width, int height, qbyte *data, int textype, int flags);
-rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, char *identifier, int width, qbyte *data, int textype, int flags);
-rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, char *identifier, int width, int height, qbyte *data, int textype, int flags);
-rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, char *identifier, int width, int height, int depth, qbyte *data, int textype, int flags);
-rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, char *identifier, int width, qbyte *data, int textype, int flags);
+// (note: palette must not be NULL if using TEXTYPE_PALETTE)
+rtexture_t *R_LoadTexture1D(rtexturepool_t *rtexturepool, const char *identifier, int width, const qbyte *data, int textype, int flags, const unsigned int *palette);
+rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const qbyte *data, int textype, int flags, const unsigned int *palette);
+rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const qbyte *data, int textype, int flags, const unsigned int *palette);
+rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const qbyte *data, int textype, int flags, const unsigned int *palette);
 
 // free a texture
 void R_FreeTexture(rtexture_t *rt);
index fdeb233..7ca8cfc 100644 (file)
--- a/render.h
+++ b/render.h
@@ -149,7 +149,6 @@ extern float overbrightscale;
 #include "r_lerpanim.h"
 
 extern cvar_t r_render;
-#include "image.h"
 
 extern cvar_t r_textureunits;
 extern cvar_t gl_dither;
diff --git a/sbar.c b/sbar.c
index de556fa..77fd458 100644 (file)
--- a/sbar.c
+++ b/sbar.c
@@ -634,9 +634,9 @@ void Sbar_DrawFrags (void)
                        continue;
 
                // draw background
-               c = (qbyte *)&d_8to24table[(s->colors & 0xf0) + 8];
+               c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
                DrawQ_Fill (sbar_x + x + 10, sbar_y     - 23, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
-               c = (qbyte *)&d_8to24table[((s->colors & 15)<<4) + 8];
+               c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
                DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
 
                // draw number
@@ -679,9 +679,9 @@ void Sbar_DrawFace (void)
                s = &cl.scores[cl.viewentity - 1];
                // draw background
                Sbar_DrawPic (112, 0, rsb_teambord);
-               c = (qbyte *)&d_8to24table[(s->colors & 0xf0) + 8];
+               c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
                DrawQ_Fill (sbar_x + 113, vid.conheight-SBAR_HEIGHT+3, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
-               c = (qbyte *)&d_8to24table[((s->colors & 15)<<4) + 8];
+               c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
                DrawQ_Fill (sbar_x + 113, vid.conheight-SBAR_HEIGHT+12, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
 
                // draw number
@@ -948,9 +948,9 @@ void Sbar_DeathmatchOverlay (void)
                        continue;
 
        // draw background
-               c = (qbyte *)&d_8to24table[(s->colors & 0xf0) + 8];
+               c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
                DrawQ_Fill ( x + 8, y+1, 88, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
-               c = (qbyte *)&d_8to24table[((s->colors & 15)<<4) + 8];
+               c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
                DrawQ_Fill ( x + 8, y+4, 88, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
 
                total = cl.time - s->entertime;
@@ -1021,9 +1021,9 @@ void Sbar_MiniDeathmatchOverlay (void)
                        continue;
 
                // draw background
-               c = (qbyte *)&d_8to24table[(s->colors & 0xf0) + 8];
+               c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
                DrawQ_Fill ( x, y+1, 72, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
-               c = (qbyte *)&d_8to24table[((s->colors & 15)<<4) + 8];
+               c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
                DrawQ_Fill ( x, y+4, 72, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f), 0);
 
                fph = (cl.time - s->entertime) ? (int) ((float) s->frags * 3600.0 / (cl.time - s->entertime)) : 0;
index 00c9485..6d59a92 100644 (file)
@@ -146,9 +146,10 @@ void (GLAPIENTRY *qglStencilMask)(GLuint mask);
 void (GLAPIENTRY *qglStencilOp)(GLenum fail, GLenum zfail, GLenum zpass);
 void (GLAPIENTRY *qglClearStencil)(GLint s);
 
-//void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
+void (GLAPIENTRY *qglTexEnvf)(GLenum target, GLenum pname, GLfloat param);
 void (GLAPIENTRY *qglTexEnvi)(GLenum target, GLenum pname, GLint param);
-//void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+void (GLAPIENTRY *qglTexParameterf)(GLenum target, GLenum pname, GLfloat param);
+void (GLAPIENTRY *qglTexParameterfv)(GLenum target, GLenum pname, GLfloat *params);
 void (GLAPIENTRY *qglTexParameteri)(GLenum target, GLenum pname, GLint param);
 
 void (GLAPIENTRY *qglGenTextures)(GLsizei n, GLuint *textures);
@@ -281,9 +282,10 @@ static gl_extensionfunctionlist_t opengl110funcs[] =
        {"glStencilMask", (void **) &qglStencilMask},
        {"glStencilOp", (void **) &qglStencilOp},
        {"glClearStencil", (void **) &qglClearStencil},
-//     {"glTexEnvf", (void **) &qglTexEnvf},
+       {"glTexEnvf", (void **) &qglTexEnvf},
        {"glTexEnvi", (void **) &qglTexEnvi},
-//     {"glTexParameterf", (void **) &qglTexParameterf},
+       {"glTexParameterf", (void **) &qglTexParameterf},
+       {"glTexParameterfv", (void **) &qglTexParameterfv},
        {"glTexParameteri", (void **) &qglTexParameteri},
        {"glPixelStoref", (void **) &qglPixelStoref},
        {"glPixelStorei", (void **) &qglPixelStorei},