void TestLightFace (int surfnum, const vec3_t faceoffset) { dface_t *f; lightinfo_t l; int i; // int j, c; vec3_t point; f = dfaces + surfnum; memset (&l, 0, sizeof(l)); strcpy (l.texname, miptex[texinfo[f->texinfo].miptex].name); // we can speed up the checking process by ignoring any textures // that give white light. this hasn't been done since version 0.2, // we can get rid of it // FindTexlightColor (&i, &j, &c, miptex[texinfo[f->texinfo].miptex].name); // if (i == 255 && j == 255 && c == 255) // return; // don't even bother with sky - although we might later on if we can // get some kinda good sky textures going. if (!strncmp (l.texname, "sky", 3)) return; l.surfnum = surfnum; l.face = f; /* rotate plane */ VectorCopy (dplanes[f->planenum].normal, l.facenormal); l.facedist = dplanes[f->planenum].dist; VectorScale (l.facenormal, l.facedist, point); VectorAdd (point, faceoffset, point); l.facedist = DotProduct( point, l.facenormal ); if (f->side) { VectorNegate (l.facenormal, l.facenormal); l.facedist = -l.facedist; } CalcFaceVectors (&l); // use the safe version here which will not give bad surface // extents on special textures CalcFaceExtents(&l, faceoffset, false); CalcPoints (&l); for (i = 0 ; i < num_entities ; i++) { if (!strcmp (entities[i].classname, "light")) { // don't test torches, flames and globes // they already have their own light TestSingleLightFace (&entities[i], &l, faceoffset); } else if (!strncmp (entities[i].classname, "light_fluor", 11)) { // test fluoros as well TestSingleLightFace (&entities[i], &l, faceoffset); } } }
/* ============ LightFace ============ */ void LightFace (int surfnum) { dface_t *f; lightinfo_t l; int s, t; int i,j,c; vec3_t total; int size; int lightmapwidth, lightmapsize; byte *out; vec3_t *light; int w, h; int clamp = 192; float clampfactor = 0.75; if ( !clamp192 ) { clamp = 255; clampfactor = 1.0; } f = dfaces + surfnum; // // some surfaces don't need lightmaps // f->lightofs = -1; for (j=0 ; j<MAXLIGHTMAPS ; j++) f->styles[j] = 255; if ( texinfo[f->texinfo].flags & TEX_SPECIAL) { // non-lit texture return; } memset (&l, 0, sizeof(l)); l.surfnum = surfnum; l.face = f; // // rotate plane // VectorCopy (dplanes[f->planenum].normal, l.facenormal); l.facedist = dplanes[f->planenum].dist; if (f->side) { VectorSubtract (vec3_origin, l.facenormal, l.facenormal); l.facedist = -l.facedist; } CalcFaceVectors (&l); CalcFaceExtents (&l); CalcPoints (&l); lightmapwidth = l.texsize[0]+1; size = lightmapwidth*(l.texsize[1]+1); if (size > SINGLEMAP) Error ("Bad lightmap size"); for (i=0 ; i<MAXLIGHTMAPS ; i++) l.lightstyles[i] = 255; // // cast all lights // l.numlightstyles = 0; for (i=0 ; i<numlightentities ; i++) SingleLightFace (&lightentities[i], &l); FixMinlight (&l); if (!l.numlightstyles) { // no light hitting it return; } // // save out the values // for (i=0 ; i <MAXLIGHTMAPS ; i++) f->styles[i] = l.lightstyles[i]; if( hicolor ) lightmapsize = size*l.numlightstyles*3; else lightmapsize = size * l.numlightstyles; out = GetFileSpace (lightmapsize); f->lightofs = out - filebase; // extra filtering h = (l.texsize[1]+1)*2; w = (l.texsize[0]+1)*2; for (i=0 ; i< l.numlightstyles ; i++) { if (l.lightstyles[i] == 0xff) Error ("Wrote empty lightmap"); light = l.lightmaps[i]; c = 0; for (t=0 ; t<=l.texsize[1] ; t++) { for (s=0 ; s<=l.texsize[0] ; s++, c++) { if (extrasamples) { #ifdef OLD_CODE // filtered sample VectorCopy( light[t*2*w+s*2], total ); VectorAdd( total, light[t*2*w+s*2+1], total ); VectorAdd( total, light[(t*2+1)*w+s*2], total ); VectorAdd( total, light[(t*2+1)*w+s*2+1], total ); VectorScale( total, 0.25, total ); #else int u, v; float weight[3][3] = { { 5, 9, 5 }, { 9, 16, 9 }, { 5, 9, 5 }, }; float divisor = 0.0; VectorFill(total,0); for ( u = 0; u < 3; u++ ) { for ( v = 0; v < 3; v++ ) { if ( s+u-2>=0 && t+v-1>=0 && s+u-1 <= w && t+v-1 <= h) { vec3_t sample; VectorScale( light[((t*2)+(v-1))*w + ((s*2)+(u-1))], weight[u][v], sample ); divisor += weight[u][v]; VectorAdd( total, sample, total ); } } } #endif if ( divisor > 1.0 ) VectorScale( total, 1/divisor, total ); total[0] = max(total[0],0.0); total[1] = max(total[1],0.0); total[2] = max(total[2],0.0); } else VectorCopy( light[ c ], total ); // Scale VectorScale( total, rangescale, total ); // Clamp if( hicolor ) { for( j=0; j<3; j++ ) { total[ j ] *= clampfactor; if( total[j] > clamp) total[j] = clamp; else if (total[j] < 0) Error ("light < 0"); *out++ = (byte) total[j]; } } else { int intensity = total[ 0 ] + total[ 1 ] + total[ 2 ]; if( intensity > 255 ) intensity = 255; else if( intensity < 0 ) Error( "light < 0" ); *out++ = (byte) intensity; } } } } }
/* ============ LightFace ============ */ void LightFaceLIT (int surfnum, const vec3_t faceoffset) { dface_t *f; lightinfo_t l; int s, t; int i, j, c; int size; int lightmapwidth; byte *out; int w; /* TYR - temp vars */ vec_t maxc; int x1, x2, x3, x4; /* TYR - colored lights */ vec3_t *lightcolor; vec3_t totalcolors; vec3_t point; f = dfaces + surfnum; // this version already has the light offsets calculated from // the original lighting, so we will just reuse them. if (f->lightofs == -1) return; for (j = 0 ; j < MAXLIGHTMAPS ; j++) f->styles[j] = 255; if ( texinfo[f->texinfo].flags & TEX_SPECIAL) { // non-lit texture return; } memset (&l, 0, sizeof(l)); l.surfnum = surfnum; l.face = f; // // rotate plane // VectorCopy (dplanes[f->planenum].normal, l.facenormal); l.facedist = dplanes[f->planenum].dist; VectorScale (l.facenormal, l.facedist, point); VectorAdd (point, faceoffset, point); l.facedist = DotProduct( point, l.facenormal ); if (f->side) { VectorNegate (l.facenormal, l.facenormal); l.facedist = -l.facedist; } CalcFaceVectors (&l); CalcFaceExtents (&l, faceoffset, true); CalcPoints (&l); lightmapwidth = l.texsize[0]+1; size = lightmapwidth*(l.texsize[1]+1); if (size > SINGLEMAP) COM_Error ("Bad lightmap size"); for (i = 0 ; i < MAXLIGHTMAPS ; i++) l.lightstyles[i] = 255; l.numlightstyles = 0; strcpy (l.texname, miptex[texinfo[f->texinfo].miptex].name); for (i = 0 ; i < num_entities ; i++) { if (entities[i].light) SingleLightFace (&entities[i], &l, faceoffset); } // minimum lighting FixMinlight (&l); if (!l.numlightstyles) { // no light hitting it return; } // // save out the values // for (i = 0 ; i < MAXLIGHTMAPS ; i++) f->styles[i] = l.lightstyles[i]; // we have to store the new light data at // the same offset as the old stuff... out = &newdlightdata[faces_ltoffset[surfnum]]; // extra filtering w = (l.texsize[0] + 1) * 2; for (i = 0 ; i < l.numlightstyles ; i++) { if (l.lightstyles[i] == 0xff) COM_Error ("Wrote empty lightmap"); lightcolor = l.lightmapcolors[i]; c = 0; for (t = 0 ; t <= l.texsize[1] ; t++) { for (s = 0 ; s <= l.texsize[0] ; s++, c++) { if (extrasamples) { x1 = t*2*w + s*2; x2 = x1 + 1; x3 = (t*2 + 1)*w + s*2; x4 = x3 + 1; // calculate the color totalcolors[0] = lightcolor[x1][0] + lightcolor[x2][0] + lightcolor[x3][0] + lightcolor[x4][0]; totalcolors[0] *= 0.25; totalcolors[1] = lightcolor[x1][1] + lightcolor[x2][1] + lightcolor[x3][1] + lightcolor[x4][1]; totalcolors[1] *= 0.25; totalcolors[2] = lightcolor[x1][2] + lightcolor[x2][2] + lightcolor[x3][2] + lightcolor[x4][2]; totalcolors[2] *= 0.25; } else { VectorCopy (lightcolor[c], totalcolors); } // CSL - Scale back intensity, instead // of capping individual colors VectorScale (totalcolors, rangescale, totalcolors); maxc = 0; for (j = 0; j < 3; j++) { if (totalcolors[j] > maxc) { maxc = totalcolors[j]; } else if (totalcolors[j] < 0) { totalcolors[j] = 0; // this used to be an error!!!! } } if (maxc > 255.0) VectorScale (totalcolors, 255.0 / maxc, totalcolors); // write out the lightmap in RGBA format *out++ = totalcolors[0]; *out++ = totalcolors[1]; *out++ = totalcolors[2]; } } } }