diff --git a/ref/vk/shaders/additive.rahit b/ref/vk/shaders/additive.rahit index 973074c145..f66331256e 100644 --- a/ref/vk/shaders/additive.rahit +++ b/ref/vk/shaders/additive.rahit @@ -16,19 +16,21 @@ layout(location = PAYLOAD_LOCATION_ADDITIVE) rayPayloadInEXT RayPayloadAdditive hitAttributeEXT vec2 bary; void main() { - const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; - const int kusok_index = instance_kusochki_offset + gl_GeometryIndexEXT; - const uint first_index_offset = getKusok(kusok_index).index_offset + gl_PrimitiveID * 3; - - const uint vi1 = uint(getIndex(first_index_offset+0)) + getKusok(kusok_index).vertex_offset; - const uint vi2 = uint(getIndex(first_index_offset+1)) + getKusok(kusok_index).vertex_offset; - const uint vi3 = uint(getIndex(first_index_offset+2)) + getKusok(kusok_index).vertex_offset; - - const vec2 texture_uv = GET_VERTEX(vi1).gl_tc * (1. - bary.x - bary.y) + GET_VERTEX(vi2).gl_tc * bary.x + GET_VERTEX(vi3).gl_tc * bary.y + push_constants.time * getKusok(kusok_index).uv_speed; - // TODO mips - const uint tex_index = getKusok(kusok_index).tex_base_color; - const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], texture_uv); - const vec3 color = texture_color.rgb * getKusok(kusok_index).color.rgb * texture_color.a * getKusok(kusok_index).color.a; + const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; + const int kusok_index = instance_kusochki_offset + gl_GeometryIndexEXT; + const uint first_index_offset = getKusok(kusok_index).index_offset + gl_PrimitiveID * 3; + + const uint vi1 = uint(getIndex(first_index_offset+0)) + getKusok(kusok_index).vertex_offset; + const uint vi2 = uint(getIndex(first_index_offset+1)) + getKusok(kusok_index).vertex_offset; + const uint vi3 = uint(getIndex(first_index_offset+2)) + getKusok(kusok_index).vertex_offset; + + const vec2 texture_uv = GET_VERTEX(vi1).gl_tc * (1. - bary.x - bary.y) + GET_VERTEX(vi2).gl_tc * bary.x + GET_VERTEX(vi3).gl_tc * bary.y; + + const Kusok kusok = getKusok(kusok_index); + // TODO mips + const uint tex_index = kusok.material.tex_base_color; + const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], texture_uv); + const vec3 color = texture_color.rgb * kusok.model.color.rgb * texture_color.a * kusok.model.color.a; const float overshoot = gl_HitTEXT - payload_additive.ray_distance; diff --git a/ref/vk/shaders/alphamask.rahit b/ref/vk/shaders/alphamask.rahit index 59ae5a46d8..9d7df1df9d 100644 --- a/ref/vk/shaders/alphamask.rahit +++ b/ref/vk/shaders/alphamask.rahit @@ -19,7 +19,7 @@ void main() { const uint vi3 = uint(getIndex(first_index_offset+2)) + getKusok(kusok_index).vertex_offset; const vec2 texture_uv = GET_VERTEX(vi1).gl_tc * (1. - bary.x - bary.y) + GET_VERTEX(vi2).gl_tc * bary.x + GET_VERTEX(vi3).gl_tc * bary.y; - const uint tex_index = getKusok(kusok_index).tex_base_color; + const uint tex_index = getKusok(kusok_index).material.tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], texture_uv); if (texture_color.a < 0.1) { diff --git a/ref/vk/shaders/bounce.comp b/ref/vk/shaders/bounce.comp index f4e0573ac0..bc19245c66 100644 --- a/ref/vk/shaders/bounce.comp +++ b/ref/vk/shaders/bounce.comp @@ -71,7 +71,7 @@ bool getHit(vec3 origin, vec3 direction, inout RayPayloadPrimary payload) { // Separate pass could be more efficient as it'd be doing the same thing for every invocation. // 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha const MiniGeometry geom = readCandidateMiniGeometry(rq); - const uint tex_base_color = getKusok(geom.kusok_index).tex_base_color; + const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv); const float alpha_mask_threshold = .1f; diff --git a/ref/vk/shaders/light_common.glsl b/ref/vk/shaders/light_common.glsl index 4b740193fd..81d6cf18b5 100644 --- a/ref/vk/shaders/light_common.glsl +++ b/ref/vk/shaders/light_common.glsl @@ -63,7 +63,7 @@ bool shadowTestAlphaMask(vec3 pos, vec3 dir, float dist) { }; const vec2 bary = rayQueryGetIntersectionBarycentricsEXT(rq, false); const vec2 uv = baryMix(uvs[0], uvs[1], uvs[2], bary); - const vec4 texture_color = texture(textures[nonuniformEXT(kusok.tex_base_color)], uv); + const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], uv); const float alpha_mask_threshold = .1f; if (texture_color.a >= alpha_mask_threshold) { @@ -141,7 +141,7 @@ bool shadowedSky(vec3 pos, vec3 dir) { 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.flags & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) + if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) return true; } diff --git a/ref/vk/shaders/ray_common_alphatest.rahit b/ref/vk/shaders/ray_common_alphatest.rahit index c6f92d18cd..45632bbac4 100644 --- a/ref/vk/shaders/ray_common_alphatest.rahit +++ b/ref/vk/shaders/ray_common_alphatest.rahit @@ -21,7 +21,7 @@ const float alpha_mask_threshold = .1f; void main() { const Geometry geom = readHitGeometry(bary, ubo.ubo.ray_cone_width); - const uint tex_index = getKusok(geom.kusok_index).tex_base_color; + const uint tex_index = getKusok(geom.kusok_index).material.tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], geom.uv); if (texture_color.a < alpha_mask_threshold) { diff --git a/ref/vk/shaders/ray_interop.h b/ref/vk/shaders/ray_interop.h index c6ad0bb516..51ad42824e 100644 --- a/ref/vk/shaders/ray_interop.h +++ b/ref/vk/shaders/ray_interop.h @@ -66,33 +66,51 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT) #define KUSOK_MATERIAL_FLAG_SKYBOX (1<<0) #define KUSOK_MATERIAL_FLAG_FIXME_GLOW (1<<1) -struct Kusok { - uint index_offset; - uint vertex_offset; - uint triangles; +struct Material { + uint flags; - // Material uint tex_base_color; - // TODO the color is per-model, not per-kusok - vec4 color; - - vec3 emissive; + // TODO can be combined into a single texture uint tex_roughness; - - vec2 uv_speed; // for conveyors; TODO this can definitely be done in software more efficiently (there only a handful of these per map) uint tex_metalness; uint tex_normalmap; + // TODO: + // uint tex_emissive; + // uint tex_detail; + float roughness; float metalness; float normal_scale; - uint flags; +}; - // TODO per-model +struct ModelMetadata { + vec4 color; mat4 prev_transform; }; +struct Kusok { + // Geometry data + uint index_offset; + uint vertex_offset; + uint triangles; + + // material below consists of scalar fields only, so it's not aligned to vec4. + // Alignt it here to vec4 explicitly, so that later vector fields are properly aligned (for simplicity). + uint _padding0; + + // TODO reference into material table + STRUCT Material material; + + // Per-kusok because individual surfaces can be patched + vec3 emissive; + PAD(1) + + // TODO move into a separate model array, and reference it by gl_GeometryIndexEXT/rayQueryGetIntersectionGeometryIndexEXT + STRUCT ModelMetadata model; +}; + struct PointLight { vec4 origin_r; vec4 color_stopdot; diff --git a/ref/vk/shaders/ray_primary.comp b/ref/vk/shaders/ray_primary.comp index f2e0c230e8..2cf07cfd23 100644 --- a/ref/vk/shaders/ray_primary.comp +++ b/ref/vk/shaders/ray_primary.comp @@ -86,7 +86,7 @@ void main() { // Separate pass could be more efficient as it'd be doing the same thing for every invocation. // 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha const MiniGeometry geom = readCandidateMiniGeometry(rq); - const uint tex_base_color = getKusok(geom.kusok_index).tex_base_color; + const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color; const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv); const float alpha_mask_threshold = .1f; diff --git a/ref/vk/shaders/ray_primary.rchit b/ref/vk/shaders/ray_primary.rchit index 69402c6a08..b8123dd1f4 100644 --- a/ref/vk/shaders/ray_primary.rchit +++ b/ref/vk/shaders/ray_primary.rchit @@ -28,17 +28,16 @@ void main() { payload.prev_pos_t = vec4(geom.prev_pos, 0.); const Kusok kusok = getKusok(geom.kusok_index); - const uint tex_base_color = kusok.tex_base_color; - if ((tex_base_color & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) { + if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) { payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb); return; } else { - payload.base_color_a = sampleTexture(tex_base_color, geom.uv, geom.uv_lods) * kusok.color; - payload.material_rmxx.r = (kusok.tex_roughness > 0) ? sampleTexture(kusok.tex_roughness, geom.uv, geom.uv_lods).r : kusok.roughness; - payload.material_rmxx.g = (kusok.tex_metalness > 0) ? sampleTexture(kusok.tex_metalness, geom.uv, geom.uv_lods).r : kusok.metalness; + payload.base_color_a = sampleTexture(kusok.material.tex_base_color, geom.uv, geom.uv_lods) * kusok.model.color; + payload.material_rmxx.r = sampleTexture(kusok.material.tex_roughness, geom.uv, geom.uv_lods).r * kusok.material.roughness; + payload.material_rmxx.g = sampleTexture(kusok.material.tex_metalness, geom.uv, geom.uv_lods).r * kusok.material.metalness; - const uint tex_normal = kusok.tex_normalmap; + const uint tex_normal = kusok.material.tex_normalmap; vec3 T = geom.tangent; if (tex_normal > 0 && dot(T,T) > .5) { T = normalize(T - dot(T, geom.normal_shading) * geom.normal_shading); diff --git a/ref/vk/shaders/ray_primary_hit.glsl b/ref/vk/shaders/ray_primary_hit.glsl index aa9d118d6b..feb579fa41 100644 --- a/ref/vk/shaders/ray_primary_hit.glsl +++ b/ref/vk/shaders/ray_primary_hit.glsl @@ -28,24 +28,25 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { payload.prev_pos_t = vec4(geom.prev_pos, 0.); const Kusok kusok = getKusok(geom.kusok_index); + const Material material = kusok.material; - if ((kusok.flags & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) { + if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) != 0) { payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb); return; } else { - payload.base_color_a = sampleTexture(kusok.tex_base_color, geom.uv, geom.uv_lods); - payload.material_rmxx.r = sampleTexture(kusok.tex_roughness, geom.uv, geom.uv_lods).r * kusok.roughness; - payload.material_rmxx.g = sampleTexture(kusok.tex_metalness, geom.uv, geom.uv_lods).r * kusok.metalness; + payload.base_color_a = sampleTexture(material.tex_base_color, geom.uv, geom.uv_lods); + payload.material_rmxx.r = sampleTexture(material.tex_roughness, geom.uv, geom.uv_lods).r * material.roughness; + payload.material_rmxx.g = sampleTexture(material.tex_metalness, geom.uv, geom.uv_lods).r * material.metalness; #ifndef RAY_BOUNCE - const uint tex_normal = kusok.tex_normalmap; + const uint tex_normal = material.tex_normalmap; vec3 T = geom.tangent; if (tex_normal > 0 && dot(T,T) > .5) { T = normalize(T - dot(T, geom.normal_shading) * geom.normal_shading); const vec3 B = normalize(cross(geom.normal_shading, T)); const mat3 TBN = mat3(T, B, geom.normal_shading); vec3 tnorm = sampleTexture(tex_normal, geom.uv, geom.uv_lods).xyz * 2. - 1.; // TODO is this sampling correct for normal data? - tnorm.xy *= kusok.normal_scale; + tnorm.xy *= material.normal_scale; tnorm.z = sqrt(max(0., 1. - dot(tnorm.xy, tnorm.xy))); geom.normal_shading = normalize(TBN * tnorm); } @@ -68,7 +69,7 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { payload.emissive.rgb = payload.base_color_a.rgb; #endif - payload.base_color_a *= kusok.color; + payload.base_color_a *= kusok.model.color; } #endif // ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED diff --git a/ref/vk/shaders/ray_shadow.rchit b/ref/vk/shaders/ray_shadow.rchit index 8823e99836..bc4da1adc0 100644 --- a/ref/vk/shaders/ray_shadow.rchit +++ b/ref/vk/shaders/ray_shadow.rchit @@ -9,7 +9,8 @@ layout(location = PAYLOAD_LOCATION_SHADOW) rayPayloadInEXT RayPayloadShadow payl void main() { const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; const int kusok_index = instance_kusochki_offset + gl_GeometryIndexEXT; - const uint tex_base_color = getKusok(kusok_index).tex_base_color; + const Kusok kusok = getKusok(kusok_index); + const uint tex_base_color = kusok.material.tex_base_color; - payload_shadow.hit_type = ((tex_base_color & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) ? SHADOW_HIT : SHADOW_SKY ; + payload_shadow.hit_type = ((kusok.material.flags & KUSOK_MATERIAL_FLAG_SKYBOX) == 0) ? SHADOW_HIT : SHADOW_SKY ; } diff --git a/ref/vk/shaders/rt_geometry.glsl b/ref/vk/shaders/rt_geometry.glsl index c2274f8139..643b6fcde7 100644 --- a/ref/vk/shaders/rt_geometry.glsl +++ b/ref/vk/shaders/rt_geometry.glsl @@ -89,9 +89,9 @@ Geometry readHitGeometry(vec2 bary, float ray_cone_width) { }; const vec3 prev_pos[3] = { - (kusok.prev_transform * vec4(GET_VERTEX(vi1).prev_pos, 1.f)).xyz, - (kusok.prev_transform * vec4(GET_VERTEX(vi2).prev_pos, 1.f)).xyz, - (kusok.prev_transform * vec4(GET_VERTEX(vi3).prev_pos, 1.f)).xyz, + (kusok.model.prev_transform * vec4(GET_VERTEX(vi1).prev_pos, 1.f)).xyz, + (kusok.model.prev_transform * vec4(GET_VERTEX(vi2).prev_pos, 1.f)).xyz, + (kusok.model.prev_transform * vec4(GET_VERTEX(vi3).prev_pos, 1.f)).xyz, }; const vec2 uvs[3] = { diff --git a/ref/vk/shaders/trace_additive.glsl b/ref/vk/shaders/trace_additive.glsl index 13b2a922f3..831d03949d 100644 --- a/ref/vk/shaders/trace_additive.glsl +++ b/ref/vk/shaders/trace_additive.glsl @@ -15,15 +15,15 @@ vec3 traceAdditive(vec3 pos, vec3 dir, float L) { const MiniGeometry geom = readCandidateMiniGeometry(rq); const Kusok kusok = getKusok(geom.kusok_index); - const vec4 texture_color = texture(textures[nonuniformEXT(kusok.tex_base_color)], geom.uv); - const vec3 color = texture_color.rgb * kusok.emissive * texture_color.a * kusok.color.a * SRGBtoLINEAR(geom.color.rgb * geom.color.a); + const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], geom.uv); + const vec3 color = texture_color.rgb * kusok.emissive * texture_color.a * kusok.model.color.a * SRGBtoLINEAR(geom.color.rgb * geom.color.a); const float hit_t = rayQueryGetIntersectionTEXT(rq, false); const float overshoot = hit_t - L; if (overshoot < 0.) ret += color; - else if ((kusok.flags & KUSOK_MATERIAL_FLAG_FIXME_GLOW) != 0) + else if ((kusok.material.flags & KUSOK_MATERIAL_FLAG_FIXME_GLOW) != 0) ret += color * smoothstep(additive_soft_overshoot, 0., overshoot); } return ret; diff --git a/ref/vk/vk_ray_model.c b/ref/vk/vk_ray_model.c index fd3679b66b..376ff21b2f 100644 --- a/ref/vk/vk_ray_model.c +++ b/ref/vk/vk_ray_model.c @@ -138,7 +138,7 @@ void XVK_RayModel_Validate( void ) { for (int j = 0; j < num_geoms; j++) { const vk_kusok_data_t *kusok = kusochki + j; - const vk_texture_t *tex = findTexture(kusok->tex_base_color); + const vk_texture_t *tex = findTexture(kusok->material.tex_base_color); ASSERT(tex); ASSERT(tex->vk.image.view != VK_NULL_HANDLE); @@ -165,30 +165,32 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr kusok->index_offset = geom->index_offset; kusok->triangles = geom->element_count / 3; - kusok->tex_base_color = mat->tex_base_color; - kusok->tex_roughness = mat->tex_roughness; - kusok->tex_metalness = mat->tex_metalness; - kusok->tex_normalmap = mat->tex_normalmap; + kusok->material = (struct Material){ + .flags = 0, - kusok->roughness = mat->roughness; - kusok->metalness = mat->metalness; - kusok->normal_scale = mat->normal_scale; + .tex_base_color = mat->tex_base_color, + .tex_roughness = mat->tex_roughness, + .tex_metalness = mat->tex_metalness, + .tex_normalmap = mat->tex_normalmap, - kusok->flags = 0; + .roughness = mat->roughness, + .metalness = mat->metalness, + .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->tex_roughness = tglob.blackTexture; + kusok->material.tex_roughness = tglob.blackTexture; } else if (!mat->set && geom->material == kXVkMaterialChrome) { - kusok->tex_roughness = tglob.grayTexture; + kusok->material.tex_roughness = tglob.grayTexture; } if (geom->material == kXVkMaterialSky) - kusok->flags |= KUSOK_MATERIAL_FLAG_SKYBOX; + kusok->material.flags |= KUSOK_MATERIAL_FLAG_SKYBOX; if (geom->material == kXVkMaterialEmissiveGlow) - kusok->flags |= KUSOK_MATERIAL_FLAG_FIXME_GLOW; + kusok->material.flags |= KUSOK_MATERIAL_FLAG_FIXME_GLOW; { vec4_t gcolor; @@ -196,17 +198,10 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr gcolor[1] = color[1] * mat->base_color[1]; gcolor[2] = color[2] * mat->base_color[2]; gcolor[3] = color[3] * mat->base_color[3]; - Vector4Copy(gcolor, kusok->color); + Vector4Copy(gcolor, kusok->model.color); } VectorCopy(geom->emissive, kusok->emissive); - -/* FIXME these should be done in a different way - if (geom->material == kXVkMaterialConveyor) { - computeConveyorSpeed( entcolor, geom->texture, kusok->uv_speed ); - } else */ { - kusok->uv_speed[0] = kusok->uv_speed[1] = 0.f; - } } vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) { @@ -277,7 +272,7 @@ vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) { }; applyMaterialToKusok(kusochki + i, mg, args.model->color, false); - Matrix4x4_LoadIdentity(kusochki[i].prev_transform); + Matrix4x4_LoadIdentity(kusochki[i].model.prev_transform); } R_VkStagingUnlock(kusok_staging.handle); @@ -475,7 +470,7 @@ void VK_RayFrameAddModel( vk_ray_model_t *model, const vk_render_model_t *render applyMaterialToKusok(kusochki + i, geom, render_model->color, HACK_reflective); - Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + i)->prev_transform); + 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", */