rt: commoditize setting material mode

Known issues:
- Breaks sprite glow for some reason.
This commit is contained in:
Ivan 'provod' Avdeev 2023-04-24 11:38:12 -07:00 committed by Ivan Avdeev
parent 5b370509fe
commit 1ebc1d207c
11 changed files with 53 additions and 66 deletions

View File

@ -140,8 +140,7 @@ bool shadowedSky(vec3 pos, vec3 dir) {
const uint kusok_index = instance_kusochki_offset + geometry_index;
const Kusok kusok = getKusok(kusok_index);
// TODO this flag can be encoded into custom index, so that we'd need no extra indirection
if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) == 0)
if (kusok.material.mode != MATERIAL_MODE_SKYBOX)
return true;
}

View File

@ -49,7 +49,7 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT)
#define GEOMETRY_BIT_OPAQUE 0x01
#define GEOMETRY_BIT_ALPHA_TEST 0x02
#define GEOMETRY_BIT_ADDITIVE 0x04
#define GEOMETRY_BIT_BLEND 0x04
#define GEOMETRY_BIT_REFRACTIVE 0x08
#define SHADER_OFFSET_MISS_REGULAR 0
@ -63,11 +63,16 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT)
#define SHADER_OFFSET_HIT_REGULAR_BASE 0
#define SHADER_OFFSET_HIT_SHADOW_BASE 3
#define KUSOK_MATERIAL_FLAG_SKYBOX (1<<0)
#define KUSOK_MATERIAL_FLAG_FIXME_GLOW (1<<1)
#define MATERIAL_MODE_OPAQUE 0
#define MATERIAL_MODE_OPAQUE_ALPHA_TEST 1
#define MATERIAL_MODE_TRANSLUCENT 2
#define MATERIAL_MODE_BLEND_ADD 3
#define MATERIAL_MODE_BLEND_MIX 4
#define MATERIAL_MODE_BLEND_GLOW 5
#define MATERIAL_MODE_SKYBOX 6
struct Material {
uint flags;
uint mode;
uint tex_base_color;

View File

@ -29,7 +29,7 @@ void main() {
const Kusok kusok = getKusok(geom.kusok_index);
if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) {
if (kusok.material.mode == MATERIAL_MODE_SKYBOX) {
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb);
return;
} else {

View File

@ -30,7 +30,7 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) {
const Kusok kusok = getKusok(geom.kusok_index);
const Material material = kusok.material;
if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) {
if (kusok.material.mode == MATERIAL_MODE_SKYBOX) {
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb);
return;
} else {

View File

@ -12,5 +12,5 @@ void main() {
const Kusok kusok = getKusok(kusok_index);
const uint tex_base_color = kusok.material.tex_base_color;
payload_shadow.hit_type = ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) ? SHADOW_HIT : SHADOW_SKY ;
payload_shadow.hit_type = (kusok.material.mode != MATERIAL_MODE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ;
}

View File

@ -10,7 +10,7 @@ vec3 traceAdditive(vec3 pos, vec3 dir, float L) {
//| gl_RayFlagsSkipClosestHitShaderEXT
| gl_RayFlagsNoOpaqueEXT // force all to be non-opaque
;
rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_ADDITIVE, pos, 0., dir, L + additive_soft_overshoot);
rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_BLEND, pos, 0., dir, L + additive_soft_overshoot);
while (rayQueryProceedEXT(rq)) {
const MiniGeometry geom = readCandidateMiniGeometry(rq);
const Kusok kusok = getKusok(geom.kusok_index);
@ -23,7 +23,7 @@ vec3 traceAdditive(vec3 pos, vec3 dir, float L) {
if (overshoot < 0.)
ret += color;
else if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_FIXME_GLOW) != 0)
else if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW)
ret += color * smoothstep(additive_soft_overshoot, 0., overshoot);
}
return ret;

View File

@ -189,26 +189,32 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
.accelerationStructureReference = getASAddress(model->model->as), // TODO cache this addr
};
switch (model->material_mode) {
case MaterialMode_Opaque:
case MATERIAL_MODE_OPAQUE:
case MATERIAL_MODE_SKYBOX:
inst[i].mask = GEOMETRY_BIT_OPAQUE;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR;
break;
case MaterialMode_Opaque_AlphaTest:
case MATERIAL_MODE_OPAQUE_ALPHA_TEST:
inst[i].mask = GEOMETRY_BIT_ALPHA_TEST;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_ALPHA_TEST,
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR;
break;
case MaterialMode_Refractive:
case MATERIAL_MODE_TRANSLUCENT:
inst[i].mask = GEOMETRY_BIT_REFRACTIVE;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR;
break;
case MaterialMode_Additive:
inst[i].mask = GEOMETRY_BIT_ADDITIVE;
case MATERIAL_MODE_BLEND_ADD:
case MATERIAL_MODE_BLEND_MIX:
case MATERIAL_MODE_BLEND_GLOW:
inst[i].mask = GEOMETRY_BIT_BLEND;
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_ADDITIVE,
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR;
break;
default:
gEngine.Host_Error("Unexpected material mode %d\n", model->material_mode);
break;
}
memcpy(&inst[i].transform, model->transform_row, sizeof(VkTransformMatrixKHR));
}

View File

@ -31,13 +31,7 @@ typedef struct Kusok vk_kusok_data_t;
typedef struct {
matrix3x4 transform_row;
vk_ray_model_t *model;
enum {
MaterialMode_Opaque,
MaterialMode_Opaque_AlphaTest,
MaterialMode_Refractive,
// TODO MaterialMode_Subtractive,
MaterialMode_Additive,
} material_mode;
uint32_t material_mode; // MATERIAL_MODE_ from ray_interop.h
} vk_ray_draw_model_t;
typedef struct {

View File

@ -155,7 +155,7 @@ void XVK_RayModel_Validate( void ) {
}
}
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, const vec4_t color, qboolean HACK_reflective) {
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, const vec4_t model_color, uint32_t mode) {
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture );
ASSERT(mat);
@ -166,7 +166,7 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
kusok->triangles = geom->element_count / 3;
kusok->material = (struct Material){
.flags = 0,
.mode = mode,
.tex_base_color = mat->tex_base_color,
.tex_roughness = mat->tex_roughness,
@ -178,26 +178,20 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
.normal_scale = mat->normal_scale,
};
// HACK until there is a proper mechanism for patching materials, see https://github.com/w23/xash3d-fwgs/issues/213
// FIXME also this erases previous roughness unconditionally
if (HACK_reflective) {
kusok->material.tex_roughness = tglob.blackTexture;
} else if (!mat->set && geom->material == kXVkMaterialChrome) {
const qboolean HACK_chrome = geom->material == kXVkMaterialChrome;
if (!mat->set && HACK_chrome)
kusok->material.tex_roughness = tglob.grayTexture;
}
if (geom->material == kXVkMaterialSky)
kusok->material.flags |= KUSOK_MATERIAL_FLAG_SKYBOX;
if (geom->material == kXVkMaterialEmissiveGlow)
kusok->material.flags |= KUSOK_MATERIAL_FLAG_FIXME_GLOW;
kusok->material.mode = MATERIAL_MODE_SKYBOX;
// FIXME modulates model_color with material->base_color which has different frequency
{
vec4_t gcolor;
gcolor[0] = color[0] * mat->base_color[0];
gcolor[1] = color[1] * mat->base_color[1];
gcolor[2] = color[2] * mat->base_color[2];
gcolor[3] = color[3] * mat->base_color[3];
gcolor[0] = model_color[0] * mat->base_color[0];
gcolor[1] = model_color[1] * mat->base_color[1];
gcolor[2] = model_color[2] * mat->base_color[2];
gcolor[3] = model_color[3] * mat->base_color[3];
Vector4Copy(gcolor, kusok->model.color);
}
@ -271,7 +265,7 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
.firstVertex = mg->vertex_offset,
};
applyMaterialToKusok(kusochki + i, mg, args.model->color, false);
applyMaterialToKusok(kusochki + i, mg, args.model->color, MATERIAL_MODE_OPAQUE);
Matrix4x4_LoadIdentity(kusochki[i].model.prev_transform);
}
@ -408,37 +402,31 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
memcpy(draw_model->transform_row, *transform_row, sizeof(draw_model->transform_row));
}
qboolean HACK_reflective = false;
qboolean HACK_additive_emissive = false;
uint32_t material_mode = MATERIAL_MODE_OPAQUE;
switch (render_model->render_type) {
case kVkRenderTypeSolid:
draw_model->material_mode = MaterialMode_Opaque;
break;
case kVkRenderType_A_1mA_RW: // blend: scr*a + dst*(1-a), depth: RW
case kVkRenderType_A_1mA_R: // blend: scr*a + dst*(1-a), depth test
// FIXME proper trasnlucency
//HACK_reflective = true;
//draw_model->material_mode = MaterialMode_Refractive;
HACK_additive_emissive = true;
draw_model->material_mode = MaterialMode_Additive;
material_mode = MATERIAL_MODE_BLEND_MIX;
break;
case kVkRenderType_A_1: // blend: scr*a + dst, no depth test or write; sprite:kRenderGlow only
material_mode = MATERIAL_MODE_BLEND_GLOW;
break;
case kVkRenderType_A_1: // blend: scr*a + dst, no depth test or write
case kVkRenderType_A_1_R: // blend: scr*a + dst, depth test
case kVkRenderType_1_1_R: // blend: scr + dst, depth test
HACK_additive_emissive = true;
draw_model->material_mode = MaterialMode_Additive;
material_mode = MATERIAL_MODE_BLEND_ADD;
break;
case kVkRenderType_AT: // no blend, depth RW, alpha test
draw_model->material_mode = MaterialMode_Opaque_AlphaTest;
material_mode = MATERIAL_MODE_OPAQUE_ALPHA_TEST;
break;
default:
gEngine.Host_Error("Unexpected render type %d\n", render_model->render_type);
}
draw_model->material_mode = material_mode;
// TODO optimize:
// - collect list of geoms for which we could update anything (animated textues, uvs, etc)
// - update only those through staging
@ -464,11 +452,11 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render
vk_render_geometry_t *geom = render_model->geometries + i;
// FIXME an impedance mismatch: render_type is per-model, while materials and emissive color are per-geom
if (HACK_additive_emissive) {
VectorCopy(render_model->color, geom->emissive);
}
/* if (HACK_additive_emissive) { */
/* VectorCopy(render_model->color, geom->emissive); */
/* } */
applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective);
applyMaterialToKusok(kusochki + i, geom, render_model->color, material_mode);
Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->model.prev_transform);
}

View File

@ -25,15 +25,10 @@ typedef enum {
kXVkMaterialRegular = 0,
// Set for SURF_DRAWSKY surfaces in vk_brush.c.
// Used: for setting KUSOK_MATERIAL_FLAG_SKYBOX for skybox texture sampling and environment shadows.
// Used: for setting MATERIAL_MODE_SKYBOX for skybox texture sampling and environment shadows.
// Remove: pass it as a special texture/material index (e.g. -2).
kXVkMaterialSky,
// Set by glow sprites only.
// Used: glow means no depth test. Allows for slight ray overshoot (KUSOK_MATERIAL_FLAG_FIXME_GLOW). Special exclusive case for sprites. Desired effect: "bloom" from bright light sources.
// Remove: in favor of "real" pbr hdr, tonemapping and bloop.
kXVkMaterialEmissiveGlow,
// Set for chrome studio submodels.
// Used: ray tracing sets gray roughness texture to get smooth surface look.
// Remove: Have an explicit material for chrome surfaces.

View File

@ -730,7 +730,7 @@ static void R_DrawSpriteQuad( const char *debug_name, mspriteframe_t *frame, vec
{
const vk_render_geometry_t geometry = {
.texture = texture,
.material = render_mode == kRenderGlow ? kXVkMaterialEmissiveGlow : kXVkMaterialRegular,
.material = kXVkMaterialRegular,
.max_vertex = 4,
.vertex_offset = buffer.vertices.unit_offset,