diff --git a/ref/vk/NOTES.md b/ref/vk/NOTES.md index e1029bef..8ed2cead 100644 --- a/ref/vk/NOTES.md +++ b/ref/vk/NOTES.md @@ -398,3 +398,17 @@ TODO: can we not have a BLAS/model for each submodel? Can it be per-model instea # 2023-07-30 - ~~R_DrawStudioModel is the main func for drawing studio model. Called from scene code for each studio entity, with everything current (RI and stuff) set up~~ - `R_StudioDrawModelInternal()` is the main one. It is where it splits into renderer-vs-game rendering functions. + +# 2023-09-19 E298 +## SURF_DRAWSKY +- (context: want to remove kXVkMaterialSky, #474) +- qrad: + - uses textue name "sky" or "SKY" to check `IsSky()`. `IsSky()` surfaces do not get patches and do not participate in radiosity. + - uses CONTENTS_SKY node flag to detect whether a ray has hit skybox and can contribute sky light. +- xash/gl: + - CONTENTS_SKY is not used in any meaningful way + - sets SURF_DRAWSKY for surfaces with "sky" texture. + - uses SURF_DRAWSKY: + - to build skychain, and then draw it in Quake mode (the other branch does a bunch of math, which seemingly isn't used for anything at all). + - for dynamic lighting: if sky ray has hit sky surface then sky is contributing light + diff --git a/ref/vk/vk_brush.c b/ref/vk/vk_brush.c index c2fa4ae0..11a1bfee 100644 --- a/ref/vk/vk_brush.c +++ b/ref/vk/vk_brush.c @@ -275,9 +275,10 @@ static void brushComputeWaterPolys( compute_water_polys_t args ) { // Render const int tex_id = args.warp->texinfo->texture->gl_texturenum; + const r_vk_material_ref_t material_ref = R_VkMaterialGetForTexture(tex_id); *args.dst_geometry = (vk_render_geometry_t){ - .texture = tex_id, // FIXME assert >= 0 - .material = kXVkMaterialRegular, + .material = material_ref, + .material_type_deprecated = kXVkMaterialRegular, .surf_deprecate = args.warp, .max_vertex = vertices, @@ -704,7 +705,7 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co // 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; + geom->material = R_VkMaterialGetForTexture(tglob.whiteTexture); } } else { APROF_SCOPE_DECLARE_BEGIN(brush_update_textures, "brush: update animated textures"); @@ -719,10 +720,11 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co // 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); - const int new_texture = t->gl_texturenum; + const int tex_id = t->gl_texturenum; - if (new_texture >= 0 && new_texture != geom->texture) { - geom->texture = t->gl_texturenum; + const r_vk_material_ref_t new_material = R_VkMaterialGetForTexture(tex_id); + if (new_material.index >= 0 && new_material.index != geom->material.index) { + geom->material = new_material; if (updated_textures_count < MAX_ANIMATED_TEXTURES) { g_brush.updated_textures[updated_textures_count++] = bmodel->animated_indexes[i]; } @@ -732,7 +734,7 @@ void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode, float blend, co // Add them as dynamic lights for now. It would probably be better if they were static lights (for worldmodel), // but there's no easy way to do it for now. vec3_t *emissive = &bmodel->render_model.geometries[geom_index].emissive; - if (RT_GetEmissiveForTexture(*emissive, geom->texture)) { + if (RT_GetEmissiveForTexture(*emissive, tex_id)) { rt_light_add_polygon_t polylight = loadPolyLight(mod, surface_index, geom->surf_deprecate, *emissive); polylight.dynamic = true; polylight.transform_row = (const matrix3x4*)&transform; @@ -1075,7 +1077,7 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { VectorClear(model_geometry->emissive); model_geometry->surf_deprecate = surf; - model_geometry->texture = tex_id; + model_geometry->material = R_VkMaterialGetForTexture(tex_id); model_geometry->vertex_offset = args.base_vertex_offset; model_geometry->max_vertex = vertex_offset + surf->numedges; @@ -1083,9 +1085,9 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { model_geometry->index_offset = index_offset; if(type == BrushSurface_Sky) { - model_geometry->material = kXVkMaterialSky; + model_geometry->material_type_deprecated = kXVkMaterialSky; } else { - model_geometry->material = kXVkMaterialRegular; + model_geometry->material_type_deprecated = kXVkMaterialRegular; ASSERT(!FBitSet( surf->flags, SURF_DRAWTILED )); VK_CreateSurfaceLightmap( surf, args.mod ); } diff --git a/ref/vk/vk_materials.c b/ref/vk/vk_materials.c index e73cdd84..f3de6d1e 100644 --- a/ref/vk/vk_materials.c +++ b/ref/vk/vk_materials.c @@ -11,7 +11,7 @@ #define MAX_INCLUDE_DEPTH 4 -static xvk_material_t k_default_material = { +static r_vk_material_t k_default_material = { .tex_base_color = -1, .tex_metalness = 0, .tex_roughness = 0, @@ -26,7 +26,7 @@ static xvk_material_t k_default_material = { }; static struct { - xvk_material_t materials[MAX_TEXTURES]; + r_vk_material_t materials[MAX_TEXTURES]; } g_materials; static struct { @@ -70,7 +70,7 @@ static void loadMaterialsFromFile( const char *filename, int depth ) { g_stats.material_file_read_duration_ns += aprof_time_now_ns() - load_file_begin_ns; char *pos = (char*)data; - xvk_material_t current_material = k_default_material; + r_vk_material_t current_material = k_default_material; int current_material_index = -1; qboolean force_reload = false; qboolean create = false; @@ -215,7 +215,7 @@ static void loadMaterialsFromFileF( const char *fmt, ... ) { loadMaterialsFromFile( buffer, MAX_INCLUDE_DEPTH ); } -void XVK_ReloadMaterials( void ) { +void R_VkMaterialsReload( void ) { memset(&g_stats, 0, sizeof(g_stats)); const uint64_t begin_time_ns = aprof_time_now_ns(); @@ -223,7 +223,7 @@ void XVK_ReloadMaterials( void ) { k_default_material.tex_roughness = tglob.whiteTexture; for (int i = 0; i < MAX_TEXTURES; ++i) { - xvk_material_t *const mat = g_materials.materials + i; + r_vk_material_t *const mat = g_materials.materials + i; const vk_texture_t *const tex = findTexture( i ); *mat = k_default_material; @@ -264,14 +264,18 @@ void XVK_ReloadMaterials( void ) { } } -xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index ) { - xvk_material_t *mat = NULL; +r_vk_material_ref_t R_VkMaterialGetForTexture( int tex_index ) { ASSERT(tex_index >= 0); ASSERT(tex_index < MAX_TEXTURES); - mat = g_materials.materials + tex_index; - if (mat->base_color >= 0) - return mat; - - return NULL; + // TODO add versioning to detect reloads? + return (r_vk_material_ref_t){ .index = tex_index, }; +} + +const r_vk_material_t* R_VkMaterialGet( r_vk_material_ref_t ref ) { + ASSERT(ref.index >= 0); + ASSERT(ref.index < MAX_TEXTURES); + + // TODO verify version ? + return g_materials.materials + ref.index; } diff --git a/ref/vk/vk_materials.h b/ref/vk/vk_materials.h index 3eec91c7..294c6010 100644 --- a/ref/vk/vk_materials.h +++ b/ref/vk/vk_materials.h @@ -2,7 +2,7 @@ #include "xash3d_types.h" -typedef struct { +typedef struct r_vk_material_s { int tex_base_color; int tex_roughness; int tex_metalness; @@ -14,8 +14,14 @@ typedef struct { float normal_scale; qboolean set; -} xvk_material_t; +} r_vk_material_t; -void XVK_ReloadMaterials( void ); +typedef struct { int index; } r_vk_material_ref_t; -xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index ); +// Note: invalidates all previously issued material refs +// TODO: track "version" in high bits? +void R_VkMaterialsReload( void ); + +r_vk_material_ref_t R_VkMaterialGetForTexture( int tex_id ); + +const r_vk_material_t* R_VkMaterialGet( r_vk_material_ref_t ref ); diff --git a/ref/vk/vk_ray_internal.h b/ref/vk/vk_ray_internal.h index decf0f51..e191b2cc 100644 --- a/ref/vk/vk_ray_internal.h +++ b/ref/vk/vk_ray_internal.h @@ -101,8 +101,8 @@ rt_kusochki_t RT_KusochkiAllocLong(int count); uint32_t RT_KusochkiAllocOnce(int count); void RT_KusochkiFree(const rt_kusochki_t*); -struct vk_render_geometry_s; -qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_color); +//struct vk_render_geometry_s; +//qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_color); qboolean RT_DynamicModelInit(void); void RT_DynamicModelShutdown(void); diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index 0de8855a..379c1d78 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -25,9 +25,8 @@ typedef struct rt_model_s { rt_kusochki_t kusochki; } rt_model_t; -static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, int override_texture_id, const vec4_t override_color) { - const int tex_id = override_texture_id > 0 ? override_texture_id : geom->texture; - const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( tex_id ); +static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom, const r_vk_material_t *override_material, const vec4_t override_color) { + const r_vk_material_t *const mat = override_material ? override_material : R_VkMaterialGet(geom->material); ASSERT(mat); // TODO split kusochki into static geometry data and potentially dynamic material data @@ -59,12 +58,12 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr } // TODO should be patched by the Chrome material source itself to generate a static chrome material - const qboolean HACK_chrome = geom->material == kXVkMaterialChrome; + const qboolean HACK_chrome = geom->material_type_deprecated == kXVkMaterialChrome; if (!mat->set && HACK_chrome) kusok->material.tex_roughness = tglob.grayTexture; // Purely static. Once a sky forever a sky. - if (geom->material == kXVkMaterialSky) + if (geom->material_type_deprecated == kXVkMaterialSky) kusok->material.tex_base_color = TEX_BASE_SKYBOX; } @@ -180,7 +179,7 @@ void RT_KusochkiFree(const rt_kusochki_t *kusochki) { } // TODO this function can't really fail. It'd mean that staging is completely broken. -qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, int override_texture_id, const vec4_t *override_colors) { +qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geometry_s *geoms, int geoms_count, const r_vk_material_t *override_material, const vec4_t *override_colors) { const vk_staging_buffer_args_t staging_args = { .buffer = g_ray_model_state.kusochki_buffer.buffer, .offset = kusochki_offset * sizeof(vk_kusok_data_t), @@ -197,7 +196,7 @@ qboolean RT_KusochkiUpload(uint32_t kusochki_offset, const struct vk_render_geom vk_kusok_data_t *const p = kusok_staging.ptr; for (int i = 0; i < geoms_count; ++i) { const vk_render_geometry_t *geom = geoms + i; - applyMaterialToKusok(p + i, geom, override_texture_id, override_colors ? override_colors[i] : NULL); + applyMaterialToKusok(p + i, geom, override_material, override_colors ? override_colors[i] : NULL); } R_VkStagingUnlock(kusok_staging.handle); @@ -222,7 +221,7 @@ struct rt_model_s *RT_ModelCreate(rt_model_create_t args) { goto fail; } - RT_KusochkiUpload(kusochki.offset, args.geometries, args.geometries_count, -1, NULL); + RT_KusochkiUpload(kusochki.offset, args.geometries, args.geometries_count, NULL, NULL); { rt_model_t *const ret = Mem_Malloc(vk_core.pool, sizeof(*ret)); @@ -275,7 +274,7 @@ qboolean RT_ModelUpdateMaterials(struct rt_model_s *model, const struct vk_rende const int offset = geom_indices[begin]; const int count = i - begin; ASSERT(offset + count <= geometries_count); - if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, -1, NULL)) { + if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, NULL, NULL)) { APROF_SCOPE_END(update_materials); return false; } @@ -288,7 +287,7 @@ qboolean RT_ModelUpdateMaterials(struct rt_model_s *model, const struct vk_rende const int offset = geom_indices[begin]; const int count = geom_indices_count - begin; ASSERT(offset + count <= geometries_count); - if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, -1, NULL)) { + if (!RT_KusochkiUpload(model->kusochki.offset + offset, geometries + offset, count, NULL, NULL)) { APROF_SCOPE_END(update_materials); return false; @@ -314,12 +313,12 @@ void RT_FrameAddModel( struct rt_model_s *model, rt_frame_add_model_t args ) { uint32_t kusochki_offset = model->kusochki.offset; - if (args.override.textures > 0) { + if (args.override.material != NULL) { kusochki_offset = RT_KusochkiAllocOnce(args.override.geoms_count); if (kusochki_offset == ALO_ALLOC_FAILED) return; - if (!RT_KusochkiUpload(kusochki_offset, args.override.geoms, args.override.geoms_count, args.override.textures, NULL)) { + if (!RT_KusochkiUpload(kusochki_offset, args.override.geoms, args.override.geoms_count, args.override.material, NULL)) { gEngine.Con_Printf(S_ERROR "Couldn't upload kusochki for instanced model\n"); return; } @@ -413,7 +412,7 @@ void RT_DynamicModelProcessFrame(void) { } // FIXME override color - if (!RT_KusochkiUpload(kusochki_offset, dyn->geometries, dyn->geometries_count, -1, dyn->colors)) { + if (!RT_KusochkiUpload(kusochki_offset, dyn->geometries, dyn->geometries_count, NULL, dyn->colors)) { gEngine.Con_Printf(S_ERROR "Couldn't build blas for %d geoms of %s, skipping\n", dyn->geometries_count, group_names[i]); goto tail; } diff --git a/ref/vk/vk_render.c b/ref/vk/vk_render.c index 22683e40..ec01d265 100644 --- a/ref/vk/vk_render.c +++ b/ref/vk/vk_render.c @@ -723,7 +723,8 @@ static void submitToTraditionalRender( trad_submit_t args ) { for (int i = 0; i < args.geometries_count; ++i) { const vk_render_geometry_t *geom = args.geometries + i; - const int tex = args.textures_override > 0 ? args.textures_override : geom->texture; + const r_vk_material_t *material = R_VkMaterialGet(geom->material); + const int tex = args.textures_override > 0 ? args.textures_override : material->tex_base_color; const qboolean split = current_texture != tex || vertex_offset != geom->vertex_offset || (index_offset + element_count) != geom->index_offset; @@ -788,7 +789,7 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) { .dynamic_polylights = model->dynamic_polylights, .dynamic_polylights_count = model->dynamic_polylights_count, .override = { - .textures = args.textures_override, + .material = args.material_override, .geoms = model->geometries, .geoms_count = model->num_geometries, }, @@ -802,7 +803,7 @@ void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args) { .transform = args.transform, .color = args.color, .render_type = args.render_type, - .textures_override = args.textures_override + .textures_override = args.material_override ? args.material_override->tex_base_color : -1, }); } } @@ -820,8 +821,7 @@ void R_RenderDrawOnce(r_draw_once_t args) { R_GeometryBufferUnlock( &buffer ); const vk_render_geometry_t geometry = { - .texture = args.texture, - .material = kXVkMaterialRegular, + .material = args.material, .material_type_deprecated = kXVkMaterialRegular, .max_vertex = args.vertices_count, .vertex_offset = buffer.vertices.unit_offset, diff --git a/ref/vk/vk_render.h b/ref/vk/vk_render.h index 24dc2779..d6eeccc1 100644 --- a/ref/vk/vk_render.h +++ b/ref/vk/vk_render.h @@ -1,4 +1,5 @@ #pragma once +#include "vk_materials.h" #include "vk_common.h" #include "vk_const.h" #include "vk_core.h" @@ -27,7 +28,7 @@ typedef enum { // Used: ray tracing sets gray roughness texture to get smooth surface look. // Remove: Have an explicit material for chrome surfaces. kXVkMaterialChrome, -} XVkMaterialType; +} XVkMaterialType_Deprecated; typedef struct vk_render_geometry_s { int index_offset, vertex_offset; @@ -42,11 +43,9 @@ typedef struct vk_render_geometry_s { // Remove: have an explicit list of surfaces with animated textures const struct msurface_s *surf_deprecate; - // Animated textures will be dynamic and change between frames - int texture; - // If this geometry is special, it will have a material type override - XVkMaterialType material; + XVkMaterialType_Deprecated material_type_deprecated; + r_vk_material_ref_t material; // for kXVkMaterialEmissive{,Glow} and others vec3_t emissive; @@ -145,9 +144,7 @@ typedef struct { const vec4_t *color; const matrix4x4 *transform, *prev_transform; - // Global texture override if > 0 - // Used by sprite+quad instancing - int textures_override; + const r_vk_material_t* material_override; } r_model_draw_t; void R_RenderModelDraw(const vk_render_model_t *model, r_model_draw_t args); @@ -159,7 +156,7 @@ typedef struct { int vertices_count, indices_count; int render_type; - int texture; + r_vk_material_ref_t material; const vec4_t *emissive; const vec4_t *color; } r_draw_once_t; diff --git a/ref/vk/vk_rtx.h b/ref/vk/vk_rtx.h index 35798ec4..5bf2d2af 100644 --- a/ref/vk/vk_rtx.h +++ b/ref/vk/vk_rtx.h @@ -34,6 +34,7 @@ void VK_RayShutdown( void ); struct vk_render_geometry_s; struct rt_model_s; +struct r_vk_material_s; typedef enum { kBlasBuildStatic, // builds slow for fast trace @@ -63,7 +64,7 @@ typedef struct { int dynamic_polylights_count; struct { - int textures; // Override kusochki/material textures if > 0 + const struct r_vk_material_s *material; // These are needed in order to recreate kusochki geometry data // TODO remove when material data is split from kusochki diff --git a/ref/vk/vk_scene.c b/ref/vk/vk_scene.c index 5477b61d..2bad00b2 100644 --- a/ref/vk/vk_scene.c +++ b/ref/vk/vk_scene.c @@ -148,7 +148,7 @@ static void loadMap(const model_t* const map) { XVK_ParseMapEntities(); // Load PBR materials (depends on wadlist from parsed map entities) - XVK_ReloadMaterials(); + R_VkMaterialsReload(); // Parse patch data // Depends on loaded materials. Must preceed loading brush models. diff --git a/ref/vk/vk_sprite.c b/ref/vk/vk_sprite.c index 2c598e6d..7df2de2e 100644 --- a/ref/vk/vk_sprite.c +++ b/ref/vk/vk_sprite.c @@ -103,8 +103,8 @@ static qboolean createQuadModel(void) { .element_count = 6, .index_offset = g_sprite.quad.geom.indices.unit_offset, - .material = kXVkMaterialRegular, - .texture = tglob.defaultTexture, + .material_type_deprecated = kXVkMaterialRegular, + .material = R_VkMaterialGetForTexture(tglob.defaultTexture), .emissive = {1,1,1}, }; @@ -804,7 +804,7 @@ static void R_DrawSpriteQuad( const char *debug_name, const mspriteframe_t *fram .color = (const vec4_t*)color, .transform = &transform, .prev_transform = &transform, - .textures_override = texture, + .material_override = R_VkMaterialGet(R_VkMaterialGetForTexture(texture)), }); } diff --git a/ref/vk/vk_studio.c b/ref/vk/vk_studio.c index 5de6c270..7326bcd8 100644 --- a/ref/vk/vk_studio.c +++ b/ref/vk/vk_studio.c @@ -1770,8 +1770,8 @@ static void buildSubmodelMeshGeometry( build_submodel_mesh_t args ) { ASSERT(vertex_offset == num_vertices); *args.out_geometry = (vk_render_geometry_t){ - .texture = args.texture, - .material = FBitSet( args.face_flags, STUDIO_NF_CHROME ) ? kXVkMaterialChrome : kXVkMaterialRegular, + .material = R_VkMaterialGetForTexture(args.texture), + .material_type_deprecated = FBitSet( args.face_flags, STUDIO_NF_CHROME ) ? kXVkMaterialChrome : kXVkMaterialRegular, .vertex_offset = args.vertices_offset, .max_vertex = num_vertices, @@ -2304,7 +2304,7 @@ static void R_StudioDrawPoints( void ) { .color = &color, .transform = &g_studio_current.entmodel->transform, .prev_transform = &g_studio_current.entmodel->prev_transform, - .textures_override = -1, + .material_override = NULL, }); ++g_studio_stats.submodels_total; diff --git a/ref/vk/vk_triapi.c b/ref/vk/vk_triapi.c index eab504e9..656914ac 100644 --- a/ref/vk/vk_triapi.c +++ b/ref/vk/vk_triapi.c @@ -170,7 +170,7 @@ void TriEndEx( const vec4_t color, const char* name ) { .vertices_count = g_triapi.num_vertices, .indices_count = num_indices, .render_type = g_triapi.render_type, - .texture = g_triapi.texture_index, + .material = R_VkMaterialGetForTexture(g_triapi.texture_index), .emissive = (const vec4_t*)color, .color = (const vec4_t*)color, });