vk: rt: allow per-model back face culling

Make transparent studio models, e.g. holograms, single-sided.

Related: #665
This commit is contained in:
Ivan Avdeev 2023-12-22 15:14:27 -05:00
parent caac371681
commit 180f3ed9cb
9 changed files with 22 additions and 3 deletions

View File

@ -700,6 +700,7 @@ static void brushDrawWater(r_brush_water_model_t *wmodel, const cl_entity_t *ent
R_RenderModelDraw(&wmodel->render_model, (r_model_draw_t){
.render_type = render_type,
.material_mode = material_mode,
.material_flags = kMaterialFlag_None,
.color = (const vec4_t*)color,
.transform = (const matrix4x4*)transform,
.prev_transform = (const matrix4x4*)prev_transform,
@ -949,6 +950,7 @@ void R_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, con
R_RenderModelDraw(&bmodel->render_model, (r_model_draw_t){
.render_type = render_type,
.material_mode = material_mode,
.material_flags = kMaterialFlag_None,
.color = &color,
.transform = &transform,
.prev_transform = &bmodel->prev_transform,

View File

@ -270,13 +270,16 @@ vk_resource_t RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
.instanceShaderBindingTableRecordOffset = 0,
.accelerationStructureReference = instance->blas_addr,
};
const VkGeometryInstanceFlagsKHR flags = (instance->material_flags & kMaterialFlag_CullBackFace_Bit) ? 0 : VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
switch (instance->material_mode) {
case MATERIAL_MODE_OPAQUE:
inst[i].mask = GEOMETRY_BIT_OPAQUE;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
// Force no-culling because there are cases where culling leads to leaking shadows, holes in reflections, etc
// CULL_DISABLE_BIT disables culling even if the gl_RayFlagsCullFrontFacingTrianglesEXT bit is set in shaders
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR | VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR | flags;
break;
case MATERIAL_MODE_OPAQUE_ALPHA_TEST:
inst[i].mask = GEOMETRY_BIT_ALPHA_TEST;
@ -287,7 +290,7 @@ vk_resource_t RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
inst[i].mask = GEOMETRY_BIT_REFRACTIVE;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
// Disable culling for translucent surfaces: decide what side it is based on normal wrt ray directions
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR | VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR | flags;
break;
case MATERIAL_MODE_BLEND_ADD:
case MATERIAL_MODE_BLEND_MIX:
@ -295,7 +298,7 @@ vk_resource_t RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
inst[i].mask = GEOMETRY_BIT_BLEND;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_ADDITIVE,
// Force no-culling because these should be visible from any angle
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR | VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR | flags;
break;
default:
gEngine.Host_Error("Unexpected material mode %d\n", instance->material_mode);

View File

@ -20,6 +20,7 @@ typedef struct rt_draw_instance_s {
matrix4x4 prev_transform_row;
vec4_t color;
uint32_t material_mode; // MATERIAL_MODE_ from ray_interop.h
uint32_t material_flags; // material_flag_bits_e
} rt_draw_instance_t;
typedef struct {

View File

@ -361,6 +361,7 @@ void RT_FrameAddModel( struct rt_model_s *model, rt_frame_add_model_t args ) {
draw_instance->blas_addr = model->blas_addr;
draw_instance->kusochki_offset = kusochki_offset;
draw_instance->material_mode = args.material_mode;
draw_instance->material_flags = args.material_flags;
sRGBtoLinearVec4(*args.color_srgb, draw_instance->color);
Matrix3x4_Copy(draw_instance->transform_row, args.transform);
Matrix4x4_Copy(draw_instance->prev_transform_row, args.prev_transform);
@ -453,6 +454,7 @@ void RT_DynamicModelProcessFrame(void) {
draw_instance->blas_addr = dyn->blas_addr;
draw_instance->kusochki_offset = kusochki_offset;
draw_instance->material_mode = i;
draw_instance->material_flags = 0;
Vector4Set(draw_instance->color, 1, 1, 1, 1);
Matrix3x4_LoadIdentity(draw_instance->transform_row);
Matrix4x4_LoadIdentity(draw_instance->prev_transform_row);

View File

@ -791,6 +791,7 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) {
ASSERT(model->rt_model);
RT_FrameAddModel(model->rt_model, (rt_frame_add_model_t){
.material_mode = args.material_mode,
.material_flags = args.material_flags,
.transform = (const matrix3x4*)args.transform,
.prev_transform = (const matrix3x4*)args.prev_transform,
.color_srgb = args.color,

View File

@ -123,9 +123,15 @@ void R_RenderModelDestroy( vk_render_model_t* model );
qboolean R_RenderModelUpdate( const vk_render_model_t *model );
qboolean R_RenderModelUpdateMaterials( const vk_render_model_t *model, const int *geom_indices, int geom_indices_count);
typedef enum {
kMaterialFlag_None = 0,
kMaterialFlag_CullBackFace_Bit = (1<<0),
} material_flag_bits_e;
typedef struct {
vk_render_type_e render_type; // TODO rename legacy
material_mode_e material_mode;
uint32_t material_flags; // material_flag_bits_e
// These are "consumed": copied into internal storage and can be pointers to stack vars
const vec4_t *color;

View File

@ -58,6 +58,8 @@ qboolean RT_ModelUpdateMaterials(struct rt_model_s *model, const struct vk_rende
typedef struct {
int material_mode;
uint32_t material_flags;
const matrix3x4 *transform, *prev_transform;
const vec4_t *color_srgb;

View File

@ -808,6 +808,7 @@ static void R_DrawSpriteQuad( const char *debug_name, const mspriteframe_t *fram
R_RenderModelDraw(&g_sprite.quad.model, (r_model_draw_t){
.render_type = render_type,
.material_mode = material_mode,
.material_flags = kMaterialFlag_None,
.color = (const vec4_t*)color,
.transform = &transform,
.prev_transform = &transform,

View File

@ -2331,6 +2331,7 @@ static void R_StudioDrawPoints( void ) {
R_RenderModelDraw(&render_submodel->model, (r_model_draw_t){
.render_type = render_type,
.material_mode = material_mode,
.material_flags = kMaterialFlag_CullBackFace_Bit, // TODO for transparent only?
.color = &color,
.transform = &g_studio_current.entmodel->transform,
.prev_transform = &g_studio_current.entmodel->prev_transform,