From 63a4ff4563c4bbd232c265a288e9890e4015bd93 Mon Sep 17 00:00:00 2001 From: havoc Date: Mon, 14 Oct 2002 19:05:23 +0000 Subject: [PATCH] R_LoadTexture functions take a palette pointer now 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 --- cl_main.c | 2 +- cl_parse.c | 2 +- cl_particles.c | 2 +- cl_video.c | 2 +- gl_backend.c | 1 + gl_draw.c | 15 ++-- gl_models.c | 6 +- gl_rsurf.c | 38 +++++---- gl_textures.c | 57 +++++++------- glquake.h | 6 +- image.c | 184 +++++++++++++++++++++++++++++++------------ image.h | 34 ++++---- menu.c | 3 +- model_alias.c | 116 +++++++++------------------ model_brush.c | 207 +++++++++++++++++++++++++++++++------------------ model_brush.h | 5 +- model_shared.c | 2 +- model_shared.h | 2 + model_sprite.c | 9 ++- palette.c | 80 ++++++++++++++++++- palette.h | 10 ++- quakedef.h | 1 - r_crosshairs.c | 2 +- r_explosion.c | 4 +- r_light.c | 2 +- r_shadow.c | 46 +++++++++-- r_sky.c | 15 ++-- r_textures.h | 14 ++-- render.h | 1 - sbar.c | 16 ++-- vid_shared.c | 10 ++- 31 files changed, 565 insertions(+), 329 deletions(-) diff --git a/cl_main.c b/cl_main.c index c483a337..1e04c31e 100644 --- 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) diff --git a/cl_parse.c b/cl_parse.c index 608b3ef8..bcb3a511 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -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; diff --git a/cl_particles.c b/cl_particles.c index d092dc3c..c858654d 100644 --- a/cl_particles.c +++ b/cl_particles.c @@ -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 } diff --git a/cl_video.c b/cl_video.c index 857d5d8f..ba88b34f 100644 --- a/cl_video.c +++ b/cl_video.c @@ -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) diff --git a/gl_backend.c b/gl_backend.c index 65b2c4a1..c9d9ec8a 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -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"}; diff --git a/gl_draw.c b/gl_draw.c index c3ade96d..c18954bc 100644 --- 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; } diff --git a/gl_models.c b/gl_models.c index c5c4c712..4126c63a 100644 --- a/gl_models.c +++ b/gl_models.c @@ -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) diff --git a/gl_rsurf.c b/gl_rsurf.c index aa5c4055..a587d658 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -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); } } } diff --git a/gl_textures.c b/gl_textures.c index aa421f91..a502f81a 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -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) diff --git a/glquake.h b/glquake.h index 182e43e7..f68e815f 100644 --- 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 d78d1f5e..dce3b365 100644 --- 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 c73d48ac..5ff67384 100644 --- 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 fe2e8d94..879761a0 100644 --- 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); } diff --git a/model_alias.c b/model_alias.c index 9b624025..112df181 100644 --- a/model_alias.c +++ b/model_alias.c @@ -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)); } { diff --git a/model_brush.c b/model_brush.c index d5fe31f9..665483c2 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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); diff --git a/model_brush.h b/model_brush.h index c2eed625..3d031e73 100644 --- a/model_brush.h +++ b/model_brush.h @@ -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]; diff --git a/model_shared.c b/model_shared.c index 8c7342a8..10d37620 100644 --- a/model_shared.c +++ b/model_shared.c @@ -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); diff --git a/model_shared.h b/model_shared.h index 0523fb3b..f013bb28 100644 --- a/model_shared.h +++ b/model_shared.h @@ -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; diff --git a/model_sprite.c b/model_sprite.c index 0d96a24b..732b8c63 100644 --- a/model_sprite.c +++ b/model_sprite.c @@ -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) { diff --git a/palette.c b/palette.c index c7dd2e85..7dbc82f0 100644 --- 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]; } diff --git a/palette.h b/palette.h index 8013e989..e1dcfda4 100644 --- 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; diff --git a/quakedef.h b/quakedef.h index 86529c7e..dc1be096 100644 --- a/quakedef.h +++ b/quakedef.h @@ -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); diff --git a/r_crosshairs.c b/r_crosshairs.c index 7e7bf706..e660f087 100644 --- a/r_crosshairs.c +++ b/r_crosshairs.c @@ -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 diff --git a/r_explosion.c b/r_explosion.c index 168a9ff3..aa08b1bf 100644 --- a/r_explosion.c +++ b/r_explosion.c @@ -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 } diff --git a/r_light.c b/r_light.c index b33418c2..e233ff7e 100644 --- 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) diff --git a/r_shadow.c b/r_shadow.c index eca072c4..f648a5e5 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -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 6f1cb06a..63f2820c 100644 --- 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) diff --git a/r_textures.h b/r_textures.h index 48f62201..5cf3753d 100644 --- a/r_textures.h +++ b/r_textures.h @@ -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); diff --git a/render.h b/render.h index fdeb233e..7ca8cfc7 100644 --- 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 de556faf..77fd4586 100644 --- 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; diff --git a/vid_shared.c b/vid_shared.c index 00c94858..6d59a927 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -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}, -- 2.39.2