rt: group Material and ModelMetadata in Kusok
They have mismatching frequencies. ModelMetadata should be per-Model, there should be only a few dozen of these. There maybe hundreds (or even thousands) of materials, but one material can be still referenced by many kusochki. This only moves fields into new structs, which still belong to Kusok. The real extraction will happen later, see #52.
This commit is contained in:
parent
aab689a37b
commit
5b370509fe
|
@ -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 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 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 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;
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
}
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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", */
|
||||
|
|
Loading…
Reference in New Issue