diff --git a/changelog.txt b/changelog.txt index 5db9eec6..a72c269f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,7 @@ * light: implemented attenutation formulae "delay" 4+5, ala Bengt's tools * light: removed old bsp30 support * light: lit files now automatically generated when coloured lights detected +* light: implemented 4x4 oversampling with -extra4 command line 2013-02-25 TyrUtils v0.5 diff --git a/include/light/light.h b/include/light/light.h index 5c581a66..5cee5297 100644 --- a/include/light/light.h +++ b/include/light/light.h @@ -61,7 +61,7 @@ extern byte *lit_filebase; void TransformSample(vec3_t in, vec3_t out); void RotateSample(vec3_t in, vec3_t out); -extern qboolean extrasamples; +extern int oversample; extern qboolean compress_ents; extern qboolean facecounter; extern qboolean colored; diff --git a/light.txt b/light.txt index fa8da67f..6c093028 100644 --- a/light.txt +++ b/light.txt @@ -17,6 +17,9 @@ OPTIONS -extra Calculate extra samples (2x2) and average the results for smoother shadows. + -extra4 Calculate even more samples (4x4) and average the + results for smoother shadows. + -light n Set a global minimum light level. Overrides default light level set in worldspawn. diff --git a/light/light.c b/light/light.c index b6e4c2cc..8e708987 100644 --- a/light/light.c +++ b/light/light.c @@ -36,7 +36,7 @@ byte *lit_filebase; // start of litfile data static byte *lit_file_p; // start of free space after litfile data static byte *lit_file_end; // end of space for litfile data -qboolean extrasamples; +int oversample = 1; qboolean compress_ents; qboolean colored; qboolean nominlimit; @@ -208,8 +208,11 @@ main(int argc, const char **argv) numthreads = atoi(argv[i + 1]); i++; } else if (!strcmp(argv[i], "-extra")) { - extrasamples = true; - logprint("extra sampling enabled\n"); + oversample = 2; + logprint("extra 2x2 sampling enabled\n"); + } else if (!strcmp(argv[i], "-extra4")) { + oversample = 4; + logprint("extra 4x4 sampling enabled\n"); } else if (!strcmp(argv[i], "-dist")) { scaledist = atof(argv[i + 1]); i++; @@ -238,7 +241,7 @@ main(int argc, const char **argv) logprint(".lit colored light output requested on command line.\n"); if (i != argc - 1) - Error("usage: light [-threads num] [-light num] [-extra]\n" + Error("usage: light [-threads num] [-light num] [-extra|-extra4]\n" " [-dist n] [-range n] [-lit] [-compress]\n" " [-nominlimit] bspfile\n"); diff --git a/light/ltface.c b/light/ltface.c index 5fce2e6a..32d04a20 100644 --- a/light/ltface.c +++ b/light/ltface.c @@ -150,7 +150,8 @@ CastRay(const vec3_t p1, const vec3_t p2) * ============================================================================ */ -#define SINGLEMAP (18*18*4) +/* Allow space for 4x4 oversampling */ +#define SINGLEMAP (18*18*4*4) typedef struct { vec_t lightmaps[MAXLIGHTMAPS][SINGLEMAP]; @@ -380,19 +381,11 @@ CalcPoints(lightinfo_t * l) tex_to_world(mids, midt, l, facemid); - if (extrasamples) { - h = (l->texsize[1] + 1) * 2; - w = (l->texsize[0] + 1) * 2; - starts = (l->texmins[0] - 0.25) * 16; - startt = (l->texmins[1] - 0.25) * 16; - step = 8; - } else { - h = l->texsize[1] + 1; - w = l->texsize[0] + 1; - starts = l->texmins[0] * 16; - startt = l->texmins[1] * 16; - step = 16; - } + h = (l->texsize[1] + 1) * oversample; + w = (l->texsize[0] + 1) * oversample; + starts = (l->texmins[0] - 0.5 + (0.5 / oversample)) * 16; + startt = (l->texmins[1] - 0.5 + (0.5 / oversample)) * 16; + step = 16 / oversample; l->numsurfpt = w * h; for (t = 0; t < h; t++) { @@ -853,8 +846,6 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset) int i, j, k, c; vec_t max; - int x1, x2, x3, x4; - vec_t total; int size; int lightmapwidth; @@ -1019,7 +1010,7 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset) face->lightofs = out - filebase; /* extra filtering */ - width = (l.texsize[0] + 1) * 2; + width = (l.texsize[0] + 1) * oversample; for (i = 0; i < l.numlightstyles; i++) { if (l.lightstyles[i] == 0xff) @@ -1031,38 +1022,27 @@ LightFace(int surfnum, qboolean nolight, const vec3_t faceoffset) for (t = 0; t <= l.texsize[1]; t++) { for (s = 0; s <= l.texsize[0]; s++, c++) { - if (extrasamples) { - x1 = t * 2 * width + s * 2; - x2 = x1 + 1; - x3 = (t * 2 + 1) * width + s * 2; - x4 = x3 + 1; - - /* filtered sample */ - total = light[x1] + light[x2] + light[x3] + light[x4]; - total *= 0.25; - - /* Calculate the color */ - if (colored) { - colors[0] = - lightcolor[x1][0] + lightcolor[x2][0] - + lightcolor[x3][0] + lightcolor[x4][0]; - colors[0] *= 0.25; - colors[1] = - lightcolor[x1][1] + lightcolor[x2][1] - + lightcolor[x3][1] + lightcolor[x4][1]; - colors[1] *= 0.25; - colors[2] = - lightcolor[x1][2] + lightcolor[x2][2] - + lightcolor[x3][2] + lightcolor[x4][2]; - colors[2] *= 0.25; + if (oversample > 1) { + total = 0; + VectorCopy(vec3_origin, colors); + for (j = 0; j < oversample; j++) { + for (k = 0; k < oversample; k++) { + int sample = (t * oversample + j) * width; + sample += s * oversample + k; + total += light[sample]; + if (colored) + VectorAdd(colors, lightcolor[sample], colors); + } } + total /= oversample * oversample; + VectorScale(colors, 1.0 / oversample / oversample, colors); } else { total = light[c]; if (colored) VectorCopy(lightcolor[c], colors); } - total *= rangescale; /* scale before clamping */ + total *= rangescale; /* scale before clamping */ if (colored) { /* Scale back intensity, instead of capping individual * colors