mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 21:31:37 +00:00
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:
parent
0dc1b91ec6
commit
af661232e3
4 changed files with 124 additions and 33 deletions
|
@ -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,38 +3557,83 @@ 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++)
|
||||
{
|
||||
for (x=0; x < w; 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;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = ldexp(1,rgbe[3]-136);
|
||||
*o++ = m * rgbe[0];
|
||||
*o++ = m * rgbe[1];
|
||||
*o++ = m * rgbe[2];
|
||||
*o++ = 1;
|
||||
//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++;
|
||||
|
||||
m = ldexp(1,rgbe[3]-136);
|
||||
*o++ = m * rgbe[0];
|
||||
*o++ = m * rgbe[1];
|
||||
*o++ = m * rgbe[2];
|
||||
*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;
|
||||
}
|
||||
|
|
|
@ -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.",
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue