From f8abac5d463a47ea89bbd0e7628e0fb6744e69d4 Mon Sep 17 00:00:00 2001 From: skyjake Date: Sat, 16 Aug 2003 21:36:33 +0000 Subject: [PATCH] Added lightmaps --- doomsday/Include/dd_defns.h | 1 + doomsday/Include/dedfile.h | 8 +- doomsday/Src/dd_defns.c | 41 +++++++++- doomsday/Src/dedread.c | 8 +- doomsday/Src/gl_tex.c | 155 +++++++++++++++++++++++++++++++++++- doomsday/Src/rend_decor.c | 17 ++-- doomsday/Src/rend_dyn.c | 21 ++++- 7 files changed, 228 insertions(+), 23 deletions(-) diff --git a/doomsday/Include/dd_defns.h b/doomsday/Include/dd_defns.h index f379c286a4..707dc55095 100644 --- a/doomsday/Include/dd_defns.h +++ b/doomsday/Include/dd_defns.h @@ -65,5 +65,6 @@ ded_light_t *Def_GetLightDef(int spr, int frame); ded_decor_t *Def_GetDecoration(int number, boolean is_texture, boolean has_ext); int Def_Get(int type, char *id, void *out); boolean Def_SameStateSequence(state_t *snew, state_t *sold); +void Def_LightMapLoaded(const char *id, unsigned int texture); #endif \ No newline at end of file diff --git a/doomsday/Include/dedfile.h b/doomsday/Include/dedfile.h index 9b91199eea..2f9d4d413e 100644 --- a/doomsday/Include/dedfile.h +++ b/doomsday/Include/dedfile.h @@ -101,6 +101,11 @@ typedef struct int misc[NUM_STATE_MISC]; } ded_state_t; +typedef struct ded_lightmap_s { + ded_stringid_t id; + unsigned int tex; // Runtime +} ded_lightmap_t; + typedef struct { ded_stateid_t state; @@ -110,6 +115,7 @@ typedef struct float color[3]; // Red Green Blue (0,1) ded_flags_t flags_string; int flags; // Runtime + ded_lightmap_t up, down, sides; } ded_light_t; typedef struct @@ -366,7 +372,7 @@ typedef struct int pattern_skip[2]; int light_levels[2];// Fade by sector lightlevel. int flare_texture; - //ded_string_t texture; // DL map to use (later...). + ded_lightmap_t up, down, sides; } ded_decorlight_t; // There is a fixed number of light decorations in each decoration. diff --git a/doomsday/Src/dd_defns.c b/doomsday/Src/dd_defns.c index cdd08de9de..bca31ad397 100644 --- a/doomsday/Src/dd_defns.c +++ b/doomsday/Src/dd_defns.c @@ -746,7 +746,7 @@ void Def_PostInit(void) (defs.details[i].detail_lump); details[i].gltex = 0; // Not loaded. } - + // Surface decorations. for(i = 0; i < defs.count.decorations.num; i++) { @@ -766,6 +766,45 @@ void Def_PostInit(void) } } +//=========================================================================== +// Def_SetLightMap +//=========================================================================== +void Def_SetLightMap + (ded_lightmap_t *map, const char *id, unsigned int texture) +{ + if(stricmp(map->id, id)) return; // Not the same lightmap? + map->tex = texture; +} + +//=========================================================================== +// Def_LightMapLoaded +//=========================================================================== +void Def_LightMapLoaded(const char *id, unsigned int texture) +{ + int i, k; + ded_decor_t *decor; + + // Load lightmaps. + for(i = 0; i < defs.count.lights.num; i++) + { + Def_SetLightMap(&defs.lights[i].up, id, texture); + Def_SetLightMap(&defs.lights[i].down, id, texture); + Def_SetLightMap(&defs.lights[i].sides, id, texture); + } + for(i = 0, decor = defs.decorations; i < defs.count.decorations.num; + i++, decor++) + { + for(k = 0; k < DED_DECOR_NUM_LIGHTS; k++) + { + if(!R_IsValidLightDecoration(&decor->lights[k])) + break; + Def_SetLightMap(&decor->lights[k].up, id, texture); + Def_SetLightMap(&decor->lights[k].down, id, texture); + Def_SetLightMap(&decor->lights[k].sides, id, texture); + } + } +} + //========================================================================== // Def_SameStateSequence // Can we reach 'snew' if we start searching from 'sold'? diff --git a/doomsday/Src/dedread.c b/doomsday/Src/dedread.c index 6df1340921..13fe459e6a 100644 --- a/doomsday/Src/dedread.c +++ b/doomsday/Src/dedread.c @@ -720,8 +720,6 @@ int DED_ReadData(ded_t *ded, char *buffer, const char *sourceFile) for(;;) { READLABEL; - //RV_STR("Sprite", lig->sprite.id) - //RV_INT("Frame", lig->frame) RV_STR("State", lig->state) RV_FLT("X Offset", lig->xoffset) RV_FLT("Y Offset", lig->yoffset) @@ -731,6 +729,9 @@ int DED_ReadData(ded_t *ded, char *buffer, const char *sourceFile) RV_FLT("Blue", lig->color[2]) RV_VEC("Color", lig->color, 3) RV_STR("Flags", lig->flags_string) + RV_STR("Top map", lig->up.id) + RV_STR("Bottom map", lig->down.id) + RV_STR("Side map", lig->sides.id) RV_END CHECKSC; } @@ -1239,6 +1240,9 @@ int DED_ReadData(ded_t *ded, char *buffer, const char *sourceFile) RV_IVEC("Pattern skip", dl->pattern_skip, 2) RV_IVEC("Levels", dl->light_levels, 2) RV_INT("Flare texture", dl->flare_texture) + RV_STR("Top map", dl->up.id) + RV_STR("Bottom map", dl->down.id) + RV_STR("Side map", dl->sides.id) RV_END CHECKSC; } diff --git a/doomsday/Src/gl_tex.c b/doomsday/Src/gl_tex.c index a20dbe264f..466f8a00d0 100644 --- a/doomsday/Src/gl_tex.c +++ b/doomsday/Src/gl_tex.c @@ -124,6 +124,7 @@ DGLuint glowtexname; static boolean texInited = false; // Init done. static boolean allowMaskedTexEnlarge = false; static boolean noHighResTex = false; +static boolean noHighResPatches = false; static boolean highResWithPWAD = false; // Raw screen lumps (just lump numbers). @@ -342,8 +343,9 @@ void GL_InitTextureManager(void) // that have taller patches than they are themselves. allowMaskedTexEnlarge = ArgExists("-bigmtex"); - // The -nohitex option disables the high resolution TGA textures. + // Disable the use of 'high resolution' textures? noHighResTex = ArgExists("-nohightex"); + noHighResPatches = ArgExists("-nohighpat"); // Should we allow using external resources with PWAD textures? highResWithPWAD = ArgExists("-pwadtex"); @@ -429,17 +431,104 @@ void GL_DestroySkinNames(void) numskinnames = 0; } +//=========================================================================== +// GL_LoadLightMap +// Lightmaps should be monochrome images. +//=========================================================================== +void GL_LoadLightMap(ded_lightmap_t *map) +{ + image_t image; + char resource[256]; + + if(map->tex) return; // Already loaded. + + // Default texture name. + map->tex = dltexname; + + if(!strcmp(map->id, "-")) + { + // No lightmap, if we don't know where to find the map. + map->tex = 0; + } + else if(map->id[0]) // Not an empty string. + { + // Search an external resource. + if(R_FindResource(RC_LIGHTMAP, map->id, "-ck", resource) + && GL_LoadImage(&image, resource, false)) + { + if(!image.isMasked) + { + // An alpha channel is required. If one is not in the + // image data, we'll generate it. + GL_ConvertToAlpha(&image); + } + + map->tex = gl.NewTexture(); + + // Upload the texture. + // No mipmapping or resizing is needed, upload directly. + gl.TexImage(image.pixelSize == 2? DGL_LUMINANCE_PLUS_A8 + : image.pixelSize == 3? DGL_RGB : DGL_RGBA, + image.width, image.height, 0, image.pixels); + GL_DestroyImage(&image); + + gl.TexParameter(DGL_MIN_FILTER, DGL_LINEAR); + gl.TexParameter(DGL_MAG_FILTER, DGL_LINEAR); + gl.TexParameter(DGL_WRAP_S, DGL_CLAMP); + gl.TexParameter(DGL_WRAP_T, DGL_CLAMP); + + // Copy this to all defs with the same lightmap. + Def_LightMapLoaded(map->id, map->tex); + } + } +} + +//=========================================================================== +// GL_DeleteLightMap +//=========================================================================== +void GL_DeleteLightMap(ded_lightmap_t *map) +{ + if(map->tex != dltexname) + { + gl.DeleteTextures(1, &map->tex); + } + map->tex = 0; +} + //=========================================================================== // GL_LoadSystemTextures // Prepares all the system textures (dlight, ptcgens). //=========================================================================== void GL_LoadSystemTextures(void) { + int i, k; + ded_decor_t *decor; + if(!texInited) return; dltexname = GL_PrepareLightTexture(); glowtexname = GL_PrepareGlowTexture(); + // Load lightmaps. + for(i = 0; i < defs.count.lights.num; i++) + { + GL_LoadLightMap(&defs.lights[i].up); + GL_LoadLightMap(&defs.lights[i].down); + GL_LoadLightMap(&defs.lights[i].sides); + } + for(i = 0, decor = defs.decorations; i < defs.count.decorations.num; + i++, decor++) + { + for(k = 0; k < DED_DECOR_NUM_LIGHTS; k++) + { + if(!R_IsValidLightDecoration(&decor->lights[k])) + break; + GL_LoadLightMap(&decor->lights[k].up); + GL_LoadLightMap(&decor->lights[k].down); + GL_LoadLightMap(&decor->lights[k].sides); + } + } + // Load particle textures. PG_InitTextures(); } @@ -451,8 +540,30 @@ void GL_LoadSystemTextures(void) //=========================================================================== void GL_ClearSystemTextures(void) { + int i, k; + ded_decor_t *decor; + if(!texInited) return; + for(i = 0; i < defs.count.lights.num; i++) + { + GL_DeleteLightMap(&defs.lights[i].up); + GL_DeleteLightMap(&defs.lights[i].down); + GL_DeleteLightMap(&defs.lights[i].sides); + } + for(i = 0, decor = defs.decorations; i < defs.count.decorations.num; + i++, decor++) + { + for(k = 0; k < DED_DECOR_NUM_LIGHTS; k++) + { + if(!R_IsValidLightDecoration(&decor->lights[k])) + break; + GL_DeleteLightMap(&decor->lights[k].up); + GL_DeleteLightMap(&decor->lights[k].down); + GL_DeleteLightMap(&decor->lights[k].sides); + } + } + gl.DeleteTextures(1, &dltexname); gl.DeleteTextures(1, &glowtexname); dltexname = 0; @@ -1447,6 +1558,29 @@ void TranslatePatch(patch_t *patch, byte *transTable) } } +//=========================================================================== +// GL_ConvertToAlpha +//=========================================================================== +void GL_ConvertToAlpha(image_t *image) +{ + int p, total = image->width * image->height; + byte *ptr = image->pixels; + + // Average the RGB colors. + for(p = 0; p < total; p++, ptr += image->pixelSize) + { + image->pixels[p] = (ptr[0] + ptr[1] + ptr[2]) / 3; + } + for(p = 0; p < total; p++) + { + // Move the average color to the alpha channel, make the + // actual color white. + image->pixels[total + p] = image->pixels[p]; + image->pixels[p] = 255; + } + image->pixelSize = 2; +} + //=========================================================================== // GL_LoadImage // Loads PCX, TGA and PNG images. The returned buffer must be freed @@ -1469,7 +1603,9 @@ byte *GL_LoadImage(image_t *img, const char *imagefn, boolean useModelPath) return NULL; // Not found. } else + { strcpy(img->fileName, imagefn); + } // We know how to load PCX, TGA and PNG. M_GetFileExt(img->fileName, ext); @@ -1478,6 +1614,7 @@ byte *GL_LoadImage(image_t *img, const char *imagefn, boolean useModelPath) img->pixels = PCX_AllocLoad(img->fileName, &img->width, &img->height, NULL); img->pixelSize = 3; // PCXs can't be masked. + img->originalBits = 8; } else if(!strcmp(ext, "tga")) { @@ -1491,7 +1628,16 @@ byte *GL_LoadImage(image_t *img, const char *imagefn, boolean useModelPath) img->pixels = M_Malloc(4 * img->width * img->height); format = TGA_Load32_rgba8888(file, img->width, img->height, img->pixels); - img->pixelSize = (format == TGA_TARGA24? 3 : 4); + if(format == TGA_TARGA24) + { + img->pixelSize = 3; + img->originalBits = 24; + } + else + { + img->pixelSize = 4; + img->originalBits = 32; + } F_Close(file); } else if(!strcmp(ext, "png")) @@ -1500,6 +1646,7 @@ byte *GL_LoadImage(image_t *img, const char *imagefn, boolean useModelPath) img->pixels = PNG_Load(img->fileName, &img->width, &img->height, &img->pixelSize); + img->originalBits = 8 * img->pixelSize; END_PROF( PROF_PNG_LOAD ); @@ -1541,6 +1688,7 @@ byte *GL_LoadImage(image_t *img, const char *imagefn, boolean useModelPath) } // Color keying is done; now we have 4 bytes per pixel. img->pixelSize = 4; + img->originalBits = 32; // Effectively... } // Any alpha pixels? @@ -2804,7 +2952,8 @@ void GL_SetPatch(int lump) // Let's first try the resource locator and see if there is a // 'high-resolution' version available. - if(!noHighResTex + if(!noHighResPatches + && (loadExtAlways || highResWithPWAD || W_IsFromIWAD(lump)) && R_FindResource(RC_PATCH, lumpinfo[lump].name, "-ck", fileName) && GL_LoadImage(&image, fileName, false)) { diff --git a/doomsday/Src/rend_decor.c b/doomsday/Src/rend_decor.c index 671d2d083c..55ec8d5a94 100644 --- a/doomsday/Src/rend_decor.c +++ b/doomsday/Src/rend_decor.c @@ -237,7 +237,9 @@ void Rend_AddLightDecoration lum->thing = &source->thing; lum->center = 0; lum->flags = LUMF_CLIPPED; - lum->tex = lum->floortex = lum->ceiltex = GL_PrepareLightTexture(); + lum->tex = def->sides.tex; + lum->ceiltex = def->up.tex; + lum->floortex = def->down.tex; // These are the same rules as in DL_ThingRadius(). lum->radius = def->radius * 40 * dlRadFactor; @@ -282,15 +284,6 @@ boolean Rend_CheckDecorationBounds(fixed_t bounds[6], float fMaxDist) && viewz < bounds[BCEILING] + maxDist; } -/* - * Returns true if the given light decoration definition is valid. - */ -boolean Rend_IsValidLightDecoration(ded_decorlight_t *lightDef) -{ - return lightDef->color[0] != 0 || lightDef->color[1] != 0 - || lightDef->color[2] != 0; -} - /* * Returns > 0 if the sector lightlevel passes the limit condition. */ @@ -379,7 +372,7 @@ void Rend_DecorateLineSection lightDef = def->lights + i; // No more? - if(!Rend_IsValidLightDecoration(lightDef)) break; + if(!R_IsValidLightDecoration(lightDef)) break; // Does it pass the sectorlight limitation? if((brightMul = Rend_CheckSectorLight(side->sector, lightDef)) <= 0) @@ -612,7 +605,7 @@ void Rend_DecoratePlane lightDef = def->lights + i; // No more? - if(!Rend_IsValidLightDecoration(lightDef)) break; + if(!R_IsValidLightDecoration(lightDef)) break; // Does it pass the sectorlight limitation? if((brightMul = Rend_CheckSectorLight(sector, lightDef)) <= 0) diff --git a/doomsday/Src/rend_dyn.c b/doomsday/Src/rend_dyn.c index 294174d636..623d0d06d0 100644 --- a/doomsday/Src/rend_dyn.c +++ b/doomsday/Src/rend_dyn.c @@ -1058,8 +1058,17 @@ void DL_AddLuminous(mobj_t *thing) lum->xyscale = 1; // Use the same default light texture for all directions. - lum->tex = lum->ceiltex = lum->floortex - = GL_PrepareLightTexture(); + if(def) + { + lum->tex = def->sides.tex; + lum->ceiltex = def->up.tex; + lum->floortex = def->down.tex; + } + else + { + lum->tex = lum->ceiltex = lum->floortex + = GL_PrepareLightTexture(); + } } } @@ -1508,7 +1517,7 @@ boolean DL_LightIteratorFunc(lumobj_t *lum, flatitervars_t *fi) //fi->poly->light = lum; - if(applyCeiling > 0) + if(applyCeiling > 0 && lum->ceiltex) { // Check that the height difference is tolerable. cdiff = fi->fceil - z; @@ -1533,7 +1542,7 @@ boolean DL_LightIteratorFunc(lumobj_t *lum, flatitervars_t *fi) } } - if(applyFloor > 0) + if(applyFloor > 0 && lum->floortex) { fdiff = z - fi->ffloor; if(fdiff < 0) fdiff = 0; @@ -1557,6 +1566,10 @@ boolean DL_LightIteratorFunc(lumobj_t *lum, flatitervars_t *fi) } } + // If the light has no texture for the 'sides', there's no point in + // going through the wall segments. + if(!lum->tex) return true; + // The wall segments. for(i = 0, seg = segs + SEGIDX(fi->subsector->firstline); i < fi->subsector->linecount; i++, seg += SEGSIZE)