Merge pull request #529 from w23/E260

- [x] Improves #528 a bit
- [x] Fixes #523 
  - [x] Fix ![image](https://user-images.githubusercontent.com/321361/235242886-bbae06cf-4375-4e11-bae0-8bc4e7644d59.png)
  - [ ] ~верни зеркало! ![image](https://user-images.githubusercontent.com/321361/235250971-6652e2b2-e531-4b41-b603-1c50306b7ea3.png)~
  - [x] test_brush2 лесенки пропали на растеризации
This commit is contained in:
Ivan Avdeev 2023-05-01 10:45:31 -07:00 committed by GitHub
commit 0d8a7f76f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 280 additions and 106 deletions

View File

@ -50,7 +50,8 @@ void XVK_CameraDebugPrintCenterEntity( void ) {
);
p += Q_snprintf(p, end - p,
"entity index: %d, name: %s\n",
"entity (dynamic index: %d, info: %d), name: %s\n",
ent ? ent->index : -1,
(physent && physent->info > 0) ? physent->info : -1,
(ent && ent->model) ? ent->model->name : "N/A");

View File

@ -1,4 +1,4 @@
#define SRGB_FAST_APPROXIMATION 0
#define SRGB_FAST_APPROXIMATION
#ifdef SRGB_FAST_APPROXIMATION
#define LINEARtoSRGB OECF_sRGBFast
@ -32,6 +32,9 @@ vec4 sRGB_OECF(const vec4 sRGB)
vec3 sRGB_OECFFast(const vec3 sRGB) {
return pow(sRGB, vec3(2.2));
}
float sRGB_OECFFast(const float sRGB) {
return pow(sRGB, 2.2);
}
vec4 sRGB_OECFFast(const vec4 sRGB) {
return vec4(pow(sRGB.rgb, vec3(2.2)), sRGB.w);
}

View File

@ -49,8 +49,12 @@ void traceSimpleBlending(vec3 pos, vec3 dir, float L, inout vec3 emissive, inout
}
#else
const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], geom.uv);
float alpha = texture_color.a * kusok.model.color.a * geom.vertex_color.a;
vec3 color = kusok.model.color.rgb * texture_color.rgb * SRGBtoLINEAR(geom.vertex_color.rgb) * alpha;
// "Linearizing" alpha, while looking weird conceptually in the code, is necessary to make it look close to the original.
// TODO figure out whether texture alpha needs to be linearized too. Don't have good examples to look at.
// TODO this also makes sprites look dull, so likely kusok.model.color linearization should only apply to brush models, not sprites. This is better done when passing brush model to ray tracer.
float alpha = SRGBtoLINEAR(texture_color.a * kusok.model.color.a) * geom.vertex_color.a;
vec3 color = kusok.model.color.rgb * SRGBtoLINEAR(texture_color.rgb) * geom.vertex_color.rgb * alpha;
if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW) {
// Glow is additive + small overshoot

View File

@ -26,6 +26,9 @@ typedef struct vk_brush_model_s {
vk_render_model_t render_model;
int num_water_surfaces;
int *surface_to_geometry_index;
int *animated_indexes;
int animated_indexes_count;
} vk_brush_model_t;
static struct {
@ -371,6 +374,25 @@ const texture_t *R_TextureAnimation( const cl_entity_t *ent, const msurface_t *s
return base;
}
static qboolean isSurfaceAnimated( const msurface_t *s, const struct texture_s *base_override ) {
const texture_t *base = base_override ? base_override : s->texinfo->texture;
/* FIXME don't have ent here, need to check both explicitly
if( ent && ent->curstate.frame ) {
if( base->alternate_anims )
base = base->alternate_anims;
}
*/
if( !base->anim_total )
return false;
if( base->name[0] == '-' )
return false;
return true;
}
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, const matrix4x4 model ) {
// Expect all buffers to be bound
const model_t *mod = ent->model;
@ -381,15 +403,42 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
return;
}
if (render_mode == kRenderTransColor) {
Vector4Set(bmodel->render_model.color,
ent->curstate.rendercolor.r / 255.f,
ent->curstate.rendercolor.g / 255.f,
ent->curstate.rendercolor.b / 255.f,
blend);
} else {
// Other render modes are not affected by entity current state color
Vector4Set(bmodel->render_model.color, 1, 1, 1, blend);
Vector4Set(bmodel->render_model.color, 1.f, 1.f, 1.f, 1.f);
vk_render_type_e render_type = kVkRenderTypeSolid;
switch (render_mode) {
case kRenderNormal:
Vector4Set(bmodel->render_model.color, 1.f, 1.f, 1.f, 1.f);
render_type = kVkRenderTypeSolid;
break;
case kRenderTransColor:
render_type = kVkRenderType_A_1mA_RW;
Vector4Set(bmodel->render_model.color,
ent->curstate.rendercolor.r / 255.f,
ent->curstate.rendercolor.g / 255.f,
ent->curstate.rendercolor.b / 255.f,
blend);
break;
case kRenderTransAdd:
Vector4Set(bmodel->render_model.color, blend, blend, blend, 1.f);
render_type = kVkRenderType_A_1_R;
break;
case kRenderTransAlpha:
if( gEngine.EngineGetParm( PARM_QUAKE_COMPATIBLE, 0 ))
{
render_type = kVkRenderType_A_1mA_RW;
Vector4Set(bmodel->render_model.color, 1.f, 1.f, 1.f, blend);
}
else
{
Vector4Set(bmodel->render_model.color, 1.f, 1.f, 1.f, 1.f);
render_type = kVkRenderType_AT;
}
break;
case kRenderTransTexture:
case kRenderGlow:
render_type = kVkRenderType_A_1mA_R;
Vector4Set(bmodel->render_model.color, 1.f, 1.f, 1.f, blend);
break;
}
// Only Normal and TransAlpha have lightmaps
@ -405,18 +454,21 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
++g_brush.stat.models_drawn;
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
const int surface_index = geom->surf_deprecate - mod->surfaces;
const xvk_patch_surface_t *const patch_surface = R_VkPatchGetSurface(surface_index);
if (render_mode == kRenderTransColor) {
// TransColor mode means no texture color is used
// TransColor means ignore textures and draw just color
if (render_mode == kRenderTransColor) {
// TODO cache previous render_mode.
// TODO also it will break switching render type from TransColor to anyting else -- textures will be stuck at white
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
vk_render_geometry_t *geom = bmodel->render_model.geometries + i;
geom->texture = tglob.whiteTexture;
} else if (patch_surface && patch_surface->tex_id >= 0) {
// Patch by constant texture index first, if it exists
geom->texture = patch_surface->tex_id;
} else {
}
} else {
// Update animated textures
for (int i = 0; i < bmodel->animated_indexes_count; ++i) {
vk_render_geometry_t *geom = bmodel->render_model.geometries + bmodel->animated_indexes[i];
const int surface_index = geom->surf_deprecate - mod->surfaces;
const xvk_patch_surface_t *const patch_surface = R_VkPatchGetSurface(surface_index);
// Optionally patch by texture_s pointer and run animations
const struct texture_s *texture_override = patch_surface ? patch_surface->tex : NULL;
const texture_t *t = R_TextureAnimation(ent, geom->surf_deprecate, texture_override);
@ -425,11 +477,19 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co
}
}
bmodel->render_model.render_type = brushRenderModeToRenderType(render_mode);
bmodel->render_model.render_type = render_type;
VK_RenderModelDraw(ent, &bmodel->render_model);
}
static qboolean renderableSurface( const msurface_t *surf, int i ) {
typedef enum {
BrushSurface_Hidden = 0,
BrushSurface_Regular,
BrushSurface_Animated,
BrushSurface_Water,
BrushSurface_Sky,
} brush_surface_type_e;
static brush_surface_type_e getSurfaceType( const msurface_t *surf, int i ) {
// if ( i >= 0 && (surf->flags & ~(SURF_PLANEBACK | SURF_UNDERWATER | SURF_TRANSPARENT)) != 0)
// {
// gEngine.Con_Reportf("\t%d flags: ", i);
@ -447,38 +507,43 @@ static qboolean renderableSurface( const msurface_t *surf, int i ) {
// PRINTFLAGS(PRINTFLAG)
// gEngine.Con_Reportf("\n");
// }
const xvk_patch_surface_t *patch_surface = R_VkPatchGetSurface(i);
if (patch_surface && patch_surface->flags & Patch_Surface_Delete)
return BrushSurface_Hidden;
{
const xvk_patch_surface_t *patch_surface = R_VkPatchGetSurface(i);
if (patch_surface && patch_surface->flags & Patch_Surface_Delete)
return false;
}
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWTURB_QUADS))
return BrushSurface_Water;
// Explicitly enable SURF_SKY, otherwise they will be skipped by SURF_DRAWTILED
if( FBitSet( surf->flags, SURF_DRAWSKY ))
return BrushSurface_Sky;
//if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
if( surf->flags & ( SURF_DRAWTURB | SURF_DRAWTURB_QUADS ) ) {
//if( surf->flags & ( SURF_DRAWSKY | SURF_CONVEYOR ) ) {
// FIXME don't print this on second sort-by-texture pass
//gEngine.Con_Reportf("Skipping surface %d because of flags %08x\n", i, surf->flags);
return false;
}
// Explicitly enable SURF_SKY, otherwise they will be skipped by SURF_DRAWTILED
if( FBitSet( surf->flags, SURF_DRAWSKY )) {
return true;
return BrushSurface_Hidden;
}
if( FBitSet( surf->flags, SURF_DRAWTILED )) {
//gEngine.Con_Reportf("Skipping surface %d because of tiled flag\n", i);
return false;
return BrushSurface_Hidden;
}
return true;
const struct texture_s *texture_override = patch_surface ? patch_surface->tex : NULL;
if (isSurfaceAnimated(surf, texture_override)) {
return BrushSurface_Animated;
}
return BrushSurface_Regular;
}
typedef struct {
int num_surfaces, num_vertices, num_indices;
int max_texture_id;
int water_surfaces;
int animated_count;
} model_sizes_t;
static model_sizes_t computeSizes( const model_t *mod ) {
@ -490,16 +555,25 @@ static model_sizes_t computeSizes( const model_t *mod ) {
const msurface_t *surf = mod->surfaces + surface_index;
const int tex_id = surf->texinfo->texture->gl_texturenum;
sizes.water_surfaces += !!(surf->flags & (SURF_DRAWTURB | SURF_DRAWTURB_QUADS));
if (tex_id > sizes.max_texture_id)
sizes.max_texture_id = tex_id;
if (!renderableSurface(surf, surface_index))
switch (getSurfaceType(surf, surface_index)) {
case BrushSurface_Water:
sizes.water_surfaces++;
case BrushSurface_Hidden:
continue;
case BrushSurface_Animated:
sizes.animated_count++;
case BrushSurface_Regular:
case BrushSurface_Sky:
break;
}
++sizes.num_surfaces;
sizes.num_vertices += surf->numedges;
sizes.num_indices += 3 * (surf->numedges - 1);
if (tex_id > sizes.max_texture_id)
sizes.max_texture_id = tex_id;
}
return sizes;
@ -513,6 +587,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
uint16_t *bind = NULL;
uint32_t index_offset = 0;
r_geometry_buffer_lock_t buffer;
int animated_count = 0;
if (!R_GeometryBufferAllocAndLock( &buffer, sizes.num_vertices, sizes.num_indices, LifetimeLong )) {
gEngine.Con_Printf(S_ERROR "Cannot allocate geometry for %s\n", mod->name );
@ -540,12 +615,24 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
int tex_id = surf->texinfo->texture->gl_texturenum;
const xvk_patch_surface_t *const psurf = R_VkPatchGetSurface(surface_index);
if (!renderableSurface(surf, surface_index))
continue;
if (t != tex_id)
continue;
if (psurf && psurf->tex_id >= 0)
tex_id = psurf->tex_id;
const brush_surface_type_e type = getSurfaceType(surf, surface_index);
switch (type) {
case BrushSurface_Water:
case BrushSurface_Hidden:
continue;
case BrushSurface_Animated:
bmodel->animated_indexes[animated_count++] = num_geometries;
case BrushSurface_Regular:
case BrushSurface_Sky:
break;
}
bmodel->surface_to_geometry_index[i] = num_geometries;
++num_geometries;
@ -569,14 +656,12 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
model_geometry->index_offset = index_offset;
if( FBitSet( surf->flags, SURF_DRAWSKY )) {
//gEngine.Con_Printf("SURF_SKY: tex_id=%d\n", tex_id);
if(type == BrushSurface_Sky) {
model_geometry->material = kXVkMaterialSky;
} else {
model_geometry->material = kXVkMaterialRegular;
if (!FBitSet( surf->flags, SURF_DRAWTILED )) {
VK_CreateSurfaceLightmap( surf, mod );
}
ASSERT(!FBitSet( surf->flags, SURF_DRAWTILED ));
VK_CreateSurfaceLightmap( surf, mod );
}
if (FBitSet( surf->flags, SURF_CONVEYOR )) {
@ -678,6 +763,7 @@ static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
bmodel->render_model.dynamic_polylights_count = 0;
ASSERT(sizes.num_surfaces == num_geometries);
ASSERT(sizes.animated_count == animated_count);
bmodel->render_model.num_geometries = num_geometries;
return true;
@ -704,12 +790,9 @@ qboolean VK_BrushModelLoad( model_t *mod ) {
{
const model_sizes_t sizes = computeSizes( mod );
const size_t model_size =
sizeof(vk_brush_model_t) +
sizeof(vk_render_geometry_t) * sizes.num_surfaces +
sizeof(int) * mod->nummodelsurfaces;
const size_t model_size = sizeof(vk_brush_model_t);
vk_brush_model_t *bmodel = Mem_Calloc(vk_core.pool, model_size);
vk_brush_model_t *bmodel = Mem_Calloc(vk_core.pool, sizeof(*bmodel));
mod->cache.data = bmodel;
Q_strncpy(bmodel->render_model.debug_name, mod->name, sizeof(bmodel->render_model.debug_name));
bmodel->render_model.render_type = kVkRenderTypeSolid;
@ -718,8 +801,13 @@ qboolean VK_BrushModelLoad( model_t *mod ) {
Vector4Set(bmodel->render_model.color, 1, 1, 1, 1);
if (sizes.num_surfaces != 0) {
bmodel->render_model.geometries = (vk_render_geometry_t*)((char*)(bmodel + 1));
bmodel->surface_to_geometry_index = (int*)((char*)(bmodel->render_model.geometries + sizes.num_surfaces));
bmodel->render_model.geometries = Mem_Malloc(vk_core.pool, sizeof(vk_render_geometry_t) * sizes.num_surfaces);
bmodel->surface_to_geometry_index = Mem_Malloc(vk_core.pool, sizeof(int) * mod->nummodelsurfaces);
bmodel->animated_indexes = Mem_Malloc(vk_core.pool, sizeof(int) * sizes.animated_count);
bmodel->animated_indexes_count = sizes.animated_count;
bmodel->render_model.geometries_changed = bmodel->animated_indexes;
bmodel->render_model.geometries_changed_count = bmodel->animated_indexes_count;
if (!loadBrushSurfaces(sizes, mod) || !VK_RenderModelInit(&bmodel->render_model)) {
gEngine.Con_Printf(S_ERROR "Could not load model %s\n", mod->name);
@ -744,6 +832,12 @@ void VK_BrushModelDestroy( model_t *mod ) {
return;
VK_RenderModelDestroy(&bmodel->render_model);
if (bmodel->animated_indexes)
Mem_Free(bmodel->animated_indexes);
if (bmodel->surface_to_geometry_index)
Mem_Free(bmodel->surface_to_geometry_index);
if (bmodel->render_model.geometries)
Mem_Free(bmodel->render_model.geometries);
Mem_Free(bmodel);
mod->cache.data = NULL;
}
@ -797,8 +891,13 @@ void R_VkBrushModelCollectEmissiveSurfaces( const struct model_s *mod, qboolean
const int surface_index = mod->firstmodelsurface + i;
const msurface_t *surf = mod->surfaces + surface_index;
if (!renderableSurface(surf, surface_index))
switch (getSurfaceType(surf, surface_index)) {
case BrushSurface_Regular:
case BrushSurface_Animated:
break;
default:
continue;
}
const int tex_id = surf->texinfo->texture->gl_texturenum; // TODO animation?

View File

@ -19,7 +19,11 @@ typedef struct vk_ray_model_s {
uint32_t kusochki_offset;
qboolean dynamic;
qboolean taken;
qboolean kusochki_updated_this_frame;
// TODO remove with the split of Kusok in Model+Material+Kusok
uint32_t material_mode;
vec4_t color;
matrix4x4 prev_transform;
struct {
uint32_t as_offset;

View File

@ -299,7 +299,9 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
} else {
ray_model->kusochki_offset = kusochki_count_offset;
ray_model->dynamic = args.model->dynamic;
ray_model->kusochki_updated_this_frame = false;
ray_model->material_mode = -1;
Vector4Set(ray_model->color, 1, 1, 1, 1);
Matrix4x4_LoadIdentity(ray_model->prev_transform);
if (vk_core.debug)
validateModel(ray_model);
@ -356,6 +358,77 @@ static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_
speed[1] = sy * flRate;
}
static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk_render_model_t *const render_model, uint32_t material_mode, const int *geom_indexes, int geom_indexes_count) {
// TODO can we sort all animated geometries (in brush) to have only a single range here?
for (int i = 0; i < geom_indexes_count; ++i) {
const int index = geom_indexes[i];
const vk_staging_buffer_args_t staging_args = {
.buffer = g_ray_model_state.kusochki_buffer.buffer,
.offset = (model->kusochki_offset + index) * sizeof(vk_kusok_data_t),
.size = sizeof(vk_kusok_data_t),
.alignment = 16,
};
const vk_staging_region_t kusok_staging = R_VkStagingLockForBuffer(staging_args);
if (!kusok_staging.ptr) {
gEngine.Con_Printf(S_ERROR "Couldn't allocate staging for %d kusochek for model %s\n", 1, render_model->debug_name);
return false;
}
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
vk_render_geometry_t *geom = render_model->geometries + index;
applyMaterialToKusok(kusochki + 0, geom, render_model->color, material_mode);
Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + 0)->model.prev_transform);
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
/* render_model->debug_name, */
/* render_model->num_geometries, */
/* model->kusochki_offset, */
/* staging_args.offset, staging_args.size, */
/* kusok_staging.handle */
/* ); */
R_VkStagingUnlock(kusok_staging.handle);
}
return true;
}
static qboolean uploadKusochki(const vk_ray_model_t *const model, const vk_render_model_t *const render_model, uint32_t material_mode) {
const vk_staging_buffer_args_t staging_args = {
.buffer = g_ray_model_state.kusochki_buffer.buffer,
.offset = model->kusochki_offset * sizeof(vk_kusok_data_t),
.size = render_model->num_geometries * sizeof(vk_kusok_data_t),
.alignment = 16,
};
const vk_staging_region_t kusok_staging = R_VkStagingLockForBuffer(staging_args);
if (!kusok_staging.ptr) {
gEngine.Con_Printf(S_ERROR "Couldn't allocate staging for %d kusochkov for model %s\n", model->num_geoms, render_model->debug_name);
return false;
}
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
for (int i = 0; i < render_model->num_geometries; ++i) {
vk_render_geometry_t *geom = render_model->geometries + i;
applyMaterialToKusok(kusochki + i, geom, render_model->color, material_mode);
Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->model.prev_transform);
}
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
/* render_model->debug_name, */
/* render_model->num_geometries, */
/* model->kusochki_offset, */
/* staging_args.offset, staging_args.size, */
/* kusok_staging.handle */
/* ); */
R_VkStagingUnlock(kusok_staging.handle);
return true;
}
void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render_model, const matrix3x4 *transform_row) {
vk_ray_draw_model_t* draw_model = g_ray_model_state.frame.models + g_ray_model_state.frame.num_models;
@ -368,11 +441,7 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
return;
}
{
ASSERT(model->as != VK_NULL_HANDLE);
draw_model->model = model;
memcpy(draw_model->transform_row, *transform_row, sizeof(draw_model->transform_row));
}
ASSERT(model->as != VK_NULL_HANDLE);
uint32_t material_mode = MATERIAL_MODE_OPAQUE;
switch (render_model->render_type) {
@ -399,45 +468,28 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
gEngine.Host_Error("Unexpected render type %d\n", render_model->render_type);
}
draw_model->material_mode = material_mode;
// Re-upload kusochki if needed
// TODO all of this will not be required when model data is split out from Kusok struct
#define Vector4Compare(v1,v2) ((v1)[0]==(v2)[0] && (v1)[1]==(v2)[1] && (v1)[2]==(v2)[2] && (v1)[3]==(v2)[3])
const qboolean upload_kusochki = (model->material_mode != material_mode
|| !Vector4Compare(model->color, render_model->color)
|| memcmp(model->prev_transform, render_model->prev_transform, sizeof(matrix4x4)) != 0);
// TODO optimize:
// - collect list of geoms for which we could update anything (animated textues, uvs, etc)
// - update only those through staging
// - also consider tracking whether the main model color has changed (that'd need to update everything yay)
if (!model->kusochki_updated_this_frame)
{
const vk_staging_buffer_args_t staging_args = {
.buffer = g_ray_model_state.kusochki_buffer.buffer,
.offset = model->kusochki_offset * sizeof(vk_kusok_data_t),
.size = render_model->num_geometries * sizeof(vk_kusok_data_t),
.alignment = 16,
};
const vk_staging_region_t kusok_staging = R_VkStagingLockForBuffer(staging_args);
if (!kusok_staging.ptr) {
gEngine.Con_Printf(S_ERROR "Couldn't allocate staging for %d kusochkov for model %s\n", model->num_geoms, render_model->debug_name);
if (upload_kusochki) {
model->material_mode = material_mode;
Vector4Copy(render_model->color, model->color);
Matrix4x4_Copy(model->prev_transform, render_model->prev_transform);
if (!uploadKusochki(model, render_model, material_mode)) {
return;
}
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
for (int i = 0; i < render_model->num_geometries; ++i) {
vk_render_geometry_t *geom = render_model->geometries + i;
applyMaterialToKusok(kusochki + i, geom, render_model->color, material_mode);
Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->model.prev_transform);
}
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
/* render_model->debug_name, */
/* render_model->num_geometries, */
/* model->kusochki_offset, */
/* staging_args.offset, staging_args.size, */
/* kusok_staging.handle */
/* ); */
R_VkStagingUnlock(kusok_staging.handle);
model->kusochki_updated_this_frame = true;
} else {
if (!uploadKusochkiSubset(model, render_model, material_mode, render_model->geometries_changed, render_model->geometries_changed_count))
return;
}
for (int i = 0; i < render_model->dynamic_polylights_count; ++i) {
@ -447,6 +499,10 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
RT_LightAddPolygon(polylight);
}
draw_model->model = model;
memcpy(draw_model->transform_row, *transform_row, sizeof(draw_model->transform_row));
draw_model->material_mode = material_mode;
g_ray_model_state.frame.num_models++;
}
@ -462,7 +518,6 @@ void XVK_RayModel_ClearForNextFrame( void ) {
for (int i = 0; i < g_ray_model_state.frame.num_models; ++i) {
vk_ray_draw_model_t *model = g_ray_model_state.frame.models + i;
ASSERT(model->model);
model->model->kusochki_updated_this_frame = false;
if (!model->model->dynamic)
continue;

View File

@ -116,6 +116,9 @@ typedef struct vk_render_model_s {
int num_geometries;
vk_render_geometry_t *geometries;
int geometries_changed_count;
int *geometries_changed;
// This model will be one-frame only, its buffers are not preserved between frames
qboolean dynamic;

View File

@ -54,10 +54,9 @@ static void GL_BackendEndFrame_UNUSED( void )
}
// debug
static void R_ShowTextures( void )
static void R_ShowTextures_UNUSED( void )
{
PRINT_NOT_IMPLEMENTED();
//PRINT_NOT_IMPLEMENTED();
/* Unused in Vulkan renderer. No need to debug textures this way */
}
// texture management
@ -352,9 +351,15 @@ static void GL_OrthoBounds( const float *mins, const float *maxs )
}
// get visdata for current frame from custom renderer
static byte* Mod_GetCurrentVis( void )
{
PRINT_NOT_IMPLEMENTED();
static byte* Mod_GetCurrentVis( void ) {
// ref_soft just returns NULL here
// Not sure if we need to copy what ref_gl does. What it does is:
// - Setup camera and call R_MarkLeaves() in R_RenderScene()
// - R_MarkLeaves() sets RI.visbytes
// will be eventually needed for culling in traditional renderer, see:
// - https://github.com/w23/xash3d-fwgs/pull/96
// - https://github.com/w23/xash3d-fwgs/issues/93
// - Return RI.visbytes here (if not using custom rendering)
return NULL;
}
@ -477,7 +482,7 @@ static const ref_interface_t gReffuncs =
CL_AddCustomBeam,
R_ProcessEntData,
R_ShowTextures,
.R_ShowTextures = R_ShowTextures_UNUSED,
R_GetTextureOriginalBuffer,
VK_LoadTextureFromBuffer,
@ -564,7 +569,7 @@ static const ref_interface_t gReffuncs =
VK_RenderFrame,
GL_OrthoBounds,
.R_SpeedsMessage = R_SpeedsMessage,
Mod_GetCurrentVis,
.Mod_GetCurrentVis = Mod_GetCurrentVis,
R_NewMap,
R_ClearScene,
R_GetProcAddress,