[renderer] Clean up FOV and viewport handling

Viewport and FOV updates are now separate so updating one doesn't cause
recalculations of the other. Also, perspective setup is now done
directly from the tangents of the half angles for fov_x and fov_y making
the renderers independent of fov/aspect mode. I imagine things are a bit
of a mess with view size changes, and especially screen size changes
(not supported yet anyway), and vulkan winds up updating its projection
matrices every frame, but everything that's expected to work does
(vulkan errors out for fisheye or warp due to frame buffer creation not
being supported yet).
This commit is contained in:
Bill Currie 2022-03-30 14:55:32 +09:00
parent 9fbd16be05
commit 495dd759f0
20 changed files with 224 additions and 258 deletions

View file

@ -5,8 +5,8 @@
void QFV_Orthographic (mat4f_t proj, float xmin, float xmax,
float ymin, float ymax, float znear, float zfar);
void QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect);
void QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect);
void QFV_Perspective (mat4f_t proj, float fov, float aspect);
// fov_x and fov_y are tan(fov/2) for x and y respectively
void QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y);
void QFV_PerspectiveCos (mat4f_t proj, float fov);
#endif//__QF_Vulkan_projection_h

View file

@ -78,7 +78,6 @@ typedef struct matrixctx_s {
struct vulkan_ctx_s;
struct qfv_renderframe_s;
void Vulkan_CalcProjectionMatrices (struct vulkan_ctx_s *ctx);
void Vulkan_CalcViewMatrix (struct vulkan_ctx_s *ctx);
void Vulkan_SetViewMatrix (struct vulkan_ctx_s *ctx, mat4f_t view);
void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky);

View file

@ -107,7 +107,6 @@ typedef struct vid_render_funcs_s {
void (*R_LoadSkys) (const char *);
void (*R_NewMap) (model_t *worldmodel, model_t **models, int num_models);
void (*R_LineGraph) (int x, int y, int *h_vals, int count, int height);
void (*R_ViewChanged) (void);
void (*begin_frame) (void);
void (*render_view) (void);
@ -122,6 +121,8 @@ typedef struct vid_render_funcs_s {
struct framebuffer_s *(*create_frame_buffer) (int width, int height);
void (*bind_framebuffer) (struct framebuffer_s *framebuffer);
void (*set_viewport) (const struct vrect_s *view);
// x and y are tan(f/2) for fov_x and fov_y
void (*set_fov) (float x, float y);
vid_model_funcs_t *model_funcs;
} vid_render_funcs_t;

View file

@ -166,8 +166,6 @@ typedef struct {
int ambientlight;
int drawflat;
float fov_x, fov_y;
struct model_s *worldmodel;
struct mleaf_s *viewleaf;
} refdef_t;

View file

@ -42,6 +42,7 @@ typedef void (*SCR_Func)(void);
// scr_funcs is a null terminated array
void SCR_UpdateScreen (struct transform_s *camera, double realtime,
SCR_Func *scr_funcs);
void SCR_SetFOV (float fov);
// control whether the 3d viewport is user-controlled or always fullscreen
void SCR_SetFullscreen (qboolean fullscreen);
void SCR_SetBottomMargin (int lines);

View file

@ -1,6 +1,8 @@
#ifndef __vid_gl_h
#define __vid_gl_h
#include "QF/simd/types.h"
// GL_context is a pointer to opaque data
typedef struct GL_context *GL_context;
@ -13,6 +15,8 @@ typedef struct gl_ctx_s {
void *(*get_proc_address) (const char *name, qboolean crit);
void (*end_rendering) (void);
mat4f_t projection;
int begun;
double start_time;
int brush_polys;

View file

@ -166,8 +166,6 @@ gl_FisheyeScreen (framebuffer_t *fb)
gl_framebuffer_t *buffer = fb->buffer;
qfglViewport (r_refdef.vrect.x, r_refdef.vrect.x,
r_refdef.vrect.width, r_refdef.vrect.height);
qfglMatrixMode (GL_PROJECTION);
qfglLoadIdentity ();
qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999);

View file

@ -229,40 +229,11 @@ R_DrawViewModel (void)
qfglDepthRange (gldepthmin, gldepthmax);
}
static void
R_Perspective (void)
{
float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height;
float f = 1 / tan (r_refdef.fov_y * M_PI / 360);
float neard, fard;
mat4f_t proj;
neard = r_nearclip->value;
fard = r_farclip->value;
// NOTE columns!
proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, f, 0, 0 };
proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 };
proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 };
// convert 0..1 depth buffer range to -1..1
static mat4f_t depth_range = {
{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 2, 0},
{ 0, 0,-1, 1},
};
mmulf (proj, depth_range, proj);
qfglMatrixMode (GL_PROJECTION);
qfglLoadMatrixf (&proj[0][0]);
}
static void
R_SetupGL (void)
{
R_Perspective ();
qfglMatrixMode (GL_PROJECTION);
qfglLoadMatrixf (&gl_ctx->projection[0][0]);
qfglFrontFace (GL_CW);

View file

@ -200,8 +200,3 @@ gl_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
register_textures (&models[i]->brush);
}
}
void
gl_R_ViewChanged (void)
{
}

View file

@ -68,33 +68,6 @@
mat4f_t glsl_projection;
mat4f_t glsl_view;
void
glsl_R_ViewChanged (void)
{
float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height;
float f = 1 / tan (r_refdef.fov_y * M_PI / 360);
float neard, fard;
vec4f_t *proj = glsl_projection;
neard = r_nearclip->value;
fard = r_farclip->value;
// NOTE columns!
proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, f, 0, 0 };
proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 };
proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 };
// convert 0..1 depth buffer range to -1..1
static mat4f_t depth_range = {
{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 2, 0},
{ 0, 0,-1, 1},
};
mmulf (proj, depth_range, proj);
}
static void
R_SetupView (void)
{
@ -164,6 +137,8 @@ glsl_R_RenderView (void)
return;
}
memcpy (glsl_projection, glsl_ctx->projection, sizeof (mat4f_t));
R_SetupView ();
glsl_R_DrawWorld ();
glsl_R_DrawSky ();

View file

@ -167,7 +167,7 @@ scr_fov_f (cvar_t *var)
if (fov != var->value) {
Cvar_SetValue (var, fov);
} else {
r_data->vid->recalc_refdef = 1;
SCR_SetFOV (var->value);
}
}

View file

@ -69,6 +69,9 @@ static qpic_t *scr_turtle;
static framebuffer_t *fisheye_cube_map;
static framebuffer_t *warp_buffer;
static float fov_x, fov_y;
static float tan_fov_x, tan_fov_y;
static mat4f_t box_rotations[] = {
[BOX_FRONT] = {
{ 1, 0, 0, 0}, // front
@ -146,8 +149,8 @@ R_SetVrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj)
set_vrect (vrectin, vrect, lineadj);
}
static void
set_fov (float fov)
void
SCR_SetFOV (float fov)
{
refdef_t *refdef = r_data->refdef;
@ -158,8 +161,11 @@ set_fov (float fov)
double w = refdef->vrect.width;
double h = refdef->vrect.height;
refdef->fov_x = fov;
refdef->fov_y = 360 * atan2 (s * h, c * w) / M_PI;
fov_x = fov;
fov_y = 360 * atan2 (s * h, c * w) / M_PI;
tan_fov_x = s / c;
tan_fov_y = (s * h) / (c * w);
r_funcs->set_fov (tan_fov_x, tan_fov_y);
}
static void
@ -172,9 +178,6 @@ SCR_CalcRefdef (void)
view_setgeometry (view, rect->x, rect->y, rect->width, rect->height);
// notify the refresh of the change
r_funcs->R_ViewChanged ();
// force a background redraw
r_data->scr_fullupdate = 0;
}
@ -210,10 +213,8 @@ render_side (int side)
r_refdef.frame.mat[3] = r_refdef.camera[3];
refdef_t *refdef = r_data->refdef;
R_SetFrustum (refdef->frustum, &refdef->frame,
refdef->fov_x, refdef->fov_y);
R_SetFrustum (refdef->frustum, &refdef->frame, 90, 90);
r_data->refdef->fov_x = r_data->refdef->fov_y = 90;
r_funcs->bind_framebuffer (&fisheye_cube_map[side]);
render_scene ();
@ -256,8 +257,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
refdef->frame.mat[1] = refdef->camera[0];
refdef->frame.mat[2] = refdef->camera[2];
refdef->frame.mat[3] = refdef->camera[3];
R_SetFrustum (refdef->frustum, &refdef->frame,
refdef->fov_x, refdef->fov_y);
R_SetFrustum (refdef->frustum, &refdef->frame, fov_x, fov_y);
r_data->realtime = realtime;
scr_copytop = r_data->scr_copyeverything = 0;
@ -292,6 +292,7 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs)
int side = fisheye_cube_map->width;
vrect_t feye = { 0, 0, side, side };
r_funcs->set_viewport (&feye);
r_funcs->set_fov (1, 1); //FIXME shouldn't be every frame (2d stuff)
switch (scr_fviews->int_val) {
case 6: render_side (BOX_BEHIND);
case 5: render_side (BOX_BOTTOM);
@ -335,7 +336,7 @@ update_vrect (void)
vrect.height = r_data->vid->height;
set_vrect (&vrect, &refdef->vrect, r_data->lineadj);
set_fov (scr_fov->value);
SCR_SetFOV (scr_fov->value);
}
void

View file

@ -67,7 +67,6 @@ qboolean r_drawculledpolys;
qboolean r_worldpolysbacktofront;
qboolean r_recursiveaffinetriangles = true;
int r_pixbytes = 1;
float r_aliasuvscale = 1.0;
int r_outofsurfaces;
int r_outofedges;
@ -211,113 +210,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
r_viewchanged = false;
}
/*
R_ViewChanged
Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
*/
void
R_ViewChanged (void)
{
int i;
float res_scale;
r_viewchanged = true;
#define SHIFT20(x) (((x) << 20) + (1 << 19) - 1)
r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.vrectx_adj_shift20 = SHIFT20 (r_refdef.vrect.x);
r_refdef.vrectright_adj_shift20 = SHIFT20 (r_refdef.vrectright);
r_refdef.fvrectx = (float) r_refdef.vrect.x;
r_refdef.fvrecty = (float) r_refdef.vrect.y;
r_refdef.fvrectright = (float) r_refdef.vrectright;
r_refdef.fvrectbottom = (float) r_refdef.vrectbottom;
r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5;
r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5;
r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5;
r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5;
int aleft = r_refdef.vrect.x * r_aliasuvscale;
int atop = r_refdef.vrect.y * r_aliasuvscale;
int awidth = r_refdef.vrect.width * r_aliasuvscale;
int aheight = r_refdef.vrect.height * r_aliasuvscale;
r_refdef.aliasvrectleft = aleft;
r_refdef.aliasvrecttop = atop;
r_refdef.aliasvrectright = aleft + awidth;
r_refdef.aliasvrectbottom = atop + aheight;
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = r_refdef.vrect.width * XCENTERING + r_refdef.vrect.x - 0.5;
ycenter = r_refdef.vrect.height * YCENTERING + r_refdef.vrect.y - 0.5;
aliasxcenter = xcenter * r_aliasuvscale;
aliasycenter = ycenter * r_aliasuvscale;
pixelAspect = 1;//FIXME vid.aspect;
float aspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height;
// 320*200 1.0 pixelAspect = 1.6 aspect
// 320*240 1.0 pixelAspect = 1.3333 aspect
// proper 320*200 pixelAspect = 0.8333333
float hFOV = 2.0 * tan (r_refdef.fov_x / 360 * M_PI);
float vFOV = hFOV / aspect;
// general perspective scaling
xscale = r_refdef.vrect.width / hFOV;
yscale = xscale * pixelAspect;
xscaleinv = 1.0 / xscale;
yscaleinv = 1.0 / yscale;
// perspective scaling for alias models
aliasxscale = xscale * r_aliasuvscale;
aliasyscale = yscale * r_aliasuvscale;
// perspective scaling for paricle position
xscaleshrink = (r_refdef.vrect.width - 6) / hFOV;
yscaleshrink = xscaleshrink * pixelAspect;
// left side clip
screenedge[0].normal[0] = -1.0 / (XCENTERING * hFOV);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;
// right side clip
screenedge[1].normal[0] = 1.0 / ((1.0 - XCENTERING) * hFOV);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;
// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (YCENTERING * vFOV);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;
// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0 - YCENTERING) * vFOV);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;
for (i = 0; i < 4; i++)
VectorNormalize (screenedge[i].normal);
res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) /
(320.0 * 152.0)) * (2.0 / hFOV);
r_aliastransition = r_aliastransbase->value * res_scale;
r_resfudge = r_aliastransadj->value * res_scale;
D_ViewChanged ();
}
void
R_SetColormap (const byte *cmap)
{

View file

@ -421,19 +421,43 @@ gl_bind_framebuffer (framebuffer_t *framebuffer)
vrect_t r = { 0, 0, width, height };
R_SetVrect (&r, &r_refdef.vrect, 0);
gl_R_ViewChanged ();
}
static void
gl_set_viewport (const vrect_t *view)
{
int x = view->x;
int y = vid.height - (view->y + view->height);//FIXME vid.height
int y = vid.height - (view->y + view->height); //FIXME vid.height
int w = view->width;
int h = view->height;
qfglViewport (x, y, w, h);
}
static void
gl_set_fov (float x, float y)
{
float neard, fard;
mat4f_t proj;
neard = r_nearclip->value;
fard = r_farclip->value;
// NOTE columns!
proj[0] = (vec4f_t) { 1/x, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, 1/y, 0, 0 };
proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 };
proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 };
// convert 0..1 depth buffer range to -1..1
static mat4f_t depth_range = {
{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 2, 0},
{ 0, 0,-1, 1},
};
mmulf (gl_ctx->projection, depth_range, proj);
}
vid_render_funcs_t gl_vid_render_funcs = {
gl_vid_render_init,
gl_Draw_Character,
@ -465,7 +489,6 @@ vid_render_funcs_t gl_vid_render_funcs = {
gl_R_LoadSkys,
gl_R_NewMap,
gl_R_LineGraph,
gl_R_ViewChanged,
gl_begin_frame,
gl_render_view,
gl_R_RenderEntities,
@ -479,6 +502,7 @@ vid_render_funcs_t gl_vid_render_funcs = {
gl_create_frame_buffer,
gl_bind_framebuffer,
gl_set_viewport,
gl_set_fov,
&model_funcs
};

View file

@ -368,19 +368,43 @@ glsl_bind_framebuffer (framebuffer_t *framebuffer)
vrect_t r = { 0, 0, width, height };
R_SetVrect (&r, &r_refdef.vrect, 0);
glsl_R_ViewChanged ();
}
static void
glsl_set_viewport (const vrect_t *view)
{
int x = view->x;
int y = vid.height - (view->y + view->height);//FIXME vid.height
int y = vid.height - (view->y + view->height); //FIXME vid.height
int w = view->width;
int h = view->height;
qfeglViewport (x, y, w, h);
}
static void
glsl_set_fov (float x, float y)
{
float neard, fard;
mat4f_t proj;
neard = r_nearclip->value;
fard = r_farclip->value;
// NOTE columns!
proj[0] = (vec4f_t) { 1/x, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, 1/y, 0, 0 };
proj[2] = (vec4f_t) { 0, 0, (fard) / (fard - neard), 1 };
proj[3] = (vec4f_t) { 0, 0, (fard * neard) / (neard - fard), 0 };
// convert 0..1 depth buffer range to -1..1
static mat4f_t depth_range = {
{ 1, 0, 0, 0},
{ 0, 1, 0, 0},
{ 0, 0, 2, 0},
{ 0, 0,-1, 1},
};
mmulf (glsl_ctx->projection, depth_range, proj);
}
vid_render_funcs_t glsl_vid_render_funcs = {
glsl_vid_render_init,
glsl_Draw_Character,
@ -412,7 +436,6 @@ vid_render_funcs_t glsl_vid_render_funcs = {
glsl_R_LoadSkys,
glsl_R_NewMap,
glsl_R_LineGraph,
glsl_R_ViewChanged,
glsl_begin_frame,
glsl_render_view,
glsl_R_RenderEntities,
@ -426,6 +449,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
glsl_create_frame_buffer,
glsl_bind_framebuffer,
glsl_set_viewport,
glsl_set_fov,
&model_funcs
};

View file

@ -45,6 +45,8 @@
sw_ctx_t *sw_ctx;
static float r_aliasuvscale = 1.0;
static void
sw_vid_render_choose_visual (void *data)
{
@ -258,6 +260,8 @@ sw_create_frame_buffer (int width, int height)
return fb;
}
static void sw_set_viewport (const vrect_t *view);
static void
sw_bind_framebuffer (framebuffer_t *framebuffer)
{
@ -295,14 +299,116 @@ sw_bind_framebuffer (framebuffer_t *framebuffer)
if (changed) {
vrect_t r = { 0, 0, framebuffer->width, framebuffer->height };
R_SetVrect (&r, &r_refdef.vrect, 0);
R_ViewChanged ();
sw_set_viewport (&r);
}
}
static void
sw_set_viewport (const vrect_t *view)
{
#define SHIFT20(x) (((x) << 20) + (1 << 19) - 1)
r_refdef.vrectright = view->x + view->width;
r_refdef.vrectbottom = view->y + view->height;
r_refdef.vrectx_adj_shift20 = SHIFT20 (view->x);
r_refdef.vrectright_adj_shift20 = SHIFT20 (r_refdef.vrectright);
r_refdef.fvrectx = (float) view->x;
r_refdef.fvrecty = (float) view->y;
r_refdef.fvrectright = (float) r_refdef.vrectright;
r_refdef.fvrectbottom = (float) r_refdef.vrectbottom;
r_refdef.fvrectx_adj = (float) view->x - 0.5;
r_refdef.fvrecty_adj = (float) view->y - 0.5;
r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5;
r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5;
int aleft = view->x * r_aliasuvscale;
int atop = view->y * r_aliasuvscale;
int awidth = view->width * r_aliasuvscale;
int aheight = view->height * r_aliasuvscale;
r_refdef.aliasvrectleft = aleft;
r_refdef.aliasvrecttop = atop;
r_refdef.aliasvrectright = aleft + awidth;
r_refdef.aliasvrectbottom = atop + aheight;
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter = view->width * XCENTERING + view->x - 0.5;
ycenter = view->height * YCENTERING + view->y - 0.5;
aliasxcenter = xcenter * r_aliasuvscale;
aliasycenter = ycenter * r_aliasuvscale;
r_refdef.vrect.x = view->x;
r_refdef.vrect.y = view->y;
r_refdef.vrect.width = view->width;
r_refdef.vrect.height = view->height;
D_ViewChanged ();
}
static void
sw_set_fov (float x, float y)
{
int i;
float res_scale;
r_viewchanged = true;
// 320*200 1.0 pixelAspect = 1.6 aspect
// 320*240 1.0 pixelAspect = 1.3333 aspect
// proper 320*200 pixelAspect = 0.8333333
pixelAspect = 1;//FIXME vid.aspect;
float hFOV = 2 * x;
float vFOV = 2 * y * pixelAspect;
// general perspective scaling
xscale = r_refdef.vrect.width / hFOV;
yscale = xscale * pixelAspect;
xscaleinv = 1.0 / xscale;
yscaleinv = 1.0 / yscale;
// perspective scaling for alias models
aliasxscale = xscale * r_aliasuvscale;
aliasyscale = yscale * r_aliasuvscale;
// perspective scaling for paricle position
xscaleshrink = (r_refdef.vrect.width - 6) / hFOV;
yscaleshrink = xscaleshrink * pixelAspect;
// left side clip
screenedge[0].normal[0] = -1.0 / (XCENTERING * hFOV);
screenedge[0].normal[1] = 0;
screenedge[0].normal[2] = 1;
screenedge[0].type = PLANE_ANYZ;
// right side clip
screenedge[1].normal[0] = 1.0 / ((1.0 - XCENTERING) * hFOV);
screenedge[1].normal[1] = 0;
screenedge[1].normal[2] = 1;
screenedge[1].type = PLANE_ANYZ;
// top side clip
screenedge[2].normal[0] = 0;
screenedge[2].normal[1] = -1.0 / (YCENTERING * vFOV);
screenedge[2].normal[2] = 1;
screenedge[2].type = PLANE_ANYZ;
// bottom side clip
screenedge[3].normal[0] = 0;
screenedge[3].normal[1] = 1.0 / ((1.0 - YCENTERING) * vFOV);
screenedge[3].normal[2] = 1;
screenedge[3].type = PLANE_ANYZ;
for (i = 0; i < 4; i++)
VectorNormalize (screenedge[i].normal);
res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) /
(320.0 * 152.0)) * (2.0 / hFOV);
r_aliastransition = r_aliastransbase->value * res_scale;
r_resfudge = r_aliastransadj->value * res_scale;
}
vid_render_funcs_t sw_vid_render_funcs = {
@ -336,7 +442,6 @@ vid_render_funcs_t sw_vid_render_funcs = {
R_LoadSkys,
R_NewMap,
R_LineGraph,
R_ViewChanged,
sw_begin_frame,
sw_render_view,
R_DrawEntitiesOnList,
@ -350,6 +455,7 @@ vid_render_funcs_t sw_vid_render_funcs = {
sw_create_frame_buffer,
sw_bind_framebuffer,
sw_set_viewport,
sw_set_fov,
&model_funcs
};

View file

@ -57,6 +57,7 @@
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/projection.h"
#include "QF/Vulkan/renderpass.h"
#include "QF/Vulkan/swapchain.h"
#include "QF/ui/view.h"
@ -247,12 +248,6 @@ vulkan_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, in
Vulkan_Draw_SubPic (x, y, pic, srcx, srcy, width, height, vulkan_ctx);
}
static void
vulkan_R_ViewChanged (void)
{
Vulkan_CalcProjectionMatrices (vulkan_ctx);
}
static void
vulkan_begin_frame (void)
{
@ -316,6 +311,15 @@ vulkan_post_process (framebuffer_t *src)
static void
vulkan_set_2d (int scaled)
{
//FIXME this should not be done every frame
__auto_type mctx = vulkan_ctx->matrix_context;
__auto_type mat = &mctx->matrices;
int width = vid.conview->xlen; //FIXME vid
int height = vid.conview->ylen;
QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999);
mctx->dirty = mctx->frames.size;
}
static void
@ -445,6 +449,20 @@ vulkan_set_viewport (const vrect_t *view)
{
}
static void
vulkan_set_fov (float x, float y)
{
if (!vulkan_ctx || !vulkan_ctx->matrix_context) {
return;
}
__auto_type mctx = vulkan_ctx->matrix_context;
__auto_type mat = &mctx->matrices;
QFV_PerspectiveTan (mat->Projection3d, x, y);
mctx->dirty = mctx->frames.size;
}
static int
is_bgr (VkFormat format)
{
@ -715,7 +733,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
vulkan_R_LoadSkys,
vulkan_R_NewMap,
vulkan_R_LineGraph,
vulkan_R_ViewChanged,
vulkan_begin_frame,
vulkan_render_view,
vulkan_draw_entities,
@ -729,6 +746,7 @@ vid_render_funcs_t vulkan_vid_render_funcs = {
vulkan_create_frame_buffer,
vulkan_bind_framebuffer,
vulkan_set_viewport,
vulkan_set_fov,
&model_funcs
};

View file

@ -68,30 +68,24 @@ QFV_Orthographic (mat4f_t proj, float xmin, float xmax, float ymin, float ymax,
}
void
QFV_PerspectiveTan (mat4f_t proj, float fov, float aspect)
QFV_PerspectiveTan (mat4f_t proj, float fov_x, float fov_y)
{
float f = 1 / fov;
float neard, fard;
neard = r_nearclip->value;
fard = r_farclip->value;
proj[0] = (vec4f_t) { f / aspect, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, f, 0, 0 };
proj[0] = (vec4f_t) { 1 / fov_x, 0, 0, 0 };
proj[1] = (vec4f_t) { 0, 1 / fov_y, 0, 0 };
proj[2] = (vec4f_t) { 0, 0, fard / (fard - neard), 1 };
proj[3] = (vec4f_t) { 0, 0, (neard * fard) / (neard - fard), 0 };
}
void
QFV_PerspectiveCos (mat4f_t proj, float fov, float aspect)
QFV_PerspectiveCos (mat4f_t proj, float fov)
{
// square first for auto-abs (no support for > 180 degree fov)
fov = fov * fov;
QFV_PerspectiveTan (proj, sqrt ((1 - fov) / fov), aspect);
}
void
QFV_Perspective (mat4f_t proj, float fov, float aspect)
{
QFV_PerspectiveTan (proj, tan (fov * M_PI / 360), aspect);
float t = sqrt ((1 - fov) / fov);
QFV_PerspectiveTan (proj, t, t);
}

View file

@ -711,7 +711,7 @@ create_light_matrices (lightingctx_t *lctx)
mat4fidentity (proj);
break;
case ST_PLANE:
QFV_PerspectiveCos (proj, light->cone, 1);
QFV_PerspectiveCos (proj, light->cone);
break;
}
mmulf (lctx->lightmats.a[i], proj, view);

View file

@ -169,41 +169,6 @@ Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame)
QFV_PacketSubmit (packet);
}
void
Vulkan_CalcProjectionMatrices (vulkan_ctx_t *ctx)
{
__auto_type mctx = ctx->matrix_context;
__auto_type mat = &mctx->matrices;
int width = vid.conview->xlen;
int height = vid.conview->ylen;
QFV_Orthographic (mat->Projection2d, 0, width, 0, height, 0, 99999);
float aspect = (float) r_refdef.vrect.width / r_refdef.vrect.height;
QFV_Perspective (mat->Projection3d, r_refdef.fov_y, aspect);
#if 0
Sys_MaskPrintf (SYS_vulkan, "ortho:\n");
Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n",
QuatExpand (mat->Projection2d + 0));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n",
QuatExpand (mat->Projection2d + 4));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n",
QuatExpand (mat->Projection2d + 8));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n",
QuatExpand (mat->Projection2d + 12));
Sys_MaskPrintf (SYS_vulkan, "presp:\n");
Sys_MaskPrintf (SYS_vulkan, " [[%g, %g, %g, %g],\n",
QuatExpand (mat->Projection3d + 0));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n",
QuatExpand (mat->Projection3d + 4));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g],\n",
QuatExpand (mat->Projection3d + 8));
Sys_MaskPrintf (SYS_vulkan, " [%g, %g, %g, %g]]\n",
QuatExpand (mat->Projection3d + 12));
#endif
mctx->dirty = mctx->frames.size;
}
void
Vulkan_Matrix_Init (vulkan_ctx_t *ctx)
{