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:
commit
0d8a7f76f5
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue