mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 15:01:41 +00:00
[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:
parent
9fbd16be05
commit
495dd759f0
20 changed files with 224 additions and 258 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue