mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-02-18 01:41:46 +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)
|
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.
|
{ //this isn't expected to be fast.
|
||||||
qbyte *end = buf+len;
|
qbyte *end = buf+len;
|
||||||
size_t l, x, y, w, h;
|
size_t l, x, y, w, h, e;
|
||||||
float *r, *o, m;
|
float *r, *o, m;
|
||||||
qbyte rgbe[4];
|
qbyte rgbe[4];
|
||||||
|
|
||||||
char fmt[128];
|
char fmt[128];
|
||||||
char line[256];
|
char line[256];
|
||||||
|
byte_vec4_t *row = NULL;
|
||||||
w = h = 0;
|
w = h = 0;
|
||||||
*fmt = 0;
|
*fmt = 0;
|
||||||
while (buf < end)
|
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);
|
Con_Printf("%s uses unsupported orientation\n", fname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
w = strtol(buf+3, (char**)&buf, 0);
|
h = strtol(buf+3, (char**)&buf, 0);
|
||||||
if (strncmp(buf, " +X ", 4))
|
if (strncmp(buf, " +X ", 4))
|
||||||
{
|
{
|
||||||
Con_Printf("%s uses unsupported orientation\n", fname);
|
Con_Printf("%s uses unsupported orientation\n", fname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
h = strtol(buf+4, (char**)&buf, 0);
|
w = strtol(buf+4, (char**)&buf, 0);
|
||||||
if (*buf == '\r')
|
if (*buf == '\r')
|
||||||
buf++;
|
buf++;
|
||||||
if (*buf++ != '\n')
|
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);
|
r = o = BZ_Malloc(sizeof(float)*4*w*h);
|
||||||
if (!r)
|
if (!r)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (y=0; y < h; y++)
|
for (y=0; y < h && buf+4<end; y++)
|
||||||
{
|
{
|
||||||
for (x=0; x < w; x++)
|
if (buf[0] == 2 && buf[1] == 2 && buf[2] < 127)
|
||||||
{
|
{ //'new' rle logic
|
||||||
rgbe[0] = *buf++;
|
int c, v;
|
||||||
rgbe[1] = *buf++;
|
buf+=4;
|
||||||
rgbe[2] = *buf++;
|
if (!row)
|
||||||
rgbe[3] = *buf++;
|
row = BZ_Malloc(w*sizeof(*row));
|
||||||
if (rgbe[0] == 2 && rgbe[1] == 2 && rgbe[2] < 127)
|
//encoded separately
|
||||||
{ //new rle logic
|
for (c = 0; c < 4; c++)
|
||||||
Con_Printf("%s uses unsupported (new) RLE compression\n", fname);
|
{
|
||||||
goto fail;
|
for (x=0; x < w; )
|
||||||
}
|
{
|
||||||
if (rgbe[0] == 1 && rgbe[1] == 1 && rgbe[2] == 1)
|
if (buf+1 >= end)
|
||||||
{ //old rle logic
|
goto fail;
|
||||||
Con_Printf("%s uses unsupported (old) RLE compression\n", fname);
|
if (*buf > 128)
|
||||||
goto fail;
|
{
|
||||||
|
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);
|
//decompressed the entire line, can make sense of it now.
|
||||||
*o++ = m * rgbe[0];
|
for (x=0; x < w; x++)
|
||||||
*o++ = m * rgbe[1];
|
{
|
||||||
*o++ = m * rgbe[2];
|
m = ldexp(1,row[x][3]-136);
|
||||||
*o++ = 1;
|
*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;
|
*width = w;
|
||||||
*height = h;
|
*height = h;
|
||||||
//FIXME: should probably convert to e5bgr9 or something.
|
//FIXME: should probably convert to e5bgr9 or something.
|
||||||
*format = PTI_RGBA32F;
|
*format = PTI_RGBA32F;
|
||||||
return r;
|
return r;
|
||||||
fail:
|
fail:
|
||||||
|
if (row)
|
||||||
|
BZ_Free(row);
|
||||||
BZ_Free(r);
|
BZ_Free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1062,17 +1062,25 @@ struct
|
||||||
{ "shib",
|
{ "shib",
|
||||||
"Performance optimisations for large/detailed maps.",
|
"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_temporalscenecache 1\n" //the main speedup.
|
||||||
"set r_lightstylespeed 0\n" //FIXME: we shouldn't need this, but its too stuttery without.
|
"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 sv_autooffload 1\n" //Needs polish still.
|
||||||
"set gl_pbolightmaps 1\n" //FIXME: this needs to be the default eventually.
|
"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",
|
{ "qw",
|
||||||
"Enable QuakeWorld-isms, for better gameplay.",
|
"Enable QuakeWorld-isms, for better gameplay.",
|
||||||
|
|
||||||
|
|
|
@ -79,22 +79,47 @@ void R_SetSky(const char *sky)
|
||||||
shadername = va("skybox_%s", sky);
|
shadername = va("skybox_%s", sky);
|
||||||
if (!forcedsky || strcmp(shadername, forcedsky->name))
|
if (!forcedsky || strcmp(shadername, forcedsky->name))
|
||||||
{
|
{
|
||||||
|
texnums_t tex;
|
||||||
forcedsky = NULL; //fall back to regular skies if forcing fails.
|
forcedsky = NULL; //fall back to regular skies if forcing fails.
|
||||||
|
|
||||||
if (!*sky)
|
if (!*sky)
|
||||||
return; //no need to do anything
|
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 we have cubemaps then we can just go and use a cubemap for our skybox
|
||||||
if (sh_config.havecubemaps)
|
if (sh_config.havecubemaps)
|
||||||
{
|
{
|
||||||
texnums_t tex;
|
|
||||||
memset(&tex, 0, sizeof(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)
|
if (tex.reflectcube && tex.reflectcube->status == TEX_LOADING)
|
||||||
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
|
COM_WorkerPartialSync(tex.reflectcube, &tex.reflectcube->status, TEX_LOADING);
|
||||||
if (tex.reflectcube->width && TEXLOADED(tex.reflectcube))
|
if (tex.reflectcube->width && TEXLOADED(tex.reflectcube))
|
||||||
{
|
{
|
||||||
forcedsky = R_RegisterShader(va("skybox_%s", sky), 0,
|
forcedsky = R_RegisterShader(shadername, 0,
|
||||||
"{\n"
|
"{\n"
|
||||||
"sort sky\n"
|
"sort sky\n"
|
||||||
"program defaultskybox\n"
|
"program defaultskybox\n"
|
||||||
|
|
|
@ -22,6 +22,16 @@ void main ()
|
||||||
{
|
{
|
||||||
vec2 tccoord;
|
vec2 tccoord;
|
||||||
vec3 dir = pos - e_eyepos;
|
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.z *= 3.0;
|
||||||
dir.xy /= 0.5*length(dir);
|
dir.xy /= 0.5*length(dir);
|
||||||
tccoord = (dir.xy + e_time*0.03125);
|
tccoord = (dir.xy + e_time*0.03125);
|
||||||
|
@ -29,6 +39,8 @@ void main ()
|
||||||
tccoord = (dir.xy + e_time*0.0625);
|
tccoord = (dir.xy + e_time*0.0625);
|
||||||
vec4 clouds = texture2D(s_cloud, tccoord);
|
vec4 clouds = texture2D(s_cloud, tccoord);
|
||||||
sky = (sky.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);
|
sky = (sky.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FOG
|
#ifdef FOG
|
||||||
sky.rgb = mix(sky.rgb, w_fogcolour, float(r_skyfog)*w_fogalpha); //flat fog ignoring actual geometry
|
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
|
//sky = fog3(sky); //fog according to actual geometry
|
||||||
|
|
Loading…
Reference in a new issue