From: havoc Date: Sun, 22 Dec 2002 22:56:09 +0000 (+0000) Subject: unified model skinframe loaders used for mdl, md2, md3, and bsp textures (both extern... X-Git-Tag: RELEASE_0_2_0_RC1~26 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=aee09d1c9af512a6dd365ae572464a4df0223207;p=xonotic%2Fdarkplaces.git unified model skinframe loaders used for mdl, md2, md3, and bsp textures (both external and internal where applicable) imageskin_t and image_loadskin/image_freeskin functions added to image.[ch] for use by the unified skinframe loaders added palette_nocolormap split r_shadow_bumpscale cvar into r_shadow_bumpscale_bumpmap (for _bump textures) and r_shadow_bumpscale_basetexture (self explanatory) now loads _norm normalmap textures (tenebrae compatibility) _nmap normalmap texture support removed (it was broken in the previous release and I don't need to bog down the texture loader with even more unnecessary names) r_shadow_lightattenuationpower added (default 2, to leave it looking identical to previous versions, this controls the falloff curve of light) renamed detailtextures array to mod_shared_detailtextures and moved it and related code to model_shared.[ch] removed progs/missile.mdl shadow casting check (in r_shadow_realtime mode) I had forgotten to remove before committing last time git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2682 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/gl_rmain.c b/gl_rmain.c index bedc8b8d..902a06de 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -915,7 +915,7 @@ void R_ShadowVolumeLighting (int visiblevolumes) for (i = 0;i < r_refdef.numentities;i++) { ent = r_refdef.entities[i]; - if (ent->model && !strcmp(ent->model->name, "progs/missile.mdl")) + if (ent->model) R_TestAndDrawShadowVolume(ent, wl->origin, cullradius, lightradius, wl->mins, wl->maxs, clipmins, clipmaxs); } } diff --git a/gl_rsurf.c b/gl_rsurf.c index 0c0c77a6..61ea4d01 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -817,7 +817,7 @@ static void RSurfShader_Water_Callback(const void *calldata1, int calldata2) m.blendfunc1 = GL_ONE; m.blendfunc2 = GL_ZERO; } - m.tex[0] = R_GetTexture(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; if (gl_combine.integer) { @@ -856,7 +856,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(texture->fogtexture); + m.tex[0] = R_GetTexture(texture->skin.fog); R_Mesh_State(&m); for (mesh = surf->mesh;mesh;mesh = mesh->chain) { @@ -915,7 +915,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(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; if (gl_combine.integer) { @@ -952,7 +952,7 @@ static void RSurfShader_Wall_Pass_Glow(const entity_render_t *ent, const msurfac memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(texture->glowtexture); + m.tex[0] = R_GetTexture(texture->skin.glow); R_Mesh_State(&m); GL_UseColorArray(); for (mesh = surf->mesh;mesh;mesh = mesh->chain) @@ -974,7 +974,7 @@ static void RSurfShader_Wall_Pass_Fog(const entity_render_t *ent, const msurface memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(texture->fogtexture); + m.tex[0] = R_GetTexture(texture->skin.fog); R_Mesh_State(&m); GL_UseColorArray(); for (mesh = surf->mesh;mesh;mesh = mesh->chain) @@ -998,9 +998,9 @@ static void RSurfShader_OpaqueWall_Pass_BaseTripleTexCombine(const entity_render memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_ONE; m.blendfunc2 = GL_ZERO; - m.tex[0] = R_GetTexture(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); m.tex[1] = R_GetTexture((**surfchain).lightmaptexture); - m.tex[2] = R_GetTexture(texture->detailtexture); + m.tex[2] = R_GetTexture(texture->skin.detail); m.texrgbscale[0] = 1; m.texrgbscale[1] = 4; m.texrgbscale[2] = 2; @@ -1039,7 +1039,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDoubleTex(const entity_render_t *ent memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_ONE; m.blendfunc2 = GL_ZERO; - m.tex[0] = R_GetTexture(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); m.tex[1] = R_GetTexture((**surfchain).lightmaptexture); if (gl_combine.integer) m.texrgbscale[1] = 4; @@ -1075,7 +1075,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseTexture(const entity_render_t *ent, memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_ONE; m.blendfunc2 = GL_ZERO; - m.tex[0] = R_GetTexture(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); R_Mesh_State(&m); GL_Color(1, 1, 1, 1); while((surf = *surfchain++) != NULL) @@ -1138,7 +1138,7 @@ static void RSurfShader_OpaqueWall_Pass_Light(const entity_render_t *ent, const memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(texture->texture); + m.tex[0] = R_GetTexture(texture->skin.base); colorscale = r_colorscale; if (gl_combine.integer) { @@ -1205,7 +1205,7 @@ static void RSurfShader_OpaqueWall_Pass_BaseDetail(const entity_render_t *ent, c memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_DST_COLOR; m.blendfunc2 = GL_SRC_COLOR; - m.tex[0] = R_GetTexture(texture->detailtexture); + m.tex[0] = R_GetTexture(texture->skin.detail); R_Mesh_State(&m); GL_Color(1, 1, 1, 1); while((surf = *surfchain++) != NULL) @@ -1231,7 +1231,7 @@ static void RSurfShader_OpaqueWall_Pass_Glow(const entity_render_t *ent, const t memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ONE; - m.tex[0] = R_GetTexture(texture->glowtexture); + m.tex[0] = R_GetTexture(texture->skin.glow); R_Mesh_State(&m); GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); while((surf = *surfchain++) != NULL) @@ -1257,7 +1257,7 @@ static void RSurfShader_OpaqueWall_Pass_OpaqueGlow(const entity_render_t *ent, c memset(&m, 0, sizeof(m)); m.blendfunc1 = GL_SRC_ALPHA; m.blendfunc2 = GL_ZERO; - m.tex[0] = R_GetTexture(texture->glowtexture); + m.tex[0] = R_GetTexture(texture->skin.glow); R_Mesh_State(&m); if (m.tex[0]) GL_Color(r_colorscale, r_colorscale, r_colorscale, 1); @@ -1296,13 +1296,13 @@ static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata currentalpha *= r_wateralpha.value; if (ent->effects & EF_ADDITIVE) rendertype = SURFRENDER_ADD; - else if (currentalpha < 1 || texture->fogtexture != NULL) + else if (currentalpha < 1 || texture->skin.fog != NULL) rendertype = SURFRENDER_ALPHA; else rendertype = SURFRENDER_OPAQUE; RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, rendertype, currentalpha); - if (texture->glowtexture) + if (texture->skin.glow) RSurfShader_Wall_Pass_Glow(ent, surf, texture, rendertype, currentalpha); if (fogenabled) RSurfShader_Wall_Pass_Fog(ent, surf, texture, rendertype, currentalpha); @@ -1338,7 +1338,7 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_ for (chain = surfchain;(surf = *chain) != NULL;chain++) if (surf->visframe == r_framecount) RSurfShader_Wall_Pass_BaseVertex(ent, surf, texture, texture->rendertype, texture->currentalpha); - if (texture->glowtexture) + if (texture->skin.glow) for (chain = surfchain;(surf = *chain) != NULL;chain++) if (surf->visframe == r_framecount) RSurfShader_Wall_Pass_Glow(ent, surf, texture, texture->rendertype, texture->currentalpha); @@ -1370,7 +1370,7 @@ static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const texture_ } if (!r_dlightmap.integer && !(ent->effects & EF_FULLBRIGHT)) RSurfShader_OpaqueWall_Pass_Light(ent, texture, surfchain); - if (texture->glowtexture) + if (texture->skin.glow) RSurfShader_OpaqueWall_Pass_Glow(ent, texture, surfchain); if (fogenabled) RSurfShader_OpaqueWall_Pass_Fog(ent, texture, surfchain); @@ -1407,7 +1407,7 @@ void R_UpdateTextureInfo(entity_render_t *ent) t->currentalpha *= r_wateralpha.value; if (ent->effects & EF_ADDITIVE) t->rendertype = SURFRENDER_ADD; - else if (t->currentalpha < 1 || t->fogtexture != NULL) + else if (t->currentalpha < 1 || t->skin.fog != NULL) t->rendertype = SURFRENDER_ALPHA; else t->rendertype = SURFRENDER_OPAQUE; @@ -1846,8 +1846,8 @@ void R_Model_Brush_DrawLightForSurfaceList(entity_render_t *ent, vec3_t relative { R_Mesh_ResizeCheck(mesh->numverts); memcpy(varray_vertex, mesh->verts, mesh->numverts * sizeof(float[4])); - R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL); + R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL); + R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL); } } } @@ -1891,8 +1891,8 @@ 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_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL); + R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL); + R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL); } } } @@ -1924,8 +1924,8 @@ 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_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->texture, t->nmaptexture, NULL); - R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->glosstexture, t->nmaptexture, NULL); + R_Shadow_DiffuseLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, lightradius, lightcolor, t->skin.base, t->skin.nmap, NULL); + R_Shadow_SpecularLighting(mesh->numverts, mesh->numtriangles, mesh->index, mesh->svectors, mesh->tvectors, mesh->normals, mesh->str, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, t->skin.gloss, t->skin.nmap, NULL); } } } diff --git a/image.c b/image.c index 8bb3d4d7..c26befb4 100644 --- a/image.c +++ b/image.c @@ -2,6 +2,7 @@ #include "quakedef.h" #include "image.h" #include "jpeg.h" +#include "r_shadow.h" int image_width; int image_height; @@ -1347,7 +1348,6 @@ void Image_MipReduce(const qbyte *in, qbyte *out, int *width, int *height, int * } } -extern cvar_t r_shadow_bumpscale; void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *outpixels, int width, int height, int clamp, float bumpscale) { int x, y; @@ -1356,7 +1356,7 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou float iwidth, iheight, ibumpscale, n[3]; iwidth = 1.0f / width; iheight = 1.0f / height; - ibumpscale = (255.0f * 3.0f) / (bumpscale * r_shadow_bumpscale.value); + ibumpscale = (255.0f * 3.0f) / bumpscale; out = outpixels; for (y = 0;y < height;y++) { @@ -1404,3 +1404,113 @@ void Image_HeightmapToNormalmap(const unsigned char *inpixels, unsigned char *ou } } } + +int image_loadskin(imageskin_t *s, char *name) +{ + int j; + qbyte *bumppixels; + int bumppixels_width, bumppixels_height; + memset(s, 0, sizeof(*s)); + s->basepixels = loadimagepixels(name, false, 0, 0); + if (s->basepixels == NULL) + return false; + + bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0; + for (j = 3;j < s->basepixels_width * s->basepixels_height * 4;j += 4) + if (s->basepixels[j] < 255) + break; + if (j < s->basepixels_width * s->basepixels_height * 4) + { + s->maskpixels = Mem_Alloc(loadmodel->mempool, s->basepixels_width * s->basepixels_height * 4); + s->maskpixels_width = s->basepixels_width; + s->maskpixels_height = s->basepixels_height; + memcpy(s->maskpixels, s->basepixels, s->maskpixels_width * s->maskpixels_height * 4); + for (j = 0;j < s->basepixels_width * s->basepixels_height * 4;j += 4) + { + s->maskpixels[j+0] = 255; + s->maskpixels[j+1] = 255; + s->maskpixels[j+2] = 255; + } + } + + // _luma is supported for tenebrae compatibility + // (I think it's a very stupid name, but oh well) + if ((s->glowpixels = loadimagepixels(va("%s_glow", name), false, 0, 0)) != NULL + || (s->glowpixels = loadimagepixels(va("%s_luma", name), false, 0, 0)) != NULL) + { + s->glowpixels_width = image_width; + s->glowpixels_height = image_height; + } + // _norm is the name used by tenebrae + // (I don't like the name much) + if ((s->nmappixels = loadimagepixels(va("%s_norm", name), false, 0, 0)) != NULL) + { + s->nmappixels_width = image_width; + s->nmappixels_height = image_height; + } + else if ((bumppixels = loadimagepixels(va("%s_bump", name), false, 0, 0)) != NULL) + { + bumppixels_width = image_width; + bumppixels_height = image_height; + } + if ((s->glosspixels = loadimagepixels(va("%s_gloss", name), false, 0, 0)) != NULL) + { + s->glosspixels_width = image_width; + s->glosspixels_height = image_height; + } + if ((s->pantspixels = loadimagepixels(va("%s_pants", name), false, 0, 0)) != NULL) + { + s->pantspixels_width = image_width; + s->pantspixels_height = image_height; + } + if ((s->shirtpixels = loadimagepixels(va("%s_shirt", name), false, 0, 0)) != NULL) + { + s->shirtpixels_width = image_width; + s->shirtpixels_height = image_height; + } + + if (s->nmappixels == NULL) + { + if (bumppixels != NULL) + { + if (r_shadow_bumpscale_bumpmap.value > 0) + { + s->nmappixels = Mem_Alloc(loadmodel->mempool, bumppixels_width * bumppixels_height * 4); + s->nmappixels_width = bumppixels_width; + s->nmappixels_height = bumppixels_height; + Image_HeightmapToNormalmap(bumppixels, s->nmappixels, s->nmappixels_width, s->nmappixels_height, false, r_shadow_bumpscale_bumpmap.value); + } + } + else + { + if (r_shadow_bumpscale_basetexture.value > 0) + { + s->nmappixels = Mem_Alloc(loadmodel->mempool, s->basepixels_width * s->basepixels_height * 4); + s->nmappixels_width = s->basepixels_width; + s->nmappixels_height = s->basepixels_height; + Image_HeightmapToNormalmap(s->basepixels, s->nmappixels, s->nmappixels_width, s->nmappixels_height, false, r_shadow_bumpscale_basetexture.value); + } + } + } + if (bumppixels != NULL) + Mem_Free(bumppixels); + return true; +} + +void image_freeskin(imageskin_t *s) +{ + if (s->basepixels) + Mem_Free(s->basepixels); + if (s->nmappixels) + Mem_Free(s->nmappixels); + if (s->glowpixels) + Mem_Free(s->glowpixels); + if (s->glosspixels) + Mem_Free(s->glosspixels); + if (s->pantspixels) + Mem_Free(s->pantspixels); + if (s->shirtpixels) + Mem_Free(s->shirtpixels); + memset(s, 0, sizeof(*s)); +} + diff --git a/image.h b/image.h index 2d26d29e..c2edabdd 100644 --- a/image.h +++ b/image.h @@ -53,5 +53,20 @@ 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); +typedef struct imageskin_s +{ + qbyte *basepixels;int basepixels_width;int basepixels_height; + qbyte *nmappixels;int nmappixels_width;int nmappixels_height; + qbyte *glowpixels;int glowpixels_width;int glowpixels_height; + qbyte *glosspixels;int glosspixels_width;int glosspixels_height; + qbyte *pantspixels;int pantspixels_width;int pantspixels_height; + qbyte *shirtpixels;int shirtpixels_width;int shirtpixels_height; + qbyte *maskpixels;int maskpixels_width;int maskpixels_height; +} +imageskin_t; + +int image_loadskin(imageskin_t *s, char *name); +void image_freeskin(imageskin_t *s); + #endif diff --git a/model_alias.c b/model_alias.c index 53a13958..49126380 100644 --- a/model_alias.c +++ b/model_alias.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "image.h" +#include "r_shadow.h" static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"}; @@ -177,72 +178,6 @@ static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, int outverts, v Mem_Free(vertexbuffer); } -static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int precache) -{ - 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->nmap = loadtextureimage(loadmodel->texturepool, va("%s_nmap" , basename), 0, 0, false, (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - if (skinframe->nmap == NULL) - skinframe->nmap = loadtextureimagebumpasnmap(loadmodel->texturepool, va("%s_bump" , basename), 0, 0, false, (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0), 1); - if (skinframe->nmap != NULL) - { - skinframe->base = loadtextureimagewithmask(loadmodel->texturepool, va("%s_normal", basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - if (skinframe->base == NULL) - skinframe->base = loadtextureimagewithmask(loadmodel->texturepool, basename, 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->fog = image_masktex; - } - else - { - 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 == NULL) - 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)); - if (skinframe->glow == NULL) - skinframe->glow = loadtextureimage(loadmodel->texturepool, va("%s_luma" , basename), 0, 0, false, TEXF_ALPHA | (precache ? TEXF_PRECACHE : 0) | (r_mipskins.integer ? TEXF_MIPMAP : 0)); - skinframe->merged = skinframe->base; - return skinframe->base != NULL || skinframe->pants != NULL || skinframe->shirt != NULL || skinframe->glow != NULL; -} - -static int Mod_LoadInternalSkin (char *basename, qbyte *skindata, int width, int height, skinframe_t *skinframe, int precache) -{ - qbyte *temp1, *temp2; - if (!skindata) - return false; - 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_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_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; -} - void Mod_BuildAliasSkinFromSkinFrame(aliasskin_t *skin, skinframe_t *skinframe) { aliaslayer_t *layer; @@ -528,8 +463,8 @@ void Mod_LoadQ1AliasModel (model_t *mod, void *buffer) sprintf (name, "%s_%i_%i", loadmodel->name, i, j); else sprintf (name, "%s_%i", loadmodel->name, i); - if (!Mod_LoadExternalSkin(name, loadmodel->skinframes + totalskins, i == 0)) - Mod_LoadInternalSkin(name, (qbyte *)datapointer, skinwidth, skinheight, loadmodel->skinframes + totalskins, i == 0); + if (!Mod_LoadSkinFrame(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true)) + Mod_LoadSkinFrame_Internal(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true, (qbyte *)datapointer, skinwidth, skinheight); datapointer += skinwidth * skinheight; totalskins++; } @@ -539,7 +474,7 @@ void Mod_LoadQ1AliasModel (model_t *mod, void *buffer) for (;;) { sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins); - if (Mod_LoadExternalSkin(name, &tempskinframe, loadmodel->numskins == 0)) + if (Mod_LoadSkinFrame (&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true)) { // expand the arrays to make room tempskinscenes = loadmodel->skinscenes; @@ -725,7 +660,7 @@ void Mod_LoadQ2AliasModel (model_t *mod, void *buffer) loadmodel->skinscenes[i].framecount = 1; loadmodel->skinscenes[i].loop = true; loadmodel->skinscenes[i].framerate = 10; - Mod_LoadExternalSkin (inskin, loadmodel->skinframes + i, true); + Mod_LoadSkinFrame (loadmodel->skinframes + i, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true); inskin += MD2MAX_SKINNAME; } } @@ -934,7 +869,7 @@ void Mod_LoadQ3AliasModel(model_t *mod, void *buffer) memset(&tempskinframe, 0, sizeof(tempskinframe)); if (LittleLong(pinmesh->num_shaders) >= 1 && ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name[0]) - Mod_LoadExternalSkin (((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, &tempskinframe, true); + Mod_LoadSkinFrame (&tempskinframe, ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true); Mod_ValidateElements(mesh->data_elements, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__); Mod_BuildTriangleNeighbors(mesh->data_neighbors, mesh->data_elements, mesh->num_triangles); Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins, &tempskinframe); @@ -1040,12 +975,6 @@ void Mod_LoadZymoticModel(model_t *mod, void *buffer) loadmodel->skinscenes[0].loop = true; loadmodel->skinscenes[0].framerate = 10; loadmodel->skinframes = (void *)(loadmodel->skinscenes + 1); - loadmodel->skinframes->base = NULL; - loadmodel->skinframes->fog = NULL; - loadmodel->skinframes->pants = NULL; - loadmodel->skinframes->shirt = NULL; - loadmodel->skinframes->glow = NULL; - loadmodel->skinframes->merged = NULL; loadmodel->numskins = 1; } diff --git a/model_brush.c b/model_brush.c index 4959d8c3..6e7c54f5 100644 --- a/model_brush.c +++ b/model_brush.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "image.h" +#include "r_shadow.h" // note: model_shared.c sets up r_notexture, and r_surf_notexture @@ -33,10 +34,6 @@ cvar_t r_lightmaprgba = {0, "r_lightmaprgba", "1"}; cvar_t r_nosurftextures = {0, "r_nosurftextures", "0"}; cvar_t r_sortsurfaces = {0, "r_sortsurfaces", "0"}; -#define NUM_DETAILTEXTURES 1 -static rtexture_t *detailtextures[NUM_DETAILTEXTURES]; -static rtexturepool_t *detailtexturepool; - /* =============== Mod_BrushInit @@ -54,55 +51,6 @@ void Mod_BrushInit (void) memset(mod_novis, 0xff, sizeof(mod_novis)); } -void Mod_BrushStartup (void) -{ - int i, x, y, light; - float vc[3], vx[3], vy[3], vn[3], lightdir[3]; -#define DETAILRESOLUTION 256 - qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION]; - detailtexturepool = R_AllocTexturePool(); - lightdir[0] = 0.5; - lightdir[1] = 1; - lightdir[2] = -0.25; - VectorNormalize(lightdir); - for (i = 0;i < NUM_DETAILTEXTURES;i++) - { - fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4); - for (y = 0;y < DETAILRESOLUTION;y++) - { - for (x = 0;x < DETAILRESOLUTION;x++) - { - vc[0] = x; - vc[1] = y; - vc[2] = noise[y][x] * (1.0f / 32.0f); - vx[0] = x + 1; - vx[1] = y; - vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f); - vy[0] = x; - vy[1] = y + 1; - vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f); - VectorSubtract(vx, vc, vx); - VectorSubtract(vy, vc, vy); - CrossProduct(vx, vy, vn); - VectorNormalize(vn); - light = 128 - DotProduct(vn, lightdir) * 128; - light = bound(0, light, 255); - data[y][x][0] = data[y][x][1] = data[y][x][2] = light; - data[y][x][3] = 255; - } - } - detailtextures[i] = R_LoadTexture2D(detailtexturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL); - } -} - -void Mod_BrushShutdown (void) -{ - int i; - for (i = 0;i < NUM_DETAILTEXTURES;i++) - R_FreeTexture(detailtextures[i]); - R_FreeTexturePool(&detailtexturepool); -} - /* =============== Mod_PointInLeaf @@ -214,11 +162,6 @@ static void Mod_LoadTextures (lump_t *l) dmiptexlump_t *m; 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; @@ -237,9 +180,10 @@ static void Mod_LoadTextures (lump_t *l) for (i = 0, tx = loadmodel->textures;i < loadmodel->numtextures;i++, tx++) { tx->number = i; + strcpy(tx->name, "NO TEXTURE FOUND"); tx->width = 16; tx->height = 16; - tx->texture = r_notexture; + tx->skin.base = r_notexture; tx->shader = &Cshader_wall_lightmap; if (i == loadmodel->numtextures - 1) { @@ -298,14 +242,6 @@ static void Mod_LoadTextures (lump_t *l) Con_Printf("warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); } - basepixels = NULL;basepixels_width = 0;basepixels_height = 0; - bumppixels = NULL;bumppixels_width = 0;bumppixels_height = 0; - nmappixels = NULL;nmappixels_width = 0;nmappixels_height = 0; - glosspixels = NULL;glosspixels_width = 0;glosspixels_height = 0; - glowpixels = NULL;glowpixels_width = 0;glowpixels_height = 0; - maskpixels = NULL;maskpixels_width = 0;maskpixels_height = 0; - detailtexture = NULL; - // LordHavoc: HL sky textures are entirely different than quake if (!loadmodel->ishlbsp && !strncmp(tx->name, "sky", 3) && mtwidth == 256 && mtheight == 128) { @@ -333,159 +269,38 @@ static void Mod_LoadTextures (lump_t *l) } else { - if ((basepixels = loadimagepixels(tx->name, false, 0, 0)) != NULL) - { - basepixels_width = image_width; - basepixels_height = image_height; - } - // _luma is supported for tenebrae compatibility - // (I think it's a very stupid name, but oh well) - if ((glowpixels = loadimagepixels(va("%s_glow", tx->name), false, 0, 0)) != NULL - || (glowpixels = loadimagepixels(va("%s_luma", tx->name), false, 0, 0)) != NULL) - { - glowpixels_width = image_width; - glowpixels_height = image_height; - } - if ((bumppixels = loadimagepixels(va("%s_bump", tx->name), false, 0, 0)) != NULL) - { - bumppixels_width = image_width; - bumppixels_height = image_height; - } - if ((glosspixels = loadimagepixels(va("%s_gloss", tx->name), false, 0, 0)) != NULL) - { - glosspixels_width = image_width; - glosspixels_height = image_height; - } - if (!basepixels) + if (!Mod_LoadSkinFrame(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, true)) { + // did not find external texture, load it from the bsp or wad3 if (loadmodel->ishlbsp) { // internal texture overrides wad - if (mtdata && (basepixels = W_ConvertWAD3Texture(dmiptex)) != NULL) - { - basepixels_width = image_width; - basepixels_height = image_height; - } - else if ((basepixels = W_GetTexture(tx->name)) != NULL) - { - // get the size from the wad texture - tx->width = basepixels_width = image_width; - tx->height = basepixels_height = image_height; - } - } - else - { - if (mtdata) // texture included + qbyte *pixels, *freepixels; + pixels = freepixels = NULL; + if (mtdata) + pixels = W_ConvertWAD3Texture(dmiptex); + if (pixels == NULL) + pixels = freepixels = W_GetTexture(tx->name); + if (pixels != NULL) { - if (r_fullbrights.integer && tx->name[0] != '*') - { - 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); - if (!glowpixels) - { - for (j = 0;j < (int)(tx->width*tx->height);j++) - if (((qbyte *)&palette_onlyfullbrights[mtdata[j]])[3] > 0) // fullbright - break; - if (j < (int)(tx->width * tx->height)) - { - 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); - } + tx->width = image_width; + tx->height = image_height; + tx->skin.base = tx->skin.merged = R_LoadTexture2D(loadmodel->texturepool, tx->name, image_width, image_height, pixels, TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, NULL); } + if (freepixels) + Mem_Free(freepixels); } + else if (mtdata) // texture included + Mod_LoadSkinFrame_Internal(&tx->skin, tx->name, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE, false, true, tx->name[0] != '*' && r_fullbrights.integer, mtdata, tx->width, tx->height); } } - - 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) - { - 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, nmappixels, 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 + if (tx->skin.base == NULL) { // 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); + tx->skin.base = r_notexture; + } if (tx->name[0] == '*') { @@ -507,7 +322,7 @@ static void Mod_LoadTextures (lump_t *l) else { tx->flags |= SURF_LIGHTMAP; - if (!tx->fogtexture) + if (!tx->skin.fog) tx->flags |= SURF_SHADOWCAST | SURF_SHADOWLIGHT; tx->shader = &Cshader_wall_lightmap; } diff --git a/model_brush.h b/model_brush.h index 7596a39f..4dfa594f 100644 --- a/model_brush.h +++ b/model_brush.h @@ -106,18 +106,8 @@ typedef struct texture_s // type of rendering (SURFRENDER_ value) int rendertype; - // base texture without fullbrights, never NULL - rtexture_t *texture; - // fullbrights texture, NULL if no fullbrights used - rtexture_t *glowtexture; - // alpha texture (used for fogging), NULL if opaque - 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; + // loaded the same as model skins + skinframe_t skin; // shader to use for this texture Cshader_t *shader; diff --git a/model_shared.c b/model_shared.c index c269469c..5bec6c22 100644 --- a/model_shared.c +++ b/model_shared.c @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // on the same machine. #include "quakedef.h" +#include "image.h" +#include "r_shadow.h" model_t *loadmodel; @@ -30,8 +32,49 @@ model_t *loadmodel; #define MAX_MOD_KNOWN 2048 static model_t mod_known[MAX_MOD_KNOWN]; +rtexturepool_t *mod_shared_texturepool; rtexture_t *r_notexture; -rtexturepool_t *r_notexturepool; +rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES]; + +void Mod_BuildDetailTextures (void) +{ + int i, x, y, light; + float vc[3], vx[3], vy[3], vn[3], lightdir[3]; +#define DETAILRESOLUTION 256 + qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION]; + lightdir[0] = 0.5; + lightdir[1] = 1; + lightdir[2] = -0.25; + VectorNormalize(lightdir); + for (i = 0;i < NUM_DETAILTEXTURES;i++) + { + fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4); + for (y = 0;y < DETAILRESOLUTION;y++) + { + for (x = 0;x < DETAILRESOLUTION;x++) + { + vc[0] = x; + vc[1] = y; + vc[2] = noise[y][x] * (1.0f / 32.0f); + vx[0] = x + 1; + vx[1] = y; + vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f); + vy[0] = x; + vy[1] = y + 1; + vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f); + VectorSubtract(vx, vc, vx); + VectorSubtract(vy, vc, vy); + CrossProduct(vx, vy, vn); + VectorNormalize(vn); + light = 128 - DotProduct(vn, lightdir) * 128; + light = bound(0, light, 255); + data[y][x][0] = data[y][x][1] = data[y][x][2] = light; + data[y][x][3] = 255; + } + } + mod_shared_detailtextures[i] = R_LoadTexture2D(mod_shared_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL); + } +} texture_t r_surf_notexture; @@ -62,13 +105,9 @@ void Mod_SetupNoTexture(void) } } - r_notexturepool = R_AllocTexturePool(); - r_notexture = R_LoadTexture2D(r_notexturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL); + r_notexture = R_LoadTexture2D(mod_shared_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL); } -extern void Mod_BrushStartup (void); -extern void Mod_BrushShutdown (void); - static void mod_start(void) { int i; @@ -77,8 +116,9 @@ static void mod_start(void) Mod_UnloadModel(&mod_known[i]); Mod_LoadModels(); + mod_shared_texturepool = R_AllocTexturePool(); Mod_SetupNoTexture(); - Mod_BrushStartup(); + Mod_BuildDetailTextures(); } static void mod_shutdown(void) @@ -88,8 +128,7 @@ static void mod_shutdown(void) if (mod_known[i].name[0]) Mod_UnloadModel(&mod_known[i]); - R_FreeTexturePool(&r_notexturepool); - Mod_BrushShutdown(); + R_FreeTexturePool(&mod_shared_texturepool); } static void mod_newmap(void) @@ -731,3 +770,84 @@ void Mod_ShadowMesh_Free(shadowmesh_t *mesh) Mem_Free(mesh); } } + +static rtexture_t *GL_TextureForSkinLayer(const qbyte *in, int width, int height, const char *name, const unsigned int *palette, int textureflags) +{ + 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, textureflags, palette); + return NULL; +} + +static int detailtexturecycle = 0; +int Mod_LoadSkinFrame (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture) +{ + imageskin_t s; + memset(skinframe, 0, sizeof(*skinframe)); + if (!image_loadskin(&s, basename)) + return false; + if (usedetailtexture) + skinframe->detail = mod_shared_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES]; + skinframe->base = R_LoadTexture2D (loadmodel->texturepool, basename, s.basepixels_width, s.basepixels_height, s.basepixels, TEXTYPE_RGBA, textureflags, NULL); + if (s.nmappixels != NULL) + skinframe->nmap = R_LoadTexture2D (loadmodel->texturepool, va("%s_nmap", basename), s.basepixels_width, s.basepixels_height, s.nmappixels, TEXTYPE_RGBA, textureflags, NULL); + if (s.glosspixels != NULL) + skinframe->gloss = R_LoadTexture2D (loadmodel->texturepool, va("%s_gloss", basename), s.glosspixels_width, s.glosspixels_height, s.glosspixels, TEXTYPE_RGBA, textureflags, NULL); + if (s.glowpixels != NULL && loadglowtexture) + skinframe->glow = R_LoadTexture2D (loadmodel->texturepool, va("%s_glow", basename), s.glowpixels_width, s.glowpixels_height, s.glowpixels, TEXTYPE_RGBA, textureflags, NULL); + if (s.maskpixels != NULL) + skinframe->fog = R_LoadTexture2D (loadmodel->texturepool, va("%s_mask", basename), s.maskpixels_width, s.maskpixels_height, s.maskpixels, TEXTYPE_RGBA, textureflags, NULL); + if (loadpantsandshirt) + { + if (s.pantspixels != NULL) + skinframe->pants = R_LoadTexture2D (loadmodel->texturepool, va("%s_pants", basename), s.pantspixels_width, s.pantspixels_height, s.pantspixels, TEXTYPE_RGBA, textureflags, NULL); + if (s.shirtpixels != NULL) + skinframe->shirt = R_LoadTexture2D (loadmodel->texturepool, va("%s_shirt", basename), s.shirtpixels_width, s.shirtpixels_height, s.shirtpixels, TEXTYPE_RGBA, textureflags, NULL); + } + image_freeskin(&s); + return true; +} + +int Mod_LoadSkinFrame_Internal (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture, qbyte *skindata, int width, int height) +{ + qbyte *temp1, *temp2; + memset(skinframe, 0, sizeof(*skinframe)); + if (!skindata) + return false; + if (usedetailtexture) + skinframe->detail = mod_shared_detailtextures[(detailtexturecycle++) % NUM_DETAILTEXTURES]; + if (r_shadow_bumpscale_basetexture.value > 0) + { + 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, r_shadow_bumpscale_basetexture.value); + skinframe->nmap = R_LoadTexture2D(loadmodel->texturepool, va("%s_nmap", basename), width, height, temp2, TEXTYPE_RGBA, textureflags, NULL); + Mem_Free(temp1); + } + if (loadglowtexture) + { + skinframe->glow = GL_TextureForSkinLayer(skindata, width, height, va("%s_glow", basename), palette_onlyfullbrights, textureflags); // glow + skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette_nofullbrights, textureflags); // all but fullbrights + if (loadpantsandshirt) + { + skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants + skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt + if (skinframe->pants || skinframe->shirt) + skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename), palette_nocolormapnofullbrights, textureflags); // no special colors + } + } + else + { + skinframe->base = skinframe->merged = GL_TextureForSkinLayer(skindata, width, height, va("%s_merged", basename), palette_complete, textureflags); // all but fullbrights + if (loadpantsandshirt) + { + skinframe->pants = GL_TextureForSkinLayer(skindata, width, height, va("%s_pants", basename), palette_pantsaswhite, textureflags); // pants + skinframe->shirt = GL_TextureForSkinLayer(skindata, width, height, va("%s_shirt", basename), palette_shirtaswhite, textureflags); // shirt + if (skinframe->pants || skinframe->shirt) + skinframe->base = GL_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", basename), palette_nocolormap, textureflags); // no pants or shirt + } + } + return true; +} diff --git a/model_shared.h b/model_shared.h index 3740fc5c..0c6578d1 100644 --- a/model_shared.h +++ b/model_shared.h @@ -47,14 +47,15 @@ animscene_t; typedef struct skinframe_s { - rtexture_t *base; // original texture minus pants/shirt/glow + rtexture_t *base; // original texture without pants/shirt/glow rtexture_t *pants; // pants only (in greyscale) rtexture_t *shirt; // shirt only (in greyscale) - 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 *glow; // glow only (fullbrights) + rtexture_t *merged; // original texture without glow + rtexture_t *fog; // alpha of the base texture (if not opaque) rtexture_t *nmap; // normalmap (bumpmap for dot3) rtexture_t *gloss; // glossmap (for dot3) + rtexture_t *detail; // detail texture (silly bumps for non-dot3) } skinframe_t; @@ -274,8 +275,10 @@ model_t; // this can be used for anything without a valid texture extern rtexture_t *r_notexture; +#define NUM_DETAILTEXTURES 1 +extern rtexture_t *mod_shared_detailtextures[NUM_DETAILTEXTURES]; // every texture must be in a pool... -extern rtexturepool_t *r_notexturepool; +extern rtexturepool_t *mod_shared_texturepool; // model loading extern model_t *loadmodel; @@ -317,5 +320,8 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh) void Mod_ShadowMesh_CalcBBox(shadowmesh_t *firstmesh, vec3_t mins, vec3_t maxs, vec3_t center, float *radius); void Mod_ShadowMesh_Free(shadowmesh_t *mesh); +int Mod_LoadSkinFrame (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture); +int Mod_LoadSkinFrame_Internal (skinframe_t *skinframe, char *basename, int textureflags, int loadpantsandshirt, int usedetailtexture, int loadglowtexture, qbyte *skindata, int width, int height); + #endif // __MODEL__ diff --git a/palette.c b/palette.c index 1978eefe..e6bf563c 100644 --- a/palette.c +++ b/palette.c @@ -5,6 +5,7 @@ unsigned int palette_complete[256]; unsigned int palette_nofullbrights[256]; unsigned int palette_onlyfullbrights[256]; unsigned int palette_nocolormapnofullbrights[256]; +unsigned int palette_nocolormap[256]; unsigned int palette_pantsaswhite[256]; unsigned int palette_shirtaswhite[256]; unsigned int palette_alpha[256]; @@ -77,6 +78,14 @@ void Palette_Setup8to24(void) palette_nocolormapnofullbrights[i] = palette_complete[0]; palette_nocolormapnofullbrights[255] = 0; + for (i = 0;i < 256;i++) + palette_nocolormap[i] = palette_complete[i]; + for (i = pants_start;i < pants_end;i++) + palette_nocolormap[i] = palette_complete[0]; + for (i = shirt_start;i < shirt_end;i++) + palette_nocolormap[i] = palette_complete[0]; + palette_nocolormap[255] = 0; + for (i = 0;i < 256;i++) palette_pantsaswhite[i] = palette_complete[0]; for (i = pants_start;i < pants_end;i++) diff --git a/palette.h b/palette.h index e1dcfda4..a0e97a97 100644 --- a/palette.h +++ b/palette.h @@ -12,6 +12,7 @@ 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_nocolormap[256]; extern unsigned int palette_pantsaswhite[256]; extern unsigned int palette_shirtaswhite[256]; extern unsigned int palette_alpha[256]; diff --git a/r_shadow.c b/r_shadow.c index fdbfc47a..f8a0e3de 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -29,13 +29,15 @@ rtexture_t *r_shadow_blankbumptexture; rtexture_t *r_shadow_blankglosstexture; rtexture_t *r_shadow_blankwhitetexture; +cvar_t r_shadow_lightattenuationpower = {0, "r_shadow_lightattenuationpower", "2"}; cvar_t r_shadow_lightattenuationscale = {0, "r_shadow_lightattenuationscale", "2"}; cvar_t r_shadow_lightintensityscale = {0, "r_shadow_lightintensityscale", "1"}; cvar_t r_shadow_realtime = {0, "r_shadow_realtime", "0"}; cvar_t r_shadow_gloss = {0, "r_shadow_gloss", "1"}; cvar_t r_shadow_debuglight = {0, "r_shadow_debuglight", "-1"}; cvar_t r_shadow_scissor = {0, "r_shadow_scissor", "1"}; -cvar_t r_shadow_bumpscale = {0, "r_shadow_bumpscale", "4"}; +cvar_t r_shadow_bumpscale_bumpmap = {0, "r_shadow_bumpscale_bumpmap", "4"}; +cvar_t r_shadow_bumpscale_basetexture = {0, "r_shadow_bumpscale_basetexture", "4"}; cvar_t r_shadow_shadownudge = {0, "r_shadow_shadownudge", "1"}; void R_Shadow_ClearWorldLights(void); @@ -87,13 +89,15 @@ void r_shadow_newmap(void) void R_Shadow_Init(void) { + Cvar_RegisterVariable(&r_shadow_lightattenuationpower); Cvar_RegisterVariable(&r_shadow_lightattenuationscale); Cvar_RegisterVariable(&r_shadow_lightintensityscale); Cvar_RegisterVariable(&r_shadow_realtime); Cvar_RegisterVariable(&r_shadow_gloss); Cvar_RegisterVariable(&r_shadow_debuglight); Cvar_RegisterVariable(&r_shadow_scissor); - Cvar_RegisterVariable(&r_shadow_bumpscale); + Cvar_RegisterVariable(&r_shadow_bumpscale_bumpmap); + Cvar_RegisterVariable(&r_shadow_bumpscale_basetexture); Cvar_RegisterVariable(&r_shadow_shadownudge); R_Shadow_EditLights_Init(); R_RegisterModule("R_Shadow", r_shadow_start, r_shadow_shutdown, r_shadow_newmap); @@ -345,7 +349,7 @@ void R_Shadow_RenderShadowMeshVolume(shadowmesh_t *firstmesh) } } -float r_shadow_atten1; +float r_shadow_attenpower, r_shadow_attenscale; static void R_Shadow_MakeTextures(void) { int x, y, d, side; @@ -353,7 +357,8 @@ static void R_Shadow_MakeTextures(void) qbyte *data; R_FreeTexturePool(&r_shadow_texturepool); r_shadow_texturepool = R_AllocTexturePool(); - r_shadow_atten1 = r_shadow_lightattenuationscale.value; + r_shadow_attenpower = r_shadow_lightattenuationpower.value; + r_shadow_attenscale = r_shadow_lightattenuationscale.value; data = Mem_Alloc(tempmempool, 6*128*128*4); data[0] = 128; data[1] = 128; @@ -429,8 +434,8 @@ static void R_Shadow_MakeTextures(void) v[2] = 0; intensity = 1.0f - sqrt(DotProduct(v, v)); if (intensity > 0) - intensity *= intensity; - intensity = bound(0, intensity * r_shadow_atten1 * 256.0f, 255.0f); + intensity = pow(intensity, r_shadow_attenpower); + intensity = bound(0, intensity * r_shadow_attenscale * 256.0f, 255.0f); d = bound(0, intensity, 255); data[((0*128+y)*128+x)*4+0] = d; data[((0*128+y)*128+x)*4+1] = d; @@ -448,7 +453,8 @@ void R_Shadow_Stage_Begin(void) //cl.worldmodel->numlights = min(cl.worldmodel->numlights, 1); if (!r_shadow_attenuation2dtexture - || r_shadow_lightattenuationscale.value != r_shadow_atten1) + || r_shadow_lightattenuationpower.value != r_shadow_attenpower + || r_shadow_lightattenuationscale.value != r_shadow_attenscale) R_Shadow_MakeTextures(); if (r_shadow_reloadlights && cl.worldmodel) { diff --git a/r_shadow.h b/r_shadow.h index 8b97e421..96480aa9 100644 --- a/r_shadow.h +++ b/r_shadow.h @@ -7,6 +7,8 @@ extern cvar_t r_shadow_lightintensityscale; extern cvar_t r_shadow_realtime; extern cvar_t r_shadow_gloss; extern cvar_t r_shadow_debuglight; +extern cvar_t r_shadow_bumpscale_bumpmap; +extern cvar_t r_shadow_bumpscale_basetexture; void R_Shadow_Init(void); void R_Shadow_Volume(int numverts, int numtris, int *elements, int *neighbors, vec3_t relativelightorigin, float lightradius, float projectdistance);