Support for equirectangular sky images. Because skybox orientations are generally too hard to get right. Urgh.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5955 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-07-06 00:12:35 +00:00
parent 0dc1b91ec6
commit af661232e3
4 changed files with 124 additions and 33 deletions

View file

@ -3505,12 +3505,13 @@ static qbyte *ReadPBMFile(qbyte *buf, size_t len, const char *fname, int *width,
static void *ReadRadianceFile(qbyte *buf, size_t len, const char *fname, int *width, int *height, uploadfmt_t *format)
{ //this isn't expected to be fast.
qbyte *end = buf+len;
size_t l, x, y, w, h;
size_t l, x, y, w, h, e;
float *r, *o, m;
qbyte rgbe[4];
char fmt[128];
char line[256];
byte_vec4_t *row = NULL;
w = h = 0;
*fmt = 0;
while (buf < end)
@ -3535,13 +3536,13 @@ static void *ReadRadianceFile(qbyte *buf, size_t len, const char *fname, int *wi
Con_Printf("%s uses unsupported orientation\n", fname);
return NULL;
}
w = strtol(buf+3, (char**)&buf, 0);
h = strtol(buf+3, (char**)&buf, 0);
if (strncmp(buf, " +X ", 4))
{
Con_Printf("%s uses unsupported orientation\n", fname);
return NULL;
}
h = strtol(buf+4, (char**)&buf, 0);
w = strtol(buf+4, (char**)&buf, 0);
if (*buf == '\r')
buf++;
if (*buf++ != '\n')
@ -3556,24 +3557,64 @@ static void *ReadRadianceFile(qbyte *buf, size_t len, const char *fname, int *wi
r = o = BZ_Malloc(sizeof(float)*4*w*h);
if (!r)
return NULL;
for (y=0; y < h; y++)
for (y=0; y < h && buf+4<end; y++)
{
if (buf[0] == 2 && buf[1] == 2 && buf[2] < 127)
{ //'new' rle logic
int c, v;
buf+=4;
if (!row)
row = BZ_Malloc(w*sizeof(*row));
//encoded separately
for (c = 0; c < 4; c++)
{
for (x=0; x < w; )
{
if (buf+1 >= end)
goto fail;
if (*buf > 128)
{
e = x + (*buf++ - 128);
v = *buf++;
if (e == x || e > w)
goto fail;
while (x < e)
row[x++][c] = v;
}
else
{
e = x + *buf++;
if (e == x || e > w || buf+(e-x) >= end)
goto fail;
while (x < e)
row[x++][c] = *buf++;
}
}
}
//decompressed the entire line, can make sense of it now.
for (x=0; x < w; x++)
{
m = ldexp(1,row[x][3]-136);
*o++ = m * row[x][0];
*o++ = m * row[x][1];
*o++ = m * row[x][2];
*o++ = 1;
}
}
else if (rgbe[0] == 1 && rgbe[1] == 1 && rgbe[2] == 1)
{ //old rle logic
Con_Printf("%s uses unsupported (old) RLE compression\n", fname);
goto fail;
}
else
{
for (x=0; x < w && buf+4<end ; x++)
{
rgbe[0] = *buf++;
rgbe[1] = *buf++;
rgbe[2] = *buf++;
rgbe[3] = *buf++;
if (rgbe[0] == 2 && rgbe[1] == 2 && rgbe[2] < 127)
{ //new rle logic
Con_Printf("%s uses unsupported (new) RLE compression\n", fname);
goto fail;
}
if (rgbe[0] == 1 && rgbe[1] == 1 && rgbe[2] == 1)
{ //old rle logic
Con_Printf("%s uses unsupported (old) RLE compression\n", fname);
goto fail;
}
m = ldexp(1,rgbe[3]-136);
*o++ = m * rgbe[0];
@ -3582,12 +3623,17 @@ static void *ReadRadianceFile(qbyte *buf, size_t len, const char *fname, int *wi
*o++ = 1;
}
}
}
if (row)
BZ_Free(row);
*width = w;
*height = h;
//FIXME: should probably convert to e5bgr9 or something.
*format = PTI_RGBA32F;
return r;
fail:
if (row)
BZ_Free(row);
BZ_Free(r);
return NULL;
}

View file

@ -1062,17 +1062,25 @@ struct
{ "shib",
"Performance optimisations for large/detailed maps.",
"if r_dynamic >= 1\n"
"{\n" //fake it anyway.
"set r_shadow_realtime_dlight 1\n"
"set r_shadow_realtime_dlight_shadows 0\n"
"set r_dynamic 0\n"
"}\n"
"set r_temporalscenecache 1\n" //the main speedup.
"set r_lightstylespeed 0\n" //FIXME: we shouldn't need this, but its too stuttery without.
"set sv_autooffload 1\n" //Needs polish still.
"set gl_pbolightmaps 1\n" //FIXME: this needs to be the default eventually.
},
{ "dm",
"Various settings to make you more competitive."
"set cl_yieldcpu 0\n"
"set v_kickroll 0\n" //roll change when taking damage
"set v_kickpitch 0\n" //pitch change when taking damage
"set v_damagecshift 0\n" //colour change when taking damage
"set v_gunkick 0\n" //recoil when firing
"set cl_rollangle 0\n" //rolling when strafing
"set cl_bob 0\n" //view bobbing when moving.
#ifdef _WIN32
"set sys_clockprecision 1\n" //windows kinda sucks otherwise
#endif
},
{ "qw",
"Enable QuakeWorld-isms, for better gameplay.",

View file

@ -79,22 +79,47 @@ void R_SetSky(const char *sky)
shadername = va("skybox_%s", sky);
if (!forcedsky || strcmp(shadername, forcedsky->name))
{
texnums_t tex;
forcedsky = NULL; //fall back to regular skies if forcing fails.
if (!*sky)
return; //no need to do anything
memset(&tex, 0, sizeof(tex));
tex.base = R_LoadHiResTexture(sky, "env:gfx/env", IF_LOADNOW|IF_NOMIPMAP);
if (tex.reflectcube && tex.reflectcube->status == TEX_LOADING)
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
if (tex.base->width && TEXLOADED(tex.base))
{
forcedsky = R_RegisterShader(shadername, 0,
"{\n"
"sort sky\n"
"program defaultsky#EQUI\n"
"{\n"
"if !$unmaskedsky\n" /* Q2/HL require the skybox to not draw over geometry, shouldn't we force it? --eukara */
"depthwrite\n"
"endif\n"
"map \"$diffuse\"\n"
"tcgen skybox\n"
"}\n"
"surfaceparm nodlight\n"
"surfaceparm sky\n"
"}");
R_BuildDefaultTexnums(&tex, forcedsky, IF_WORLDTEX);
return;
}
//if we have cubemaps then we can just go and use a cubemap for our skybox
if (sh_config.havecubemaps)
{
texnums_t tex;
memset(&tex, 0, sizeof(tex));
tex.reflectcube = R_LoadHiResTexture(sky, "env:gfx/env", IF_LOADNOW|IF_TEXTYPE_CUBE|IF_CLAMP);
tex.reflectcube = R_LoadHiResTexture(sky, "env:gfx/env", IF_LOADNOW|IF_TEXTYPE_CUBE|IF_NOMIPMAP|IF_CLAMP);
if (tex.reflectcube && tex.reflectcube->status == TEX_LOADING)
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
if (tex.reflectcube->width && TEXLOADED(tex.reflectcube))
{
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0,
forcedsky = R_RegisterShader(shadername, 0,
"{\n"
"sort sky\n"
"program defaultskybox\n"

View file

@ -22,6 +22,16 @@ void main ()
{
vec2 tccoord;
vec3 dir = pos - e_eyepos;
#ifdef EQUI
#define PI 3.1415926535897932384626433832795
dir = normalize(dir);
tccoord.x = atan(dir.x,dir.y) / (PI*2.0) + 0.5;
tccoord.y = acos(dir.z) / PI;
vec3 sky = vec3(texture2D(s_base, tccoord));
#else
dir.z *= 3.0;
dir.xy /= 0.5*length(dir);
tccoord = (dir.xy + e_time*0.03125);
@ -29,6 +39,8 @@ void main ()
tccoord = (dir.xy + e_time*0.0625);
vec4 clouds = texture2D(s_cloud, tccoord);
sky = (sky.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);
#endif
#ifdef FOG
sky.rgb = mix(sky.rgb, w_fogcolour, float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry
//sky = fog3(sky); //fog according to actual geometry