add beams rendering

not all beam types are supported yet

also changes studio api init sequence, fixes missing cvars
vertex type struct is no longer names as brush-specific
uniform buffer allocation is now in vk_render

blending issues still remain
This commit is contained in:
Ivan Avdeev 2021-02-17 13:26:09 -08:00
parent b22cd90184
commit 3b1e7be112
13 changed files with 1461 additions and 71 deletions

View File

@ -1,18 +1,17 @@
## 2021-02-15
- [x] weapon models -- viewmodel
- [x] coalesce studio model draw calls
- [x] initual sprite support
# Next
- [ ] fix sprite blending
- [ ] wrap viewmodel in vk debug label
# Planned
- [ ] draw more types of beams
- [ ] fix brush blending
- [ ] sprite depth offset
- [ ] fix incorrect viewport sprite culling
- [ ] improve g_camera handling; trace SetViewPass vs RenderScene ...
- [ ] loading to the same map breaks geometry
- [ ] studio model lighting
- [ ] move all consts to vk_const
- [ ] what is GL_Backend*/GL_RenderFrame ???
- [ ] beams
- [ ] particles
- [ ] decals
- [ ] issue: transparent brushes are too transparent (train ride)
@ -25,6 +24,7 @@
- [ ] 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, ...
# Someday
- [ ] cleanup unused stuff in vk_studio.c
@ -37,6 +37,8 @@
- [ ] better 2d renderer: fill DRAWQUAD(texture, color, ...) command into storage buffer instead of 4 vertices
- [ ] auto-atlas lots of smol textures: most of model texture are tiny (64x64 or less), can we not rebind them all the time? alt: bindless texture array
- [ ] can we also try to coalesce sprite draw calls?
- [ ] not visibly watertight map brushes
## 2021-02-06
- [x] alpha test
@ -64,3 +66,12 @@
- [x] studio models vk debug markers
- [x] studio models white texture as lightmap
- [x] studio models fixes
## 2021-02-15
- [x] weapon models -- viewmodel
- [x] coalesce studio model draw calls
- [x] initual sprite support
## 2021-02-17
- [x] draw some beams

1283
ref_vk/vk_beams.c Normal file

File diff suppressed because it is too large Load Diff

11
ref_vk/vk_beams.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include "xash3d_types.h"
struct cl_entity_s;
struct beam_s;
qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly );
void R_BeamDrawCustomEntity( struct cl_entity_s *ent, float frametime );
void R_BeamDraw( struct beam_s *pbeam, float frametime );

View File

@ -217,7 +217,7 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
uint32_t vertex_offset = 0;
int num_surfaces = 0;
vk_buffer_alloc_t vertex_alloc, index_alloc;
brush_vertex_t *bvert = NULL;
vk_vertex_t *bvert = NULL;
uint16_t *bind = NULL;
uint32_t index_offset = 0;
@ -243,7 +243,7 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
max_texture_id = surf->texinfo->texture->gl_texturenum;
}
vertex_alloc = VK_RenderBufferAlloc( sizeof(brush_vertex_t), num_vertices );
vertex_alloc = VK_RenderBufferAlloc( sizeof(vk_vertex_t), num_vertices );
bvert = vertex_alloc.ptr;
bmodel->vertex_offset = vertex_alloc.buffer_offset_in_units;
if (!bvert)
@ -306,7 +306,7 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
const int iedge = mod->surfedges[surf->firstedge + k];
const medge_t *edge = mod->edges + (iedge >= 0 ? iedge : -iedge);
const mvertex_t *in_vertex = mod->vertexes + (iedge >= 0 ? edge->v[0] : edge->v[1]);
brush_vertex_t vertex = {
vk_vertex_t vertex = {
{in_vertex->position[0], in_vertex->position[1], in_vertex->position[2]},
};

View File

@ -5,8 +5,11 @@
DECLARE_CVAR(NONEXTERN_CVAR)
#undef NONEXTERN_CVAR
static cvar_t *r_drawentities;
void VK_LoadCvars( void )
{
r_lighting_modulate = gEngine.Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" );
cl_lightstyle_lerping = gEngine.pfnGetCvarPointer( "cl_lightstyle_lerping", 0 );
r_drawentities = gEngine.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
}

View File

@ -22,6 +22,7 @@ static struct {
} stat;
uint32_t temp_buffer_offset;
int next_free_uniform_slot;
VkPipelineLayout pipeline_layout;
VkPipeline pipelines[kRenderTransAdd + 1];
@ -75,9 +76,9 @@ static qboolean createPipelines( void )
};
VkVertexInputAttributeDescription attribs[] = {
{.binding = 0, .location = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(brush_vertex_t, pos)},
{.binding = 0, .location = 1, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(brush_vertex_t, gl_tc)},
{.binding = 0, .location = 2, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(brush_vertex_t, lm_tc)},
{.binding = 0, .location = 0, .format = VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk_vertex_t, pos)},
{.binding = 0, .location = 1, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(vk_vertex_t, gl_tc)},
{.binding = 0, .location = 2, .format = VK_FORMAT_R32G32_SFLOAT, .offset = offsetof(vk_vertex_t, lm_tc)},
};
VkPipelineShaderStageCreateInfo shader_stages[] = {
@ -101,7 +102,7 @@ static qboolean createPipelines( void )
.stages = shader_stages,
.num_stages = ARRAYSIZE(shader_stages),
.vertex_stride = sizeof(brush_vertex_t),
.vertex_stride = sizeof(vk_vertex_t),
.depthTestEnable = VK_TRUE,
.depthWriteEnable = VK_TRUE,
@ -274,6 +275,7 @@ vk_buffer_alloc_t VK_RenderBufferAlloc( uint32_t unit_size, uint32_t count )
void VK_RenderBufferClearAll( void )
{
g_render.buffer_free_offset = 0;
g_render.next_free_uniform_slot = 0;
g_render.stat.align_holes_size = 0;
}
@ -308,6 +310,8 @@ static struct {
} g_render_state;
void VK_RenderBegin( void ) {
g_render.next_free_uniform_slot = 0;
g_render_state.pipeline = -1;
g_render_state.lightmap = -1;
g_render_state.texture = -1;
@ -375,6 +379,14 @@ void VK_RenderDraw( const render_draw_t *draw )
}
}
int VK_RenderUniformAlloc( void ) {
if (g_render.next_free_uniform_slot == MAX_UNIFORM_SLOTS)
return -1;
return g_render.next_free_uniform_slot++;
}
void VK_RenderEnd( void )
{
}

View File

@ -33,11 +33,11 @@ vk_buffer_alloc_t VK_RenderTempBufferAlloc( uint32_t unit_size, uint32_t count )
void VK_RenderTempBufferEnd( void );
// TODO is this a good place?
typedef struct brush_vertex_s {
typedef struct vk_vertex_s {
vec3_t pos;
vec2_t gl_tc;
vec2_t lm_tc;
} brush_vertex_t;
} vk_vertex_t;
typedef struct render_draw_s {
int ubo_index;
@ -48,5 +48,8 @@ typedef struct render_draw_s {
} render_draw_t;
void VK_RenderBegin( void );
// Allocate one uniform slot, -1 if no slot available
int VK_RenderUniformAlloc( void );
// FIXME rename to Submit something
void VK_RenderDraw( const render_draw_t *draw );
void VK_RenderEnd( void );

View File

@ -8,6 +8,7 @@
#include "vk_lightmap.h"
#include "vk_sprite.h"
#include "vk_studio.h"
#include "vk_beams.h"
#include "xash3d_types.h"
#include "com_strings.h"
@ -47,11 +48,6 @@ static void GL_BackendEndFrame( void )
PRINT_NOT_IMPLEMENTED();
}
static void CL_AddCustomBeam( cl_entity_t *pEnvBeam )
{
PRINT_NOT_IMPLEMENTED();
}
// debug
static void R_ShowTextures( void )
{
@ -127,10 +123,6 @@ static void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, ve
{
PRINT_NOT_IMPLEMENTED();
}
static void CL_InitStudioAPI( void )
{
PRINT_NOT_IMPLEMENTED();
}
// bmodel
static void R_InitSkyClouds( struct mip_s *mt, struct texture_s *tx, qboolean custom_palette )
@ -198,15 +190,6 @@ static void CL_DrawTracers( double frametime, particle_t *tracers )
{
PRINT_NOT_IMPLEMENTED();
}
static void CL_DrawBeams( int fTrans , BEAM *beams )
{
PRINT_NOT_IMPLEMENTED();
}
static qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly )
{
PRINT_NOT_IMPLEMENTED();
return false;
}
// Xash3D Render Interface
// Get renderer info (doesn't changes engine state at all)

View File

@ -9,6 +9,7 @@
#include "vk_core.h"
#include "vk_sprite.h"
#include "vk_global.h"
#include "vk_beams.h"
#include "com_strings.h"
#include "ref_params.h"
@ -17,6 +18,15 @@
#include <stdlib.h> // qsort
#include <memory.h>
typedef struct draw_list_s {
struct cl_entity_s *solid_entities[MAX_SCENE_ENTITIES]; // opaque moving or alpha brushes
vk_trans_entity_t trans_entities[MAX_SCENE_ENTITIES]; // translucent brushes or studio models kek
struct cl_entity_s *beam_entities[MAX_SCENE_ENTITIES];
uint num_solid_entities;
uint num_trans_entities;
uint num_beam_entities;
} draw_list_t;
static struct {
draw_list_t draw_stack[MAX_SCENE_STACK];
int draw_stack_pos;
@ -391,7 +401,7 @@ static int R_TransEntityCompare( const void *a, const void *b)
// FIXME where should this function be
#define RP_NORMALPASS() true // FIXME ???
static int CL_FxBlend( cl_entity_t *e, const vec3_t vieworg ) // FIXME do R_SetupFrustum: , vec3_t vforward )
int CL_FxBlend( cl_entity_t *e ) // FIXME do R_SetupFrustum: , vec3_t vforward )
{
int blend = 0;
float offset, dist;
@ -474,12 +484,11 @@ static int CL_FxBlend( cl_entity_t *e, const vec3_t vieworg ) // FIXME do R_Setu
if( blend < 0 ) blend = 0;
else blend = e->curstate.renderamt;
break;
/* FIXME
case kRenderFxHologram:
case kRenderFxDistort:
VectorCopy( e->origin, tmp );
VectorSubtract( tmp, vieworg, tmp );
dist = DotProduct( tmp, vforward );
VectorSubtract( tmp, g_camera.vieworg, tmp );
dist = DotProduct( tmp, g_camera.vforward );
// turn off distance fade
if( e->curstate.renderfx == kRenderFxDistort )
@ -497,7 +506,6 @@ static int CL_FxBlend( cl_entity_t *e, const vec3_t vieworg ) // FIXME do R_Setu
blend += gEngine.COM_RandomLong( -32, 31 );
}
break;
*/
default:
blend = e->curstate.renderamt;
break;
@ -526,22 +534,29 @@ static void prepareMatrix( const ref_viewpass_t *rvp, matrix4x4 worldview, matri
Matrix4x4_Concat( mvp, projection, worldview);
}
static int drawEntity( cl_entity_t *ent, int render_mode, int ubo_index, const matrix4x4 mvp )
static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
{
const model_t *mod = ent->model;
matrix4x4 model, ent_mvp;
uniform_data_t *ubo = VK_RenderGetUniformSlot(ubo_index);
uniform_data_t *ubo;
float alpha;
int ubo_index;
if (!mod)
return 0;
return;
// handle studiomodels with custom rendermodes on texture
alpha = render_mode == kRenderNormal ? 1.f : CL_FxBlend( ent, fixme_rvp.vieworigin ) / 255.0f;
alpha = render_mode == kRenderNormal ? 1.f : CL_FxBlend( ent ) / 255.0f;
// TODO ref_gl does this earlier, can we too?
if( alpha <= 0.0f )
return 0;
return;
// TODO might accidentally alloc ubo for things that won't be rendered; optimize this
ubo_index = VK_RenderUniformAlloc();
if (ubo_index < 0)
return; // TODO complain
ubo = VK_RenderGetUniformSlot(ubo_index);
switch (render_mode) {
case kRenderNormal:
@ -592,19 +607,18 @@ static int drawEntity( cl_entity_t *ent, int render_mode, int ubo_index, const m
Matrix4x4_ToArrayFloatGL( mvp, (float*)ubo->mvp);
VK_SpriteDrawModel( ent, ubo_index );
break;
default:
return 0;
}
return 1;
}
static float g_frametime = 0;
void VK_SceneRender( void )
{
matrix4x4 worldview, projection, mvp;
int current_pipeline_index = kRenderNormal;
int ubo_index = 0;
g_frametime = /*FIXME VK RP_NORMALPASS( )) ? */
gpGlobals->time - gpGlobals->oldtime
/* FIXME VK : 0.f */;
if (!VK_BrushRenderBegin())
return;
@ -617,11 +631,14 @@ void VK_SceneRender( void )
// Draw view model
{
uniform_data_t *ubo = VK_RenderGetUniformSlot(ubo_index);
const int ubo_index = VK_RenderUniformAlloc();
uniform_data_t *ubo;
ASSERT(ubo_index >= 0);
ubo = VK_RenderGetUniformSlot(ubo_index);
Matrix4x4_ToArrayFloatGL( mvp, (float*)ubo->mvp );
Vector4Set(ubo->color, 1.f, 1.f, 1.f, 1.f);
R_RunViewmodelEvents();
R_DrawViewModel( ubo_index++ );
R_DrawViewModel( ubo_index );
}
// Draw world brush
@ -629,11 +646,13 @@ void VK_SceneRender( void )
cl_entity_t *world = gEngine.GetEntityByIndex( 0 );
if( world && world->model )
{
uniform_data_t *ubo = VK_RenderGetUniformSlot(ubo_index);
const int ubo_index = VK_RenderUniformAlloc();
uniform_data_t *ubo;
ASSERT(ubo_index >= 0);
ubo = VK_RenderGetUniformSlot(ubo_index);
Matrix4x4_ToArrayFloatGL( mvp, (float*)ubo->mvp );
Vector4Set(ubo->color, 1.f, 1.f, 1.f, 1.f);
VK_BrushDrawModel( world, kRenderNormal, ubo_index );
ubo_index++;
}
}
@ -641,9 +660,12 @@ void VK_SceneRender( void )
for (int i = 0; i < g_lists.draw_list->num_solid_entities; ++i)
{
cl_entity_t *ent = g_lists.draw_list->solid_entities[i];
ubo_index += drawEntity(ent, kRenderNormal, ubo_index, mvp);
drawEntity(ent, kRenderNormal, mvp);
}
// Draw opaque beams
gEngine.CL_DrawEFX( g_frametime, false );
{
if (vk_core.debug) {
VkDebugUtilsLabelEXT label = {
@ -661,13 +683,16 @@ void VK_SceneRender( void )
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;
ubo_index += drawEntity(ent->entity, ent->render_mode, ubo_index, mvp);
drawEntity(ent->entity, ent->render_mode, mvp);
}
if (vk_core.debug)
vkCmdEndDebugUtilsLabelEXT(vk_core.cb);
}
// Draw transparent beams
gEngine.CL_DrawEFX( g_frametime, true );
VK_RenderEnd();
VK_RenderTempBufferEnd();
@ -719,3 +744,62 @@ int TriWorldToScreen( const float *world, float *screen )
return retval;
}
/*
================
CL_AddCustomBeam
Add the beam that encoded as custom entity
================
*/
void CL_AddCustomBeam( cl_entity_t *pEnvBeam )
{
if( g_lists.draw_list->num_beam_entities >= ARRAYSIZE(g_lists.draw_list->beam_entities) )
{
gEngine.Con_Printf( S_ERROR "Too many beams %d!\n", g_lists.draw_list->num_beam_entities );
return;
}
if( pEnvBeam )
{
g_lists.draw_list->beam_entities[g_lists.draw_list->num_beam_entities] = pEnvBeam;
g_lists.draw_list->num_beam_entities++;
}
}
void CL_DrawBeams( int fTrans, BEAM *active_beams )
{
BEAM *pBeam;
int i, flags;
// FIXME VK pglDepthMask( fTrans ? GL_FALSE : GL_TRUE );
// server beams don't allocate beam chains
// all params are stored in cl_entity_t
for( i = 0; i < g_lists.draw_list->num_beam_entities; i++ )
{
cl_entity_t *currentbeam = g_lists.draw_list->beam_entities[i];
flags = currentbeam->curstate.rendermode & 0xF0;
if( fTrans && FBitSet( flags, FBEAM_SOLID ))
continue;
if( !fTrans && !FBitSet( flags, FBEAM_SOLID ))
continue;
R_BeamDrawCustomEntity( currentbeam, g_frametime );
// FIXME VK r_stats.c_view_beams_count++;
}
// draw temporary entity beams
for( pBeam = active_beams; pBeam; pBeam = pBeam->next )
{
if( fTrans && FBitSet( pBeam->flags, FBEAM_SOLID ))
continue;
if( !fTrans && !FBitSet( pBeam->flags, FBEAM_SOLID ))
continue;
R_BeamDraw( pBeam, g_frametime );
}
}

View File

@ -14,15 +14,6 @@ typedef struct vk_trans_entity_s {
int render_mode;
} vk_trans_entity_t;
typedef struct draw_list_s {
struct cl_entity_s *solid_entities[MAX_SCENE_ENTITIES]; // opaque moving or alpha brushes
vk_trans_entity_t trans_entities[MAX_SCENE_ENTITIES]; // translucent brushes or studio models kek
//cl_entity_t *beam_entities[MAX_DRAW_ENTITIES];
uint num_solid_entities;
uint num_trans_entities;
//uint num_beam_entities;
} draw_list_t;
void VK_SceneInit( void );
void FIXME_VK_SceneSetViewPass( const struct ref_viewpass_s *rvp );
void VK_SceneRender( void );
@ -37,3 +28,9 @@ void R_PopScene( void );
void R_NewMap( void );
void R_RenderScene( void );
// TODO should this be here?
int CL_FxBlend( struct cl_entity_s *e );
struct beam_s;
void CL_DrawBeams( int fTrans, struct beam_s *active_beams );
void CL_AddCustomBeam( struct cl_entity_s *pEnvBeam );

View File

@ -650,11 +650,11 @@ static void R_DrawSpriteQuad( mspriteframe_t *frame, vec3_t org, vec3_t v_right,
{
vec3_t point;
vk_buffer_alloc_t buf_vertex, buf_index;
brush_vertex_t *dst_vtx;
vk_vertex_t *dst_vtx;
uint16_t *dst_idx;
// Get buffer region for vertices and indices
buf_vertex = VK_RenderTempBufferAlloc( sizeof(brush_vertex_t), 4 );
buf_vertex = VK_RenderTempBufferAlloc( sizeof(vk_vertex_t), 4 );
if (!buf_vertex.ptr)
{
gEngine.Con_Printf(S_ERROR "Cannot render mesh\n"); // TODO mesh signature?

View File

@ -432,13 +432,15 @@ static model_t *R_GetChromeSprite( void )
return gEngine.GetDefaultSprite( REF_CHROME_SPRITE );
}
static int fixme_studio_models_drawn;
static void pfnGetModelCounters( int **s, int **a )
{
*s = &g_studio.framecount;
/* FIXME VK NOT IMPLEMENTED */
/* *a = &r_stats.c_studio_models_drawn; */
*a = 0;
*a = &fixme_studio_models_drawn;
}
static void pfnGetAliasScale( float *x, float *y )
@ -1913,7 +1915,7 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
int i;
int num_vertices = 0, num_indices = 0;
vk_buffer_alloc_t buf_vertex, buf_index;
brush_vertex_t *dst_vtx;
vk_vertex_t *dst_vtx;
uint16_t *dst_idx;
uint32_t vertex_offset, index_offset;
short* const ptricmds_initial = ptricmds;
@ -1938,7 +1940,7 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
ASSERT(num_indices > 0);
// Get buffer region for vertices and indices
buf_vertex = VK_RenderTempBufferAlloc( sizeof(brush_vertex_t), num_vertices );
buf_vertex = VK_RenderTempBufferAlloc( sizeof(vk_vertex_t), num_vertices );
if (!buf_vertex.ptr)
{
gEngine.Con_Printf(S_ERROR "Cannot render mesh\n"); // TODO mesh signature?
@ -1966,7 +1968,7 @@ static void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float
for(int j = 0; j < vertices ; ++j, ++dst_vtx, ptricmds += 4 )
{
ASSERT((((brush_vertex_t*)buf_vertex.ptr) + num_vertices) > dst_vtx);
ASSERT((((vk_vertex_t*)buf_vertex.ptr) + num_vertices) > dst_vtx);
VectorCopy(g_studio.verts[ptricmds[0]], dst_vtx->pos);
dst_vtx->lm_tc[0] = dst_vtx->lm_tc[1] = mode == FAN ? .5f : 0.f;
@ -3507,7 +3509,6 @@ void CL_InitStudioAPI( void )
void VK_StudioInit( void )
{
R_StudioInit();
CL_InitStudioAPI();
}
void VK_StudioShutdown( void )

View File

@ -16,3 +16,5 @@ void VK_StudioDrawModel( cl_entity_t *ent, int render_mode, int ubo_index );
void R_RunViewmodelEvents( void );
void R_DrawViewModel( int ubo_index );
void CL_InitStudioAPI( void );