Polymost projection changes to correct the perspective in widescreen and ultrawide resolutions.

Patch from Nuke.YKT and Fox.

git-svn-id: https://svn.eduke32.com/eduke32@7916 1a8010ca-5511-0410-912e-c29ae57300e0

# Conflicts:
#	source/build/include/polymost.h
#	source/build/src/polymost.cpp
This commit is contained in:
terminx 2019-08-07 22:44:33 +00:00 committed by Christoph Oelckers
parent b7f349cd92
commit b8f668aa9b
3 changed files with 89 additions and 25 deletions

View file

@ -26,6 +26,7 @@ extern double gxyaspect;
extern float grhalfxdown10x; extern float grhalfxdown10x;
extern float gcosang, gsinang, gcosang2, gsinang2; extern float gcosang, gsinang, gcosang2, gsinang2;
extern float gchang, gshang, gctang, gstang, gvisibility; extern float gchang, gshang, gctang, gstang, gvisibility;
extern float gvrcorrection;
struct glfiltermodes { struct glfiltermodes {
const char *name; const char *name;
@ -70,6 +71,8 @@ void polymost_useDetailMapping(char useDetailMapping);
void polymost_useGlowMapping(char useGlowMapping); void polymost_useGlowMapping(char useGlowMapping);
void useShaderProgram(uint32_t shaderID); void useShaderProgram(uint32_t shaderID);
float* multiplyMatrix4f(float m0[4*4], const float m1[4*4]);
void polymost_glinit(void); void polymost_glinit(void);
void polymost_glreset(void); void polymost_glreset(void);

View file

@ -1847,9 +1847,10 @@ int md3postload_polymer(md3model_t *m)
void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f, float mat[16]) void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f, float mat[16])
{ {
float g;
float k0, k1, k2, k3, k4, k5, k6, k7; float k0, k1, k2, k3, k4, k5, k6, k7;
/*
float g;
k0 = ((float)(tspr->x-globalposx))*f*(1.f/1024.f); k0 = ((float)(tspr->x-globalposx))*f*(1.f/1024.f);
k1 = ((float)(tspr->y-globalposy))*f*(1.f/1024.f); k1 = ((float)(tspr->y-globalposy))*f*(1.f/1024.f);
f = gcosang2*gshang; f = gcosang2*gshang;
@ -1864,6 +1865,35 @@ void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f, float
mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7; mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
k6 = gcosang2*gchang; k7 = gsinang2*gchang; k6 = gcosang2*gchang; k7 = gsinang2*gchang;
mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7; mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
*/
k0 = ((float)(tspr->x-globalposx))*f*(1.f/1024.f);
k1 = ((float)(tspr->y-globalposy))*f*(1.f/1024.f);
k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] * (1.f/16384.f);
k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] * (1.f/16384.f);
k2 = k0*(1-k4)+k1*k5;
k3 = k1*(1-k4)-k0*k5;
k6 = -gsinang; k7 = gcosang;
mat[0] = k4*k6 + k5*k7; mat[4] = 0.f; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
mat[1] = 0.f; mat[5] = 1.f; mat[ 9] = 0.f; mat[13] = 0.f;
k6 = gcosang2; k7 = gsinang2;
mat[2] = k4*k6 + k5*k7; mat[6] = 0.f; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
//Up/down rotation
float udmatrix[16] = {
1.f, 0.f, 0.f, 0.f,
0.f, gchang, -gshang*gvrcorrection, 0.f,
0.f, gshang/gvrcorrection, gchang, 0.f,
0.f, 0.f, 0.f, 1.f,
};
// Tilt rotation
float tiltmatrix[16] = {
gctang, -gstang, 0.f, 0.f,
gstang, gctang, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f,
};
multiplyMatrix4f(mat, udmatrix);
multiplyMatrix4f(mat, tiltmatrix);
mat[12] = (mat[12] + a0->y*mat[0]) + (a0->z*mat[4] + a0->x*mat[ 8]); mat[12] = (mat[12] + a0->y*mat[0]) + (a0->z*mat[4] + a0->x*mat[ 8]);
mat[13] = (mat[13] + a0->y*mat[1]) + (a0->z*mat[5] + a0->x*mat[ 9]); mat[13] = (mat[13] + a0->y*mat[1]) + (a0->z*mat[5] + a0->x*mat[ 9]);

View file

@ -66,6 +66,7 @@ float gyxscale, ghalfx, grhalfxdown10, grhalfxdown10x, ghalfy;
float gcosang, gsinang, gcosang2, gsinang2; float gcosang, gsinang, gcosang2, gsinang2;
float gchang, gshang, gctang, gstang, gvisibility; float gchang, gshang, gctang, gstang, gvisibility;
float gtang = 0.f; float gtang = 0.f;
float gvrcorrection = 1.f;
static vec3d_t xtex, ytex, otex, xtex2, ytex2, otex2; static vec3d_t xtex, ytex, otex, xtex2, ytex2, otex2;
@ -102,7 +103,7 @@ int32_t r_glowmapping = 1;
int32_t gltexmaxsize = 0; // 0 means autodetection on first run int32_t gltexmaxsize = 0; // 0 means autodetection on first run
int32_t gltexmiplevel = 0; // discards this many mipmap levels int32_t gltexmiplevel = 0; // discards this many mipmap levels
int32_t glprojectionhacks = 1; int32_t glprojectionhacks = 2;
static FHardwareTexture *polymosttext = 0; static FHardwareTexture *polymosttext = 0;
int32_t glrendmode = REND_POLYMOST; int32_t glrendmode = REND_POLYMOST;
int32_t r_shadeinterpolate = 1; int32_t r_shadeinterpolate = 1;
@ -329,7 +330,7 @@ float glox1, gloy1, glox2, gloy2, gloyxscale, gloxyaspect, glohoriz2, glohorizco
static int32_t gltexcacnum = -1; static int32_t gltexcacnum = -1;
//in-place multiply m0=m0*m1 //in-place multiply m0=m0*m1
static float* multiplyMatrix4f(float m0[4*4], const float m1[4*4]) float* multiplyMatrix4f(float m0[4*4], const float m1[4*4])
{ {
float mR[4*4]; float mR[4*4];
@ -1141,20 +1142,18 @@ void calc_and_apply_fog_factor(int32_t shade, int32_t vis, int32_t pal, float fa
static float get_projhack_ratio(void) static float get_projhack_ratio(void)
{ {
if (glprojectionhacks && !r_yshearing) if ((glprojectionhacks == 1) && !r_yshearing)
{ {
float const projhack_zoom = 1.4f * // calculates the extend of the zenith glitch
// adjust for the FOV, increasing the FOV reduces the zenith glitch float verticalfovtan = (fviewingrange * (windowxy2.y-windowxy1.y) * 5.f) / ((float)yxaspect * (windowxy2.x-windowxy1.x) * 4.f);
// don't apply if the zenith is cut from the viewing area float verticalfov = atanf(verticalfovtan) * (2.f / fPI);
(65536.f / fviewingrange) * static constexpr float const maxhorizangle = 0.6361136f; // horiz of 199 in degrees
(float)(windowxy2.y-windowxy1.y+1) / float zenglitch = verticalfov + maxhorizangle - 0.95f; // less than 1 because the zenith glitch extends a bit
(float)(windowxy2.x-windowxy1.x+1) * if (zenglitch <= 0.f)
(float)(xdim)/(float)(ydim);
if (projhack_zoom < 1.f)
return 1.f; return 1.f;
static constexpr float const maxcoshoriz = 0.540971179375801f; // 128/sqrt(128^2+199^2) = cos of an horiz diff of 199 float const zenglitchtan = tanf((verticalfov - zenglitch) * (fPI / 2.f));
float const factor = (projhack_zoom - 1.f) * (1.f / maxcoshoriz); static constexpr float const maxcoshoriz = 0.54097117f; // 128/sqrt(128^2+199^2) = cos of an horiz diff of 199
return 1.f + (factor * (1.f - Bfabsf(gchang))); return 1.f + (((verticalfovtan / zenglitchtan) - 1.f) * ((1.f - Bfabsf(gchang)) / maxcoshoriz ));
} }
// No projection hacks (legacy or new-aspect) // No projection hacks (legacy or new-aspect)
@ -2054,8 +2053,8 @@ static void polymost_updaterotmat(void)
//Up/down rotation //Up/down rotation
float udmatrix[16] = { float udmatrix[16] = {
1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
0.f, gchang, -gshang, 0.f, 0.f, gchang, -gshang*gvrcorrection, 0.f,
0.f, gshang, gchang, 0.f, 0.f, gshang/gvrcorrection, gchang, 0.f,
0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f,
}; };
// Tilt rotation // Tilt rotation
@ -2132,8 +2131,8 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
int j = 0; int j = 0;
float px[8], py[8], dd[8], uu[8], vv[8]; float px[8], py[8], dd[8], uu[8], vv[8];
#if SOFTROTMAT #if SOFTROTMAT
float const ozgs = ghalfx * gshang, float const ozgs = (ghalfx / gvrcorrection) * gshang,
ozgc = ghalfx * gchang; ozgc = (ghalfx / gvrcorrection) * gchang;
#endif #endif
for (bssize_t i=0; i<n; ++i) for (bssize_t i=0; i<n; ++i)
@ -2145,12 +2144,14 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32
(dpxy[i].y - ghoriz) * gshang + ozgc }; (dpxy[i].y - ghoriz) * gshang + ozgc };
// Tilt rotation // Tilt rotation
float const r = ghalfx / orot.z; float const r = (ghalfx / gvrcorrection) / orot.z;
px[j] = ghalfx + (((orot.x * gctang) - (orot.y * gstang)) * r); px[j] = ghalfx + (((orot.x * gctang) - (orot.y * gstang)) * r);
py[j] = ghoriz + (((orot.x * gstang) + (orot.y * gctang)) * r); py[j] = ghoriz + (((orot.x * gstang) + (orot.y * gctang)) * r);
dd[j] = (dpxy[i].x * xtex.d + dpxy[i].y * ytex.d + otex.d) * r; dd[j] = (dpxy[i].x * xtex.d + dpxy[i].y * ytex.d + otex.d) * r;
if (dd[j] <= 0.f) // invalid polygon
return;
uu[j] = (dpxy[i].x * xtex.u + dpxy[i].y * ytex.u + otex.u) * r; uu[j] = (dpxy[i].x * xtex.u + dpxy[i].y * ytex.u + otex.u) * r;
vv[j] = (dpxy[i].x * xtex.v + dpxy[i].y * ytex.v + otex.v) * r; vv[j] = (dpxy[i].x * xtex.v + dpxy[i].y * ytex.v + otex.v) * r;
@ -5284,6 +5285,18 @@ void polymost_drawrooms()
polymost_setBrightness(r_brightnesshack); polymost_setBrightness(r_brightnesshack);
gvrcorrection = viewingrange*(1.f/65536.f);
if (glprojectionhacks == 2)
{
// calculates the extend of the zenith glitch
float verticalfovtan = (fviewingrange * (windowxy2.y-windowxy1.y) * 5.f) / ((float)yxaspect * (windowxy2.x-windowxy1.x) * 4.f);
float verticalfov = atanf(verticalfovtan) * (2.f / fPI);
static constexpr float const maxhorizangle = 0.6361136f; // horiz of 199 in degrees
float zenglitch = verticalfov + maxhorizangle - 0.95f; // less than 1 because the zenith glitch extends a bit
if (zenglitch > 0.f)
gvrcorrection /= (zenglitch * 2.5f) + 1.f;
}
//Polymost supports true look up/down :) Here, we convert horizon to angle. //Polymost supports true look up/down :) Here, we convert horizon to angle.
//gchang&gshang are cos&sin of this angle (respectively) //gchang&gshang are cos&sin of this angle (respectively)
gyxscale = ((float)xdimenscale)*(1.0f/131072.f); gyxscale = ((float)xdimenscale)*(1.0f/131072.f);
@ -5313,13 +5326,14 @@ void polymost_drawrooms()
else else
{ {
float r = (float)(ydimen >> 1) - ghoriz - ghorizcorrect; float r = (float)(ydimen >> 1) - ghoriz - ghorizcorrect;
gshang = r / Bsqrtf(r * r + ghalfx * ghalfx); gshang = r / Bsqrtf(r * r + ghalfx * ghalfx / (gvrcorrection * gvrcorrection));
gchang = Bsqrtf(1.f - gshang * gshang); gchang = Bsqrtf(1.f - gshang * gshang);
ghoriz2 = 0.f; ghoriz2 = 0.f;
} }
ghoriz = (float)(ydimen>>1); ghoriz = (float)(ydimen>>1);
resizeglcheck(); resizeglcheck();
float const ratio = 1.f/get_projhack_ratio();
//global cos/sin tilt angle //global cos/sin tilt angle
gctang = cosf(gtang); gctang = cosf(gtang);
@ -5343,8 +5357,8 @@ void polymost_drawrooms()
for (auto & v : p) for (auto & v : p)
{ {
//Tilt rotation (backwards) //Tilt rotation (backwards)
vec2f_t const o = { v.x-ghalfx, v.y-ghoriz }; vec2f_t const o = { (v.x-ghalfx)*ratio, (v.y-ghoriz)*ratio };
vec3f_t const o2 = { o.x*gctang + o.y*gstang, o.y*gctang - o.x*gstang + ghoriz2, ghalfx }; vec3f_t const o2 = { o.x*gctang + o.y*gstang, o.y*gctang - o.x*gstang + ghoriz2, ghalfx / gvrcorrection };
//Up/down rotation (backwards) //Up/down rotation (backwards)
v = { o2.x, o2.y * gchang + o2.z * gshang, o2.z * gchang - o2.y * gshang }; v = { o2.x, o2.y * gchang + o2.z * gshang, o2.z * gchang - o2.y * gshang };
@ -5380,7 +5394,7 @@ void polymost_drawrooms()
for (bssize_t i = 0; i < n; i++) for (bssize_t i = 0; i < n; i++)
{ {
float const r = ghalfx / p2[i].z; float const r = (ghalfx / gvrcorrection) / p2[i].z;
sx[i] = p2[i].x * r + ghalfx; sx[i] = p2[i].x * r + ghalfx;
sy[i] = p2[i].y * r + ghoriz; sy[i] = p2[i].y * r + ghoriz;
} }
@ -5734,6 +5748,18 @@ void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang
polymost_outputGLDebugMessage(3, "polymost_prepareMirror(%u)", mirrorWall); polymost_outputGLDebugMessage(3, "polymost_prepareMirror(%u)", mirrorWall);
//POGO: prepare necessary globals for drawing, as we intend to call this outside of drawrooms //POGO: prepare necessary globals for drawing, as we intend to call this outside of drawrooms
gvrcorrection = viewingrange*(1.f/65536.f);
if (glprojectionhacks == 2)
{
// calculates the extend of the zenith glitch
float verticalfovtan = (fviewingrange * (windowxy2.y-windowxy1.y) * 5.f) / ((float)yxaspect * (windowxy2.x-windowxy1.x) * 4.f);
float verticalfov = atanf(verticalfovtan) * (2.f / fPI);
static constexpr float const maxhorizangle = 0.6361136f; // horiz of 199 in degrees
float zenglitch = verticalfov + maxhorizangle - 0.95f; // less than 1 because the zenith glitch extends a bit
if (zenglitch > 0.f)
gvrcorrection /= (zenglitch * 2.5f) + 1.f;
}
set_globalpos(dax, day, daz); set_globalpos(dax, day, daz);
set_globalang(daang); set_globalang(daang);
globalhoriz = mulscale16(fix16_to_int(dahoriz)-100,divscale16(xdimenscale,viewingrange))+(ydimen>>1); globalhoriz = mulscale16(fix16_to_int(dahoriz)-100,divscale16(xdimenscale,viewingrange))+(ydimen>>1);
@ -5760,7 +5786,7 @@ void polymost_prepareMirror(int32_t dax, int32_t day, int32_t daz, fix16_t daang
else else
{ {
float r = (float)(ydimen >> 1) - ghoriz; float r = (float)(ydimen >> 1) - ghoriz;
gshang = r / Bsqrtf(r * r + ghalfx * ghalfx); gshang = r / Bsqrtf(r * r + ghalfx * ghalfx / (gvrcorrection * gvrcorrection));
gchang = Bsqrtf(1.f - gshang * gshang); gchang = Bsqrtf(1.f - gshang * gshang);
ghoriz2 = 0.f; ghoriz2 = 0.f;
} }
@ -6557,6 +6583,7 @@ void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a,
double const ogxyaspect = gxyaspect; gxyaspect = 1.f; double const ogxyaspect = gxyaspect; gxyaspect = 1.f;
int const oldviewingrange = viewingrange; viewingrange = 65536; int const oldviewingrange = viewingrange; viewingrange = 65536;
float const oldfviewingrange = fviewingrange; fviewingrange = 65536.f; float const oldfviewingrange = fviewingrange; fviewingrange = 65536.f;
float const ogvrcorrection = gvrcorrection; gvrcorrection = 1.f;
polymost_updaterotmat(); polymost_updaterotmat();
@ -6748,6 +6775,7 @@ void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a,
# endif # endif
if (!nofog) polymost_setFogEnabled(true); if (!nofog) polymost_setFogEnabled(true);
gvrcorrection = ogvrcorrection;
viewingrange = oldviewingrange; viewingrange = oldviewingrange;
fviewingrange = oldfviewingrange; fviewingrange = oldfviewingrange;
gxyaspect = ogxyaspect; gxyaspect = ogxyaspect;
@ -6808,6 +6836,8 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
gctang = 1.f; gctang = 1.f;
float const ogstang = gstang; float const ogstang = gstang;
gstang = 0.f; gstang = 0.f;
float const ogvrcorrection = gvrcorrection;
gvrcorrection = 1.f;
polymost_updaterotmat(); polymost_updaterotmat();
@ -7023,6 +7053,7 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16
gshang = ogshang; gshang = ogshang;
gctang = ogctang; gctang = ogctang;
gstang = ogstang; gstang = ogstang;
gvrcorrection = ogvrcorrection;
polymost_identityrotmat(); polymost_identityrotmat();
} }