[renderer] Get fisheye working again

Only for gl and sw at the moment (want to merge things further before I
do anything for glsl or vulkan). However, with with I've learned getting
gl and sw to work, glsl and vulkan will be trivial.
This commit is contained in:
Bill Currie 2022-03-14 23:51:30 +09:00
parent 7402fcfd0c
commit fd805886f7
3 changed files with 173 additions and 246 deletions

View file

@ -471,18 +471,18 @@ R_RenderView_ (void)
R_ZGraph ();
}
//FIXME static void R_RenderViewFishEye (void);
static void R_RenderViewFishEye (void);
void
gl_R_RenderView (void)
{
R_RenderView_ ();
/*if(!scr_fisheye->int_val)
if(!scr_fisheye->int_val)
R_RenderView_ ();
else
R_RenderViewFishEye ();*/
R_RenderViewFishEye ();
}
/*FIXME
//FIXME
// Algorithm:
// Draw up to six views, one in each direction.
// Save the picture to cube map texture, use GL_ARB_texture_cube_map.
@ -499,7 +499,34 @@ gl_R_RenderView (void)
#define BOX_TOP 4
#define BOX_BOTTOM 5
#define FPOLYCNT 16
static mat4f_t box_rotations[] = {
{ { 1, 0, 0, 0}, // front
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0,-1, 0, 0}, // right
{ 1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ {-1, 0, 0, 0}, // back
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 1, 0, 0}, // left
{-1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 0, 1, 0}, // top
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1} },
{ { 0, 0,-1, 0}, // bottom
{ 0, 1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 0, 1} },
};
#define FPOLYCNT 128
struct xyz {
float x, y, z;
@ -548,79 +575,51 @@ do { \
printf ("%s: gl error %d\n", s, (int) err); \
} while (0);
#define NO(x) \
do { \
if (x < 0) \
x += 360; \
else if (x >= 360) \
x -= 360; \
} while (0)
static void
R_RenderCubeSide (int side)
{
float pitch, n_pitch;
float yaw, n_yaw;
float roll, n_roll;
float s_roll;
mat4f_t camera;
mat4f_t camera_inverse;
mat4f_t rotinv;
pitch = n_pitch = r_refdef.viewangles[PITCH];
yaw = n_yaw = r_refdef.viewangles[YAW];
// setting ROLL for now to 0, correct roll handling
// requre more exhaustive changes in rotation
// TODO: implement via matrix
// roll = n_roll = r_refdef.viewangles[ROLL];
s_roll = r_refdef.viewangles[ROLL];
roll = n_roll = 0;
// roll -= scr_fviews->int_val * 10;
// n_roll = roll;
switch (side) {
case BOX_FRONT:
break;
case BOX_RIGHT:
n_pitch = roll;
n_yaw -= 90;
n_roll = -pitch;
break;
case BOX_LEFT:
n_pitch = -roll;
n_yaw += 90;
n_roll = pitch;
// static int f = 0;
// if (!(f++ % 100))
// printf ("%4d %4d %4d | %4d %4d %4d\n", (int) pitch, (int) yaw,
// (int) roll, (int) n_pitch, (int) n_yaw, (int) n_roll);
break;
case BOX_TOP:
n_pitch -= 90;
break;
case BOX_BOTTOM:
n_pitch += 90;
break;
case BOX_BEHIND:
n_pitch = -pitch;
n_yaw += 180;
break;
}
NO (n_pitch);
NO (n_yaw);
NO (n_roll);
r_refdef.viewangles[PITCH] = n_pitch;
r_refdef.viewangles[YAW] = n_yaw;
r_refdef.viewangles[ROLL] = n_roll;
memcpy (camera, r_refdef.camera, sizeof (camera));
memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse));
mmulf (r_refdef.camera, camera, box_rotations[side]);
mat4ftranspose (rotinv, box_rotations[side]);
mmulf (r_refdef.camera_inverse, rotinv, camera_inverse);
//FIXME see fixme in r_screen.c
r_refdef.frame.mat[0] = -r_refdef.camera[1];
r_refdef.frame.mat[1] = r_refdef.camera[0];
r_refdef.frame.mat[2] = r_refdef.camera[2];
r_refdef.frame.mat[3] = r_refdef.camera[3];
#if 0
printf ("side: %d\n", side);
printf ("c: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 0));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 1));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 2));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera, 3));
printf ("i: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 0));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 1));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 2));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.camera_inverse, 3));
printf ("f: " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 0));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 1));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 2));
printf (" " VEC4F_FMT "\n", MAT4_ROW(r_refdef.frame.mat, 3));
#endif
qfglClear (GL_DEPTH_BUFFER_BIT);
R_RenderView_ ();
qfglEnable (GL_TEXTURE_CUBE_MAP_ARB);
qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, cube_map_tex);
qfglCopyTexSubImage2D (box2cube_map[side], 0, 0, 0, 0, 0,
gl_cube_map_size, gl_cube_map_size);
// CHKGLERR ("qfglCopyTexSubImage2D");
CHKGLERR ("qfglCopyTexSubImage2D");
qfglDisable (GL_TEXTURE_CUBE_MAP_ARB);
r_refdef.viewangles[PITCH] = pitch;
r_refdef.viewangles[YAW] = yaw;
r_refdef.viewangles[ROLL] = s_roll;
memcpy (r_refdef.camera, camera, sizeof (camera));
memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse));
}
static qboolean gl_cube_map_capable = false;
@ -779,7 +778,7 @@ R_RenderViewFishEye (void)
R_SetupGL_Viewport_and_Perspective ();
qfglMatrixMode (GL_MODELVIEW);
qfglCallList (fisheye_grid);
}*/
}
void
gl_R_ClearState (void)

View file

@ -823,7 +823,7 @@ R_RenderView_ (void)
R_HighFPPrecision ();
}
//XXX FIXME static void R_RenderViewFishEye (void);
static void R_RenderViewFishEye (void);
void
R_RenderView (void)
@ -843,12 +843,10 @@ R_RenderView (void)
if ((intptr_t) (&r_warpbuffer) & 3)
Sys_Error ("Globals are missaligned");
R_RenderView_ ();
/*XXX FIXME
if (!scr_fisheye->int_val)
R_RenderView_ ();
else
R_RenderViewFishEye ();*/
R_RenderViewFishEye ();
}
void
@ -862,161 +860,55 @@ R_InitTurb (void)
// AMP2 not 20
}
}
/*XXX FIXME
#define BOX_FRONT 0
#define BOX_RIGHT 1
#define BOX_BEHIND 2
#define BOX_LEFT 3
#define BOX_RIGHT 1
#define BOX_TOP 4
#define BOX_BOTTOM 5
#define DEG(x) (x / M_PI * 180.0)
#define RAD(x) (x * M_PI / 180.0)
struct my_coords
{
double x, y, z;
static mat4f_t box_rotations[] = {
{ { 1, 0, 0, 0}, // front
{ 0, 1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0,-1, 0, 0}, // right
{ 1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ {-1, 0, 0, 0}, // back
{ 0,-1, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 1, 0, 0}, // left
{-1, 0, 0, 0},
{ 0, 0, 1, 0},
{ 0, 0, 0, 1} },
{ { 0, 0, 1, 0}, // top
{ 0, 1, 0, 0},
{-1, 0, 0, 0},
{ 0, 0, 0, 1} },
{ { 0, 0,-1, 0}, // bottom
{ 0, 1, 0, 0},
{ 1, 0, 0, 0},
{ 0, 0, 0, 1} },
};
struct my_angles
{
double yaw, pitch, roll;
};
static void
x_rot (struct my_coords *c, double pitch)
{
double nx, ny, nz;
nx = c->x;
ny = (c->y * cos(pitch)) - (c->z * sin(pitch));
nz = (c->y * sin(pitch)) + (c->z * cos(pitch));
c->x = nx; c->y = ny; c->z = nz;
}
static void
y_rot (struct my_coords *c, double yaw)
{
double nx, ny, nz;
nx = (c->x * cos(yaw)) - (c->z * sin(yaw));
ny = c->y;
nz = (c->x * sin(yaw)) + (c->z * cos(yaw));
c->x = nx; c->y = ny; c->z = nz;
}
static void
z_rot (struct my_coords *c, double roll)
{
double nx, ny, nz;
nx = (c->x * cos(roll)) - (c->y * sin(roll));
ny = (c->x * sin(roll)) + (c->y * cos(roll));
nz = c->z;
c->x = nx; c->y = ny; c->z = nz;
}
static void
my_get_angles (struct my_coords *in_o, struct my_coords *in_u, struct my_angles *a)
{
double rad_yaw, rad_pitch;
struct my_coords o, u;
a->pitch = 0.0;
a->yaw = 0.0;
a->roll = 0.0;
// make a copy of the coords
o.x = in_o->x; o.y = in_o->y; o.z = in_o->z;
u.x = in_u->x; u.y = in_u->y; u.z = in_u->z;
// special case when looking straight up or down
if ((o.x == 0.0) && (o.z == 0.0)) {
a->yaw = 0.0;
if (o.y > 0.0) { a->pitch = -90.0; a->roll = 180.0 - DEG(atan2(u.x, u.z)); } // down
else { a->pitch = 90.0; a->roll = DEG(atan2(u.x, u.z)); } // up
return;
}
// get yaw angle and then rotate o and u so that yaw = 0
rad_yaw = atan2 (-o.x, o.z);
a->yaw = DEG (rad_yaw);
y_rot (&o, -rad_yaw);
y_rot (&u, -rad_yaw);
// get pitch and then rotate o and u so that pitch = 0
rad_pitch = atan2 (-o.y, o.z);
a->pitch = DEG (rad_pitch);
x_rot (&o, -rad_pitch);
x_rot (&u, -rad_pitch);
// get roll
a->roll = DEG (-atan2(u.x, u.y));
}
static void
get_ypr (double yaw, double pitch, double roll, int side, struct my_angles *a)
{
struct my_coords o, u;
// get 'o' (observer) and 'u' ('this_way_up') depending on box side
switch(side) {
case BOX_FRONT:
o.x = 0.0; o.y = 0.0; o.z = 1.0;
u.x = 0.0; u.y = 1.0; u.z = 0.0;
break;
case BOX_BEHIND:
o.x = 0.0; o.y = 0.0; o.z = -1.0;
u.x = 0.0; u.y = 1.0; u.z = 0.0;
break;
case BOX_LEFT:
o.x = -1.0; o.y = 0.0; o.z = 0.0;
u.x = -1.0; u.y = 1.0; u.z = 0.0;
break;
case BOX_RIGHT:
o.x = 1.0; o.y = 0.0; o.z = 0.0;
u.x = 0.0; u.y = 1.0; u.z = 0.0;
break;
case BOX_TOP:
o.x = 0.0; o.y = -1.0; o.z = 0.0;
u.x = 0.0; u.y = 0.0; u.z = -1.0;
break;
case BOX_BOTTOM:
o.x = 0.0; o.y = 1.0; o.z = 0.0;
u.x = 0.0; u.y = 0.0; u.z = -1.0;
break;
}
z_rot (&o, roll); z_rot (&u, roll);
x_rot (&o, pitch); x_rot (&u, pitch);
y_rot (&o, yaw); y_rot (&u, yaw);
my_get_angles (&o, &u, a);
// normalise angles
while (a->yaw < 0.0) a->yaw += 360.0;
while (a->yaw > 360.0) a->yaw -= 360.0;
while (a->pitch < 0.0) a->pitch += 360.0;
while (a->pitch > 360.0) a->pitch -= 360.0;
while (a->roll < 0.0) a->roll += 360.0;
while (a->roll > 360.0) a->roll -= 360.0;
}
static int sw_cube_map_size;
static void
fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov)
{
int x, y;
int scrsize = sw_cube_map_size * sw_cube_map_size;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
double dx = x-width/2;
double dy = -(y-height/2);
double yaw = sqrt(dx*dx+dy*dy)*fov/((double)width);
double roll = -atan2(dy, dx);
double roll = atan2(dy, dx);
double sx = sin(yaw) * cos(roll);
double sy = sin(yaw) * sin(roll);
double sz = cos(yaw);
@ -1035,26 +927,26 @@ fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov)
else { side = ((sz > 0.0) ? BOX_FRONT : BOX_BEHIND); }
}
#define RC(x) ((x / 2.06) + 0.5)
#define R2(x) ((x / 2.03) + 0.5)
#define RC(x) ((x / 2) + 0.5)
#define R2(x) ((x / 2) + 0.5)
// scale up our vector [x,y,z] to the box
switch(side) {
case BOX_FRONT: xs = RC( sx / sz); ys = R2( sy / sz); break;
case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2( sy / -sz); break;
case BOX_LEFT: xs = RC( sz / -sx); ys = R2( sy / -sx); break;
case BOX_RIGHT: xs = RC(-sz / sx); ys = R2( sy / sx); break;
case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / -sy); break; //bot
case BOX_BOTTOM: xs = RC(-sx / sy); ys = R2( sz / -sy); break; //top??
case BOX_FRONT: xs = RC( sx / sz); ys = R2(-sy / sz); break;
case BOX_BEHIND: xs = RC(-sx / -sz); ys = R2(-sy / -sz); break;
case BOX_LEFT: xs = RC( sz / -sx); ys = R2(-sy / -sx); break;
case BOX_RIGHT: xs = RC(-sz / sx); ys = R2(-sy / sx); break;
case BOX_TOP: xs = RC( sx / sy); ys = R2( sz / sy); break;
case BOX_BOTTOM: xs = RC( sx / -sy); ys = R2( sz / sy); break;
}
if (xs < 0.0) xs = 0.0;
if (xs >= 1.0) xs = 0.999;
if (ys < 0.0) ys = 0.0;
if (ys >= 1.0) ys = 0.999;
*buf++ = scrp+(((int)(xs*(double)width))+
((int)(ys*(double)height))*width)+
side*width*height;
int sxs = xs * sw_cube_map_size;
int sys = ys * sw_cube_map_size;
*buf++ = scrp+side * scrsize + sys * sw_cube_map_size + sxs;
}
}
}
@ -1070,18 +962,45 @@ rendercopy (void *dest)
}
static void
renderside (byte* bufs, double yaw, double pitch, double roll, int side)
renderside (byte *bufs, int side)
{
struct my_angles a;
mat4f_t camera;
mat4f_t camera_inverse;
mat4f_t rotinv;
memcpy (camera, r_refdef.camera, sizeof (camera));
memcpy (camera_inverse, r_refdef.camera_inverse, sizeof (camera_inverse));
mmulf (r_refdef.camera, camera, box_rotations[side]);
mat4ftranspose (rotinv, box_rotations[side]);
mmulf (r_refdef.camera_inverse, rotinv, camera_inverse);
//FIXME see fixme in r_screen.c
r_refdef.frame.mat[0] = -r_refdef.camera[1];
r_refdef.frame.mat[1] = r_refdef.camera[0];
r_refdef.frame.mat[2] = r_refdef.camera[2];
r_refdef.frame.mat[3] = r_refdef.camera[3];
float fov_x = r_refdef.fov_x;
float fov_y = r_refdef.fov_y;
unsigned width = vid.width;
unsigned height = vid.height;
vrect_t rect = r_refdef.vrect;
r_refdef.fov_x = r_refdef.fov_y = 90;
r_refdef.vrect.x = r_refdef.vrect.y = 0;
r_refdef.vrect.height = r_refdef.vrect.width = sw_cube_map_size;
vid.height = vid.width = sw_cube_map_size;
R_ViewChanged ();
get_ypr (RAD(yaw), RAD(pitch), RAD(roll), side, &a);
if (side == BOX_RIGHT) { a.roll = -a.roll; a.pitch = -a.pitch; }
if (side == BOX_LEFT) { a.roll = -a.roll; a.pitch = -a.pitch; }
if (side == BOX_TOP) { a.yaw += 180.0; a.pitch = 180.0 - a.pitch; }
r_refdef.viewangles[YAW] = a.yaw;
r_refdef.viewangles[PITCH] = a.pitch;
r_refdef.viewangles[ROLL] = a.roll;
rendercopy (bufs);
r_refdef.vrect = rect;
vid.height = height;
vid.width = width;
r_refdef.fov_x = fov_x;
r_refdef.fov_y = fov_y;
memcpy (r_refdef.camera, camera, sizeof (camera));
memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse));
}
static void
@ -1099,14 +1018,12 @@ renderlookup (byte **offs, byte* bufs)
static void
R_RenderViewFishEye (void)
{
sw_cube_map_size = vid.width;
int width = vid.width; //r_refdef.vrect.width;
int height = vid.height; //r_refdef.vrect.height;
int scrsize = width*height;
int scrsize = sw_cube_map_size * sw_cube_map_size;
int fov = scr_ffov->int_val;
int views = scr_fviews->int_val;
double yaw = r_refdef.viewangles[YAW];
double pitch = r_refdef.viewangles[PITCH];
double roll = 0; //r_refdef.viewangles[ROLL];
static int pwidth = -1;
static int pheight = -1;
static int pfov = -1;
@ -1119,14 +1036,15 @@ R_RenderViewFishEye (void)
if (pwidth != width || pheight != height || pfov != fov) {
if (scrbufs) free (scrbufs);
if (offs) free (offs);
scrbufs = malloc (scrsize*6); // front|right|back|left|top|bottom
// front|right|back|left|top|bottom
scrbufs = malloc (scrsize*6);
SYS_CHECKMEM (scrbufs);
offs = malloc (scrsize*sizeof(byte*));
offs = malloc (width*height*sizeof(byte*));
SYS_CHECKMEM (offs);
pwidth = width;
pheight = height;
pfov = fov;
fisheyelookuptable (offs, width, height, scrbufs, ((double)fov)*M_PI/180.0);
fisheyelookuptable (offs, width, height, scrbufs, fov*M_PI/180.0);
}
if (views != pviews) {
@ -1135,19 +1053,27 @@ R_RenderViewFishEye (void)
}
switch (views) {
case 6: renderside (scrbufs+scrsize*2, yaw, pitch, roll, BOX_BEHIND);
case 5: renderside (scrbufs+scrsize*5, yaw, pitch, roll, BOX_BOTTOM);
case 4: renderside (scrbufs+scrsize*4, yaw, pitch, roll, BOX_TOP);
case 3: renderside (scrbufs+scrsize*3, yaw, pitch, roll, BOX_LEFT);
case 2: renderside (scrbufs+scrsize, yaw, pitch, roll, BOX_RIGHT);
default: renderside (scrbufs, yaw, pitch, roll, BOX_FRONT);
case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND);
case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM);
case 4: renderside (scrbufs + scrsize * BOX_TOP, BOX_TOP);
case 3: renderside (scrbufs + scrsize * BOX_LEFT, BOX_LEFT);
case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT);
default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT);
}
r_refdef.viewangles[YAW] = yaw;
r_refdef.viewangles[PITCH] = pitch;
r_refdef.viewangles[ROLL] = roll;
#if 0
memset (scrbufs + scrsize*0, 31, sw_cube_map_size);
memset (scrbufs + scrsize*1, 31, sw_cube_map_size);
memset (scrbufs + scrsize*2, 31, sw_cube_map_size);
memset (scrbufs + scrsize*3, 31, sw_cube_map_size);
memset (scrbufs + scrsize*4, 31, sw_cube_map_size);
memset (scrbufs + scrsize*5, 31, sw_cube_map_size);
for (int y = 0; y < sw_cube_map_size * 6; y++) {
scrbufs[y * sw_cube_map_size] = 31;
scrbufs[y * sw_cube_map_size + sw_cube_map_size - 1] = 31;
}
#endif
renderlookup (offs, scrbufs);
}*/
}
void
R_ClearState (void)

View file

@ -233,7 +233,9 @@ R_SetupFrame (void)
(h / (float) vid.height)));
R_ViewChanged ();
}
} else {
} else if (!scr_fisheye->int_val) {
//FIXME the above test shouldn't be necessary (this whole section
//is a bit of a mess, though)
r_refdef.vrect.x = vr_data.scr_view->xpos;
r_refdef.vrect.y = vr_data.scr_view->ypos;
r_refdef.vrect.width = vr_data.scr_view->xlen;