render: split mvp matrix to separate model,view,projection matrices

This will help with RTX model transformations.
This commit is contained in:
Ivan 'provod' Avdeev 2021-03-13 13:35:50 -08:00
parent a039e7e5ae
commit 7fa3f2dc8d
6 changed files with 82 additions and 85 deletions

View File

@ -1,6 +1,7 @@
## 2021-03-13
- [x] rtx: blend normals according to barycentrics
- [x] rtx: (debug/dev) shader reload
- [x] rtx: make projection matrix independent render global/current/static state
- [ ] rtx: model matrices
- [ ] rtx: path tracing
- [ ] rtx: textures
@ -16,7 +17,6 @@
- [ ] restore render debug labels
- [ ] make 2nd commad buffer for resource upload
- [ ] fix sprite blending; there are commented out functions that we really need (see tunnel before the helicopter in the very beginning)
- [ ] RTX: make projection matrix independent render global/current/static state
- [ ] fix projection matrix differences w/ gl render
- [ ] bad condition for temp vs map-permanent buffer error message
- [ ] draw more types of beams
@ -37,11 +37,10 @@
- [ ] flashlight
- [ ] screenshot
- [ ] fog
- [ ] RTX
- [ ] studio models survive NewMap; need to compactify buffers after removing all brushes
- [ ] sometimes it gets very slow (1fps) when ran under lldb (only on stream?)
- [ ] optimize perf: cmdbuf managements and semaphores, upload to gpu, ...
- [ ] RTX: studio models should not pre-transform vertices with modelView matrix
- [ ] rtx: studio models should not pre-transform vertices with modelView matrix
# Someday
- [ ] start building command buffers in beginframe

View File

@ -556,14 +556,14 @@ static void R_DrawCylinder( vec3_t source, vec3_t delta, float width, float scal
length = VectorLength( delta ) * 0.01f;
if( length < 0.5f ) length = 0.5f; // don't lose all of the noise/texture on short beams
div = 1.0f / (segments - 1);
vStep = length * div; // texture length texels per space pixel
// Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture)
vLast = fmod( freq * speed, 1 );
scale = scale * length;
for ( i = 0; i < segments; i++ )
{
float s, c;
@ -670,7 +670,7 @@ static void R_DrawBeamFollow( BEAM *pbeam, float frametime )
// Build point along noraml line (normal is -y, x)
VectorScale( g_camera.vup, tmp[0], normal ); // Build point along normal line (normal is -y, x)
VectorMA( normal, tmp[1], g_camera.vright, normal );
// Make a wide line
VectorMA( delta, pbeam->width, normal, last1 );
VectorMA( delta, -pbeam->width, normal, last2 );
@ -704,7 +704,7 @@ static void R_DrawBeamFollow( BEAM *pbeam, float frametime )
// Make a wide line
VectorMA( particles->org, pbeam->width, normal, last1 );
VectorMA( particles->org, -pbeam->width, normal, last2 );
vLast += vStep; // Advance texture scroll (v axis only)
if( particles->next != NULL )
@ -755,13 +755,13 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
VectorClear( screenLast );
segments = segments * M_PI_F;
if( segments > NOISE_DIVISIONS * 8 )
segments = NOISE_DIVISIONS * 8;
length = VectorLength( delta ) * 0.01f * M_PI_F;
if( length < 0.5f ) length = 0.5f; // Don't lose all of the noise/texture on short beams
div = 1.0f / ( segments - 1 );
vStep = length * div / 8.0f; // texture length texels per space pixel
@ -779,7 +779,7 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
VectorCopy( delta, xaxis );
radius = VectorLength( xaxis );
// cull beamring
// --------------------------------
// Compute box center +/- radius
@ -796,7 +796,7 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
return;
}
VectorSet( yaxis, xaxis[1], -xaxis[0], 0.0f );
VectorSet( yaxis, xaxis[1], -xaxis[0], 0.0f );
VectorNormalize( yaxis );
VectorScale( yaxis, radius, yaxis );
@ -807,7 +807,7 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
fraction = i * div;
SinCos( fraction * M_PI2_F, &x, &y );
VectorMAMAM( x, xaxis, y, yaxis, 1.0f, center, point );
VectorMAMAM( x, xaxis, y, yaxis, 1.0f, center, point );
// distort using noise
factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale;
@ -817,7 +817,7 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale;
factor *= cos( fraction * M_PI_F * 24 + freq );
VectorMA( point, factor, g_camera.vright, point );
// Transform point into screen space
TriWorldToScreen( point, screen );
@ -833,7 +833,7 @@ static void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitud
// Build point along normal line (normal is -y, x)
VectorScale( g_camera.vup, tmp[0], normal );
VectorMA( normal, tmp[1], g_camera.vright, normal );
// Make a wide line
VectorMA( point, width, normal, last1 );
VectorMA( point, -width, normal, last2 );
@ -1104,17 +1104,9 @@ void R_BeamDraw( BEAM *pbeam, float frametime )
else
color[3] = pbeam->brightness;
{
matrix4x4 tmp;
const matrix4x4 vk_proj_fixup = {
{1, 0, 0, 0},
{0, -1, 0, 0},
{0, 0, .5, 0},
{0, 0, .5, 1}
};
Matrix4x4_Concat( tmp, vk_proj_fixup, g_camera.worldviewProjectionMatrix);
VK_RenderStateSetMatrix( tmp );
}
// FIXME VK what is our vk_render matrix state now? do we have all matrices set properly?
// TODO this can be done only once for all beams, i.e. before calling CL_DrawEFX
VK_RenderStateSetMatrixModel( matrix4x4_identity );
// TODO gl renderer has per-vertex color that is updated using brightness and whatever
VK_RenderStateSetColor( color[0], color[1], color[2], color[3] );

View File

@ -20,8 +20,6 @@ typedef struct vk_global_camera_s {
matrix4x4 projectionMatrix;
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
matrix4x4 projectionMatrixVk;
} vk_global_camera_t;
extern vk_global_camera_t g_camera;

View File

@ -447,18 +447,17 @@ static struct {
draw_command_t draw_commands[MAX_DRAW_COMMANDS];
int num_draw_commands;
// FIXME vk_rtx-specific
struct {
matrix4x4 proj_inv, view_inv;
} rtx;
matrix4x4 model, view, projection;
} g_render_state;
enum {
UNIFORM_UNSET = 0,
UNIFORM_SET_COLOR = 1,
UNIFORM_SET_MATRIX = 2,
UNIFORM_SET_ALL = UNIFORM_SET_COLOR | UNIFORM_SET_MATRIX,
UNIFORM_UPLOADED = 4,
UNIFORM_SET_MATRIX_MODEL = 2,
UNIFORM_SET_MATRIX_VIEW = 4,
UNIFORM_SET_MATRIX_PROJECTION = 8,
UNIFORM_SET_ALL = UNIFORM_SET_COLOR | UNIFORM_SET_MATRIX_MODEL | UNIFORM_SET_MATRIX_VIEW | UNIFORM_SET_MATRIX_PROJECTION,
UNIFORM_UPLOADED = 16,
};
void VK_RenderBegin( void ) {
@ -481,26 +480,44 @@ void VK_RenderStateSetColor( float r, float g, float b, float a )
g_render_state.dirty_uniform_data.color[3] = a;
}
void VK_RenderStateSetMatrix( const matrix4x4 mvp )
void VK_RenderStateSetMatrixProjection(const matrix4x4 projection)
{
g_render_state.uniform_data_set_mask |= UNIFORM_SET_MATRIX;
Matrix4x4_ToArrayFloatGL( mvp, (float*)g_render_state.dirty_uniform_data.mvp );
g_render_state.uniform_data_set_mask |= UNIFORM_SET_MATRIX_PROJECTION;
// Vulkan has Y pointing down, and z should end up in (0, 1)
// NOTE this matrix is row-major
static const matrix4x4 vk_proj_fixup = {
{1, 0, 0, 0},
{0, -1, 0, 0},
{0, 0, .5, .5},
{0, 0, 0, 1}
};
Matrix4x4_Concat( g_render_state.projection, vk_proj_fixup, projection );
}
void VK_RenderStateSetProjectionMatrix(const matrix4x4 proj_vk)
void VK_RenderStateSetMatrixView(const matrix4x4 view)
{
matrix4x4 proj_inv_row;
Matrix4x4_Invert_Full(proj_inv_row, proj_vk);
Matrix4x4_ToArrayFloatGL(proj_inv_row, (float*)g_render_state.rtx.proj_inv);
g_render_state.uniform_data_set_mask |= UNIFORM_SET_MATRIX_VIEW;
Matrix4x4_Copy(g_render_state.view, view);
}
void VK_RenderStateSetViewMatrix(const matrix4x4 view)
void VK_RenderStateSetMatrixModel( const matrix4x4 model )
{
// TODO there's a more efficient way to construct an inverse view matrix
// from vforward/right/up vectors and origin in g_camera
matrix4x4 tmp;
Matrix4x4_Invert_Full(tmp, view);
Matrix4x4_ToArrayFloatGL( tmp, (float*)g_render_state.rtx.view_inv);
g_render_state.uniform_data_set_mask |= UNIFORM_SET_MATRIX_MODEL;
Matrix4x4_Copy(g_render_state.model, model);
// Assume that projection and view matrices are already properly set
ASSERT(g_render_state.uniform_data_set_mask & UNIFORM_SET_MATRIX_VIEW);
ASSERT(g_render_state.uniform_data_set_mask & UNIFORM_SET_MATRIX_PROJECTION);
{
matrix4x4 mv, mvp;
// TODO this can be cached (on a really slow device?)
Matrix4x4_Concat(mv, g_render_state.view, g_render_state.model);
Matrix4x4_Concat(mvp, g_render_state.projection, mv);
Matrix4x4_ToArrayFloatGL(mvp, (float*)g_render_state.dirty_uniform_data.mvp);
}
}
static uint32_t allocUniform( uint32_t size, uint32_t alignment ) {
@ -715,7 +732,6 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
}
{
float *matrices = NULL;
const vk_ray_scene_render_args_t args = {
.cmdbuf = cmdbuf,
.dst = {
@ -727,8 +743,8 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
// FIXME this should really be in vk_rtx, calling vk_render(or what?) to alloc slot for it
.ubo = {
.buffer = g_render.uniform_buffer.buffer,
.offset = allocUniform(sizeof(float) * 16 * 2, 16 * sizeof(float)),
.size = sizeof(float) * 16 * 2,
.offset = allocUniform(sizeof(matrix4x4) * 2, sizeof(matrix4x4)),
.size = sizeof(matrix4x4) * 2,
},
.dlights = {
@ -748,8 +764,17 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
return;
}
matrices = (float*)((byte*)g_render.uniform_buffer.mapped + args.ubo.offset);
memcpy(matrices, &g_render_state.rtx, sizeof(g_render_state.rtx));
{
matrix4x4 *ubo_matrices = (matrix4x4*)((byte*)g_render.uniform_buffer.mapped + args.ubo.offset);
matrix4x4 proj_inv, view_inv;
Matrix4x4_Invert_Full(proj_inv, g_render_state.projection);
Matrix4x4_ToArrayFloatGL(proj_inv, (float*)ubo_matrices[0]);
// TODO there's a more efficient way to construct an inverse view matrix
// from vforward/right/up vectors and origin in g_camera
Matrix4x4_Invert_Full(view_inv, g_render_state.view);
Matrix4x4_ToArrayFloatGL(view_inv, (float*)ubo_matrices[1]);
}
VK_RaySceneEnd(&args);
}

View File

@ -43,11 +43,10 @@ void VK_RenderBufferPrintStats( void );
// centralize this global state in here
void VK_RenderStateSetColor( float r, float g, float b, float a );
// TODO void VK_RenderStateGetColor( vec4_t color );
void VK_RenderStateSetMatrix( const matrix4x4 mvp );
// TODO: set projection and mv matrices separately
void VK_RenderStateSetProjectionMatrix(const matrix4x4 proj);
void VK_RenderStateSetViewMatrix(const matrix4x4 view);
void VK_RenderStateSetMatrixProjection(const matrix4x4 proj);
void VK_RenderStateSetMatrixView(const matrix4x4 view);
void VK_RenderStateSetMatrixModel(const matrix4x4 model);
// TODO is this a good place?
typedef struct vk_vertex_s {

View File

@ -482,7 +482,7 @@ int CL_FxBlend( cl_entity_t *e ) // FIXME do R_SetupFrustum: , vec3_t vforward )
}
// Analagous to R_SetupRefParams, R_SetupFrustum in GL/Soft renderers
static void setupCamera( const ref_viewpass_t *rvp, matrix4x4 mvp )
static void setupCamera( const ref_viewpass_t *rvp )
{
/* FIXME VK unused?
RI.params = RP_NONE;
@ -538,25 +538,12 @@ static void setupCamera( const ref_viewpass_t *rvp, matrix4x4 mvp )
R_SetupModelviewMatrix( g_camera.modelviewMatrix );
Matrix4x4_Concat( g_camera.worldviewProjectionMatrix, g_camera.projectionMatrix, g_camera.modelviewMatrix );
{
// Vulkan has Y pointing down, and z should end up in (0, 1)
// NOTE this matrix is row-major
const matrix4x4 vk_proj_fixup = {
{1, 0, 0, 0},
{0, -1, 0, 0},
{0, 0, .5, .5},
{0, 0, 0, 1}
};
Matrix4x4_Concat( mvp, vk_proj_fixup, g_camera.worldviewProjectionMatrix);
Matrix4x4_Concat( g_camera.projectionMatrixVk, vk_proj_fixup, g_camera.projectionMatrix);
}
}
static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
static void drawEntity( cl_entity_t *ent, int render_mode )
{
const model_t *mod = ent->model;
matrix4x4 model, ent_mvp;
matrix4x4 model;
float alpha;
if (!mod)
@ -600,18 +587,17 @@ static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
{
case mod_brush:
R_RotateForEntity( model, ent );
Matrix4x4_Concat( ent_mvp, mvp, model );
VK_RenderStateSetMatrix( ent_mvp );
VK_RenderStateSetMatrixModel( model );
VK_BrushDrawModel( ent, render_mode );
break;
case mod_studio:
VK_RenderStateSetMatrix( mvp );
VK_RenderStateSetMatrixModel( matrix4x4_identity );
VK_StudioDrawModel( ent, render_mode );
break;
case mod_sprite:
VK_RenderStateSetMatrix( mvp );
VK_RenderStateSetMatrixModel( matrix4x4_identity );
VK_SpriteDrawModel( ent );
break;
@ -625,23 +611,22 @@ static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
static float g_frametime = 0;
void VK_SceneRender( const ref_viewpass_t *rvp )
{
matrix4x4 mvp;
int current_pipeline_index = kRenderNormal;
g_frametime = /*FIXME VK RP_NORMALPASS( )) ? */
gpGlobals->time - gpGlobals->oldtime
/* FIXME VK : 0.f */;
setupCamera( rvp, mvp );
setupCamera( rvp );
VK_RenderStateSetProjectionMatrix(g_camera.projectionMatrixVk);
VK_RenderStateSetViewMatrix(g_camera.modelviewMatrix);
VK_RenderStateSetMatrixProjection( g_camera.projectionMatrix );
VK_RenderStateSetMatrixView( g_camera.modelviewMatrix );
VK_RenderStateSetMatrixModel( matrix4x4_identity );
VK_RenderDebugLabelBegin( "opaque" );
// Draw view model
{
VK_RenderStateSetMatrix( mvp );
VK_RenderStateSetColor( 1.f, 1.f, 1.f, 1.f );
R_RunViewmodelEvents();
R_DrawViewModel();
@ -652,7 +637,6 @@ void VK_SceneRender( const ref_viewpass_t *rvp )
cl_entity_t *world = gEngine.GetEntityByIndex( 0 );
if( world && world->model )
{
VK_RenderStateSetMatrix( mvp );
VK_RenderStateSetColor( 1.f, 1.f, 1.f, 1.f);
VK_BrushDrawModel( world, kRenderNormal );
}
@ -662,7 +646,7 @@ void VK_SceneRender( const ref_viewpass_t *rvp )
for (int i = 0; i < g_lists.draw_list->num_solid_entities; ++i)
{
cl_entity_t *ent = g_lists.draw_list->solid_entities[i];
drawEntity(ent, kRenderNormal, mvp);
drawEntity(ent, kRenderNormal);
}
// Draw opaque beams
@ -680,7 +664,7 @@ void VK_SceneRender( const ref_viewpass_t *rvp )
for (int i = 0; i < g_lists.draw_list->num_trans_entities; ++i)
{
const vk_trans_entity_t *ent = g_lists.draw_list->trans_entities + i;
drawEntity(ent->entity, ent->render_mode, mvp);
drawEntity(ent->entity, ent->render_mode);
}
}