Skip to content

Commit

Permalink
rt: group Material and ModelMetadata in Kusok
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
w23 committed Apr 24, 2023
1 parent aab689a commit 14f0621
Show file tree
Hide file tree
Showing 13 changed files with 92 additions and 76 deletions.
28 changes: 15 additions & 13 deletions ref/vk/shaders/additive.rahit
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion ref/vk/shaders/alphamask.rahit
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion ref/vk/shaders/bounce.comp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions ref/vk/shaders/light_common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion ref/vk/shaders/ray_common_alphatest.rahit
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
44 changes: 31 additions & 13 deletions ref/vk/shaders/ray_interop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion ref/vk/shaders/ray_primary.comp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 5 additions & 6 deletions ref/vk/shaders/ray_primary.rchit
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 8 additions & 7 deletions ref/vk/shaders/ray_primary_hit.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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
5 changes: 3 additions & 2 deletions ref/vk/shaders/ray_shadow.rchit
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;
}
6 changes: 3 additions & 3 deletions ref/vk/shaders/rt_geometry.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {
Expand Down
6 changes: 3 additions & 3 deletions ref/vk/shaders/trace_additive.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
41 changes: 18 additions & 23 deletions ref/vk/vk_ray_model.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -165,48 +165,43 @@ 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;
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];
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 ) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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", */
Expand Down

0 comments on commit 14f0621

Please sign in to comment.