rt: extract per-model data from kusochki
This commit is contained in:
parent
0d8a7f76f5
commit
1cfb183cbd
|
@ -30,7 +30,8 @@ void main() {
|
||||||
// TODO mips
|
// TODO mips
|
||||||
const uint tex_index = kusok.material.tex_base_color;
|
const uint tex_index = kusok.material.tex_base_color;
|
||||||
const vec4 texture_color = texture(textures[nonuniformEXT(tex_index)], texture_uv);
|
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 vec4 mm_color = getModelHeader(gl_InstanceID).color * kusok.material.base_color;
|
||||||
|
const vec3 color = texture_color.rgb * mm_color.rgb * texture_color.a * mm_color.a;
|
||||||
|
|
||||||
const float overshoot = gl_HitTEXT - payload_additive.ray_distance;
|
const float overshoot = gl_HitTEXT - payload_additive.ray_distance;
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ bool getHit(vec3 origin, vec3 direction, inout RayPayloadPrimary payload) {
|
||||||
// 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha
|
// 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 MiniGeometry geom = readCandidateMiniGeometry(rq);
|
||||||
const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color;
|
const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color;
|
||||||
|
// Should never happen: skybox is opaque if (tex_base_color == TEX_BASE_SKYBOX)
|
||||||
const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv);
|
const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv);
|
||||||
|
|
||||||
const float alpha_mask_threshold = .1f;
|
const float alpha_mask_threshold = .1f;
|
||||||
|
|
|
@ -140,7 +140,7 @@ bool shadowedSky(vec3 pos, vec3 dir) {
|
||||||
const uint kusok_index = instance_kusochki_offset + geometry_index;
|
const uint kusok_index = instance_kusochki_offset + geometry_index;
|
||||||
const Kusok kusok = getKusok(kusok_index);
|
const Kusok kusok = getKusok(kusok_index);
|
||||||
|
|
||||||
if (kusok.material.mode != MATERIAL_MODE_SKYBOX)
|
if (kusok.material.tex_base_color != TEX_BASE_SKYBOX)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,15 +69,10 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT)
|
||||||
#define MATERIAL_MODE_BLEND_ADD 3
|
#define MATERIAL_MODE_BLEND_ADD 3
|
||||||
#define MATERIAL_MODE_BLEND_MIX 4
|
#define MATERIAL_MODE_BLEND_MIX 4
|
||||||
#define MATERIAL_MODE_BLEND_GLOW 5
|
#define MATERIAL_MODE_BLEND_GLOW 5
|
||||||
#define MATERIAL_MODE_SKYBOX 6
|
|
||||||
|
#define TEX_BASE_SKYBOX 0xffffffffu
|
||||||
|
|
||||||
struct Material {
|
struct Material {
|
||||||
// TODO this should be moved to ModelMetadata, as granularity of this is per-model
|
|
||||||
// EXCEPT for skybox. Sky surfaces are all over the place in worldbrush.
|
|
||||||
// Maybe tex_base_color should have a special value for skybox.
|
|
||||||
// Moving this to model would allow us to make kusochki mostly static (except for animated textures)
|
|
||||||
uint mode;
|
|
||||||
|
|
||||||
uint tex_base_color;
|
uint tex_base_color;
|
||||||
|
|
||||||
// TODO can be combined into a single texture
|
// TODO can be combined into a single texture
|
||||||
|
@ -92,11 +87,16 @@ struct Material {
|
||||||
float roughness;
|
float roughness;
|
||||||
float metalness;
|
float metalness;
|
||||||
float normal_scale;
|
float normal_scale;
|
||||||
|
PAD(1)
|
||||||
|
|
||||||
|
vec4 base_color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModelMetadata {
|
struct ModelHeader {
|
||||||
vec4 color;
|
|
||||||
mat4 prev_transform;
|
mat4 prev_transform;
|
||||||
|
vec4 color;
|
||||||
|
uint mode;
|
||||||
|
PAD(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Kusok {
|
struct Kusok {
|
||||||
|
@ -109,15 +109,12 @@ struct Kusok {
|
||||||
// Alignt it here to vec4 explicitly, so that later vector fields are properly aligned (for simplicity).
|
// Alignt it here to vec4 explicitly, so that later vector fields are properly aligned (for simplicity).
|
||||||
uint _padding0;
|
uint _padding0;
|
||||||
|
|
||||||
// TODO reference into material table
|
|
||||||
STRUCT Material material;
|
|
||||||
|
|
||||||
// Per-kusok because individual surfaces can be patched
|
// Per-kusok because individual surfaces can be patched
|
||||||
vec3 emissive;
|
vec3 emissive;
|
||||||
PAD(1)
|
PAD(1)
|
||||||
|
|
||||||
// TODO move into a separate model array, and reference it by gl_GeometryIndexEXT/rayQueryGetIntersectionGeometryIndexEXT
|
// TODO reference into material table
|
||||||
STRUCT ModelMetadata model;
|
STRUCT Material material;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PointLight {
|
struct PointLight {
|
||||||
|
|
|
@ -16,12 +16,14 @@ struct Vertex {
|
||||||
uint color;
|
uint color;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std430, binding = 3, set = 0) readonly buffer Kusochki { Kusok a[]; } kusochki;
|
layout(std430, binding = 30, set = 0) readonly buffer ModelHeaders { ModelHeader a[]; } model_headers;
|
||||||
layout(std430, binding = 4, set = 0) readonly buffer Indices { uint16_t a[]; } indices;
|
layout(std430, binding = 31, set = 0) readonly buffer Kusochki { Kusok a[]; } kusochki;
|
||||||
layout(std430, binding = 5, set = 0) readonly buffer Vertices { Vertex a[]; } vertices;
|
layout(std430, binding = 32, set = 0) readonly buffer Indices { uint16_t a[]; } indices;
|
||||||
|
layout(std430, binding = 33, set = 0) readonly buffer Vertices { Vertex a[]; } vertices;
|
||||||
|
|
||||||
Kusok getKusok(uint index) { return kusochki.a[index]; }
|
Kusok getKusok(uint index) { return kusochki.a[index]; }
|
||||||
uint16_t getIndex(uint index) { return indices.a[index]; }
|
uint16_t getIndex(uint index) { return indices.a[index]; }
|
||||||
|
ModelHeader getModelHeader(uint index) { return model_headers.a[index]; }
|
||||||
#define GET_VERTEX(index) (vertices.a[index])
|
#define GET_VERTEX(index) (vertices.a[index])
|
||||||
|
|
||||||
#endif //ifndef RAY_KUSOCHKI_GLSL_INCLUDED
|
#endif //ifndef RAY_KUSOCHKI_GLSL_INCLUDED
|
||||||
|
|
|
@ -87,6 +87,7 @@ void main() {
|
||||||
// 2. Same as the above, but also with a completely independent TLAS. Why: no need to mask-check geometry for opaque-vs-alpha
|
// 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 MiniGeometry geom = readCandidateMiniGeometry(rq);
|
||||||
const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color;
|
const uint tex_base_color = getKusok(geom.kusok_index).material.tex_base_color;
|
||||||
|
// Should never happen: skybox is opaque if (tex_base_color == TEX_BASE_SKYBOX)
|
||||||
const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv);
|
const vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv);
|
||||||
|
|
||||||
const float alpha_mask_threshold = .1f;
|
const float alpha_mask_threshold = .1f;
|
||||||
|
|
|
@ -29,11 +29,12 @@ void main() {
|
||||||
|
|
||||||
const Kusok kusok = getKusok(geom.kusok_index);
|
const Kusok kusok = getKusok(geom.kusok_index);
|
||||||
|
|
||||||
if (kusok.material.mode == MATERIAL_MODE_SKYBOX) {
|
if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) {
|
||||||
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb);
|
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
payload.base_color_a = sampleTexture(kusok.material.tex_base_color, geom.uv, geom.uv_lods) * kusok.model.color;
|
const vec4 color = getModelHeader(gl_InstanceID).color * kusok.material.base_color;
|
||||||
|
payload.base_color_a = sampleTexture(kusok.material.tex_base_color, geom.uv, geom.uv_lods) * color;
|
||||||
payload.material_rmxx.r = sampleTexture(kusok.material.tex_roughness, geom.uv, geom.uv_lods).r * kusok.material.roughness;
|
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;
|
payload.material_rmxx.g = sampleTexture(kusok.material.tex_metalness, geom.uv, geom.uv_lods).r * kusok.material.metalness;
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) {
|
||||||
const Kusok kusok = getKusok(geom.kusok_index);
|
const Kusok kusok = getKusok(geom.kusok_index);
|
||||||
const Material material = kusok.material;
|
const Material material = kusok.material;
|
||||||
|
|
||||||
if (kusok.material.mode == MATERIAL_MODE_SKYBOX) {
|
if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) {
|
||||||
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb);
|
payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -69,8 +69,12 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) {
|
||||||
payload.emissive.rgb *= payload.base_color_a.rgb;
|
payload.emissive.rgb *= payload.base_color_a.rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
payload.base_color_a *= kusok.model.color;
|
const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, true);
|
||||||
payload.emissive.rgb *= kusok.model.color.rgb;
|
const ModelHeader model = getModelHeader(model_index);
|
||||||
|
const vec4 color = model.color * kusok.material.base_color;
|
||||||
|
|
||||||
|
payload.base_color_a *= color;
|
||||||
|
payload.emissive.rgb *= color.rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED
|
#endif // ifndef RAY_PRIMARY_HIT_GLSL_INCLUDED
|
||||||
|
|
|
@ -12,5 +12,5 @@ void main() {
|
||||||
const Kusok kusok = getKusok(kusok_index);
|
const Kusok kusok = getKusok(kusok_index);
|
||||||
const uint tex_base_color = kusok.material.tex_base_color;
|
const uint tex_base_color = kusok.material.tex_base_color;
|
||||||
|
|
||||||
payload_shadow.hit_type = (kusok.material.mode != MATERIAL_MODE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ;
|
payload_shadow.hit_type = (kusok.material.tex_base_color != TEX_BASE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct Geometry {
|
||||||
|
|
||||||
#ifdef RAY_QUERY
|
#ifdef RAY_QUERY
|
||||||
Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) {
|
Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) {
|
||||||
|
const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, true);
|
||||||
const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true);
|
const int instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true);
|
||||||
const int geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, true);
|
const int geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, true);
|
||||||
const int primitive_index = rayQueryGetIntersectionPrimitiveIndexEXT(rq, true);
|
const int primitive_index = rayQueryGetIntersectionPrimitiveIndexEXT(rq, true);
|
||||||
|
@ -64,6 +65,7 @@ Geometry readHitGeometry(rayQueryEXT rq, float ray_cone_width, vec2 bary) {
|
||||||
const float hit_t = rayQueryGetIntersectionTEXT(rq, true);
|
const float hit_t = rayQueryGetIntersectionTEXT(rq, true);
|
||||||
#else
|
#else
|
||||||
Geometry readHitGeometry(vec2 bary, float ray_cone_width) {
|
Geometry readHitGeometry(vec2 bary, float ray_cone_width) {
|
||||||
|
const int model_index = gl_InstanceID;
|
||||||
const int instance_kusochki_offset = gl_InstanceCustomIndexEXT;
|
const int instance_kusochki_offset = gl_InstanceCustomIndexEXT;
|
||||||
const int geometry_index = gl_GeometryIndexEXT;
|
const int geometry_index = gl_GeometryIndexEXT;
|
||||||
const int primitive_index = gl_PrimitiveID;
|
const int primitive_index = gl_PrimitiveID;
|
||||||
|
@ -88,10 +90,11 @@ Geometry readHitGeometry(vec2 bary, float ray_cone_width) {
|
||||||
objectToWorld * vec4(GET_VERTEX(vi3).pos, 1.f),
|
objectToWorld * vec4(GET_VERTEX(vi3).pos, 1.f),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ModelHeader model = getModelHeader(model_index);
|
||||||
const vec3 prev_pos[3] = {
|
const vec3 prev_pos[3] = {
|
||||||
(kusok.model.prev_transform * vec4(GET_VERTEX(vi1).prev_pos, 1.f)).xyz,
|
(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,
|
(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,
|
(model.prev_transform * vec4(GET_VERTEX(vi3).prev_pos, 1.f)).xyz,
|
||||||
};
|
};
|
||||||
|
|
||||||
const vec2 uvs[3] = {
|
const vec2 uvs[3] = {
|
||||||
|
|
|
@ -27,44 +27,43 @@ void traceSimpleBlending(vec3 pos, vec3 dir, float L, inout vec3 emissive, inout
|
||||||
rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_BLEND, pos, 0., dir, L + glow_soft_overshoot);
|
rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_BLEND, pos, 0., dir, L + glow_soft_overshoot);
|
||||||
while (rayQueryProceedEXT(rq)) {
|
while (rayQueryProceedEXT(rq)) {
|
||||||
const MiniGeometry geom = readCandidateMiniGeometry(rq);
|
const MiniGeometry geom = readCandidateMiniGeometry(rq);
|
||||||
|
const int model_index = rayQueryGetIntersectionInstanceIdEXT(rq, false);
|
||||||
|
const ModelHeader model = getModelHeader(model_index);
|
||||||
const Kusok kusok = getKusok(geom.kusok_index);
|
const Kusok kusok = getKusok(geom.kusok_index);
|
||||||
const float hit_t = rayQueryGetIntersectionTEXT(rq, false);
|
const float hit_t = rayQueryGetIntersectionTEXT(rq, false);
|
||||||
const float overshoot = hit_t - L;
|
const float overshoot = hit_t - L;
|
||||||
if (overshoot > 0. && kusok.material.mode != MATERIAL_MODE_BLEND_GLOW)
|
if (overshoot > 0. && model.mode != MATERIAL_MODE_BLEND_GLOW)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//#define DEBUG_BLEND_MODES
|
//#define DEBUG_BLEND_MODES
|
||||||
#ifdef DEBUG_BLEND_MODES
|
#ifdef DEBUG_BLEND_MODES
|
||||||
if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW) {
|
if (model.mode == MATERIAL_MODE_BLEND_GLOW) {
|
||||||
emissive += vec3(1., 0., 0.);
|
emissive += vec3(1., 0., 0.);
|
||||||
//ret += color * smoothstep(glow_soft_overshoot, 0., overshoot);
|
//ret += color * smoothstep(glow_soft_overshoot, 0., overshoot);
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_BLEND_ADD) {
|
} else if (model.mode == MATERIAL_MODE_BLEND_ADD) {
|
||||||
emissive += vec3(0., 1., 0.);
|
emissive += vec3(0., 1., 0.);
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_BLEND_MIX) {
|
} else if (model.mode == MATERIAL_MODE_BLEND_MIX) {
|
||||||
emissive += vec3(0., 0., 1.);
|
emissive += vec3(0., 0., 1.);
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_TRANSLUCENT) {
|
} else if (model.mode == MATERIAL_MODE_TRANSLUCENT) {
|
||||||
emissive += vec3(0., 1., 1.);
|
emissive += vec3(0., 1., 1.);
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_OPAQUE) {
|
} else if (model.mode == MATERIAL_MODE_OPAQUE) {
|
||||||
emissive += vec3(1., 1., 1.);
|
emissive += vec3(1., 1., 1.);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], geom.uv);
|
const vec4 texture_color = texture(textures[nonuniformEXT(kusok.material.tex_base_color)], geom.uv);
|
||||||
|
const vec4 mm_color = model.color * kusok.material.base_color;
|
||||||
|
float alpha = mm_color.a * texture_color.a * geom.vertex_color.a;
|
||||||
|
vec3 color = mm_color.rgb * SRGBtoLINEAR(texture_color.rgb) * geom.vertex_color.rgb * alpha;
|
||||||
|
|
||||||
// "Linearizing" alpha, while looking weird conceptually in the code, is necessary to make it look close to the original.
|
if (model.mode == MATERIAL_MODE_BLEND_GLOW) {
|
||||||
// TODO figure out whether texture alpha needs to be linearized too. Don't have good examples to look at.
|
|
||||||
// TODO this also makes sprites look dull, so likely kusok.model.color linearization should only apply to brush models, not sprites. This is better done when passing brush model to ray tracer.
|
|
||||||
float alpha = SRGBtoLINEAR(texture_color.a * kusok.model.color.a) * geom.vertex_color.a;
|
|
||||||
vec3 color = kusok.model.color.rgb * SRGBtoLINEAR(texture_color.rgb) * geom.vertex_color.rgb * alpha;
|
|
||||||
|
|
||||||
if (kusok.material.mode == MATERIAL_MODE_BLEND_GLOW) {
|
|
||||||
// Glow is additive + small overshoot
|
// Glow is additive + small overshoot
|
||||||
const float overshoot_factor = smoothstep(glow_soft_overshoot, 0., overshoot);
|
const float overshoot_factor = smoothstep(glow_soft_overshoot, 0., overshoot);
|
||||||
color *= overshoot_factor;
|
color *= overshoot_factor;
|
||||||
alpha = 0.;
|
alpha = 0.;
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_BLEND_ADD) {
|
} else if (model.mode == MATERIAL_MODE_BLEND_ADD) {
|
||||||
// Additive doesn't attenuate what's behind
|
// Additive doesn't attenuate what's behind
|
||||||
alpha = 0.;
|
alpha = 0.;
|
||||||
} else if (kusok.material.mode == MATERIAL_MODE_BLEND_MIX) {
|
} else if (model.mode == MATERIAL_MODE_BLEND_MIX) {
|
||||||
// Handled in composite step below
|
// Handled in composite step below
|
||||||
} else {
|
} else {
|
||||||
// Signal unhandled blending type
|
// Signal unhandled blending type
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
#include "vk_ray_internal.h"
|
#include "vk_ray_internal.h"
|
||||||
#include "r_speeds.h"
|
#include "r_speeds.h"
|
||||||
#include "vk_combuf.h"
|
#include "vk_combuf.h"
|
||||||
|
#include "vk_staging.h"
|
||||||
|
#include "vk_math.h"
|
||||||
|
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
#define MAX_SCRATCH_BUFFER (32*1024*1024)
|
#define MAX_SCRATCH_BUFFER (32*1024*1024)
|
||||||
#define MAX_ACCELS_BUFFER (64*1024*1024)
|
#define MAX_ACCELS_BUFFER (64*1024*1024)
|
||||||
|
@ -178,6 +182,15 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
|
||||||
|
|
||||||
// Upload all blas instances references to GPU mem
|
// Upload all blas instances references to GPU mem
|
||||||
{
|
{
|
||||||
|
const vk_staging_region_t headers_lock = R_VkStagingLockForBuffer((vk_staging_buffer_args_t){
|
||||||
|
.buffer = g_ray_model_state.model_headers_buffer.buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.size = g_ray_model_state.frame.num_models * sizeof(struct ModelHeader),
|
||||||
|
.alignment = 16,
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT(headers_lock.ptr);
|
||||||
|
|
||||||
VkAccelerationStructureInstanceKHR* inst = ((VkAccelerationStructureInstanceKHR*)g_accel.tlas_geom_buffer.mapped) + instance_offset;
|
VkAccelerationStructureInstanceKHR* inst = ((VkAccelerationStructureInstanceKHR*)g_accel.tlas_geom_buffer.mapped) + instance_offset;
|
||||||
for (int i = 0; i < g_ray_model_state.frame.num_models; ++i) {
|
for (int i = 0; i < g_ray_model_state.frame.num_models; ++i) {
|
||||||
const vk_ray_draw_model_t* const model = g_ray_model_state.frame.models + i;
|
const vk_ray_draw_model_t* const model = g_ray_model_state.frame.models + i;
|
||||||
|
@ -190,7 +203,6 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
|
||||||
};
|
};
|
||||||
switch (model->material_mode) {
|
switch (model->material_mode) {
|
||||||
case MATERIAL_MODE_OPAQUE:
|
case MATERIAL_MODE_OPAQUE:
|
||||||
case MATERIAL_MODE_SKYBOX:
|
|
||||||
inst[i].mask = GEOMETRY_BIT_OPAQUE;
|
inst[i].mask = GEOMETRY_BIT_OPAQUE;
|
||||||
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
|
inst[i].instanceShaderBindingTableRecordOffset = SHADER_OFFSET_HIT_REGULAR,
|
||||||
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR;
|
inst[i].flags = VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR;
|
||||||
|
@ -217,7 +229,14 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memcpy(&inst[i].transform, model->transform_row, sizeof(VkTransformMatrixKHR));
|
memcpy(&inst[i].transform, model->transform_row, sizeof(VkTransformMatrixKHR));
|
||||||
|
|
||||||
|
struct ModelHeader *const header = ((struct ModelHeader*)headers_lock.ptr) + i;
|
||||||
|
header->mode = model->material_mode;
|
||||||
|
Vector4Copy(model->model->color, header->color);
|
||||||
|
Matrix4x4_ToArrayFloatGL(model->model->prev_transform, (float*)header->prev_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R_VkStagingUnlock(headers_lock.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_accel_.stats.blas_count = g_ray_model_state.frame.num_models;
|
g_accel_.stats.blas_count = g_ray_model_state.frame.num_models;
|
||||||
|
@ -225,14 +244,14 @@ void RT_VkAccelPrepareTlas(vk_combuf_t *combuf) {
|
||||||
// Barrier for building all BLASes
|
// Barrier for building all BLASes
|
||||||
// BLAS building is now in cmdbuf, need to synchronize with results
|
// BLAS building is now in cmdbuf, need to synchronize with results
|
||||||
{
|
{
|
||||||
VkBufferMemoryBarrier bmb[] = { {
|
VkBufferMemoryBarrier bmb[] = {{
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||||
.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, // | VK_ACCESS_TRANSFER_WRITE_BIT,
|
.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, // | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
|
.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
|
||||||
.buffer = g_accel.accels_buffer.buffer,
|
.buffer = g_accel.accels_buffer.buffer,
|
||||||
.offset = instance_offset * sizeof(VkAccelerationStructureInstanceKHR),
|
.offset = instance_offset * sizeof(VkAccelerationStructureInstanceKHR),
|
||||||
.size = g_ray_model_state.frame.num_models * sizeof(VkAccelerationStructureInstanceKHR),
|
.size = g_ray_model_state.frame.num_models * sizeof(VkAccelerationStructureInstanceKHR),
|
||||||
} };
|
}};
|
||||||
vkCmdPipelineBarrier(combuf->cmdbuf,
|
vkCmdPipelineBarrier(combuf->cmdbuf,
|
||||||
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||||
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
|
||||||
|
|
|
@ -60,6 +60,10 @@ typedef struct {
|
||||||
vk_buffer_t kusochki_buffer;
|
vk_buffer_t kusochki_buffer;
|
||||||
r_debuffer_t kusochki_alloc;
|
r_debuffer_t kusochki_alloc;
|
||||||
|
|
||||||
|
// Model header
|
||||||
|
// Array of struct ModelHeader: color, material_mode, prev_transform
|
||||||
|
vk_buffer_t model_headers_buffer;
|
||||||
|
|
||||||
// Per-frame data that is accumulated between RayFrameBegin and End calls
|
// Per-frame data that is accumulated between RayFrameBegin and End calls
|
||||||
struct {
|
struct {
|
||||||
int num_models;
|
int num_models;
|
||||||
|
|
|
@ -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 model_color, uint32_t mode) {
|
static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometry_t *geom) {
|
||||||
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture );
|
const xvk_material_t *const mat = XVK_GetMaterialForTextureIndex( geom->texture );
|
||||||
ASSERT(mat);
|
ASSERT(mat);
|
||||||
|
|
||||||
|
@ -165,9 +165,8 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
|
||||||
kusok->index_offset = geom->index_offset;
|
kusok->index_offset = geom->index_offset;
|
||||||
kusok->triangles = geom->element_count / 3;
|
kusok->triangles = geom->element_count / 3;
|
||||||
|
|
||||||
|
// Material data itself is mostly static. Except for animated textures, which just get a new material slot for each frame.
|
||||||
kusok->material = (struct Material){
|
kusok->material = (struct Material){
|
||||||
.mode = mode,
|
|
||||||
|
|
||||||
.tex_base_color = mat->tex_base_color,
|
.tex_base_color = mat->tex_base_color,
|
||||||
.tex_roughness = mat->tex_roughness,
|
.tex_roughness = mat->tex_roughness,
|
||||||
.tex_metalness = mat->tex_metalness,
|
.tex_metalness = mat->tex_metalness,
|
||||||
|
@ -178,24 +177,18 @@ static void applyMaterialToKusok(vk_kusok_data_t* kusok, const vk_render_geometr
|
||||||
.normal_scale = mat->normal_scale,
|
.normal_scale = mat->normal_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO emissive is potentially "dynamic", not tied to the material directly, as it is specified per-surface in rad files
|
||||||
|
VectorCopy(geom->emissive, kusok->emissive);
|
||||||
|
Vector4Copy(mat->base_color, kusok->material.base_color);
|
||||||
|
|
||||||
|
// 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 == kXVkMaterialChrome;
|
||||||
if (!mat->set && HACK_chrome)
|
if (!mat->set && HACK_chrome)
|
||||||
kusok->material.tex_roughness = tglob.grayTexture;
|
kusok->material.tex_roughness = tglob.grayTexture;
|
||||||
|
|
||||||
|
// Purely static. Once a sky forever a sky.
|
||||||
if (geom->material == kXVkMaterialSky)
|
if (geom->material == kXVkMaterialSky)
|
||||||
kusok->material.mode = MATERIAL_MODE_SKYBOX;
|
kusok->material.tex_base_color = TEX_BASE_SKYBOX;
|
||||||
|
|
||||||
// FIXME modulates model_color with material->base_color which has different frequency
|
|
||||||
{
|
|
||||||
vec4_t gcolor;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
VectorCopy(geom->emissive, kusok->emissive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
|
vk_ray_model_t* VK_RayModelCreate( vk_ray_model_init_t args ) {
|
||||||
|
@ -329,7 +322,7 @@ void VK_RayModelDestroy( struct vk_ray_model_s *model ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO move this to some common place with traditional renderer
|
// TODO move this to vk_brush
|
||||||
static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_t speed) {
|
static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_t speed) {
|
||||||
float sy, cy;
|
float sy, cy;
|
||||||
float flConveyorSpeed = 0.0f;
|
float flConveyorSpeed = 0.0f;
|
||||||
|
@ -358,6 +351,7 @@ static void computeConveyorSpeed(const color24 rendercolor, int tex_index, vec2_
|
||||||
speed[1] = sy * flRate;
|
speed[1] = sy * flRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO utilize uploadKusochki([1]) to avoid 2 copies of staging code
|
||||||
static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk_render_model_t *const render_model, uint32_t material_mode, const int *geom_indexes, int geom_indexes_count) {
|
static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk_render_model_t *const render_model, uint32_t material_mode, const int *geom_indexes, int geom_indexes_count) {
|
||||||
// TODO can we sort all animated geometries (in brush) to have only a single range here?
|
// TODO can we sort all animated geometries (in brush) to have only a single range here?
|
||||||
for (int i = 0; i < geom_indexes_count; ++i) {
|
for (int i = 0; i < geom_indexes_count; ++i) {
|
||||||
|
@ -379,8 +373,7 @@ static qboolean uploadKusochkiSubset(const vk_ray_model_t *const model, const vk
|
||||||
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
|
vk_kusok_data_t *const kusochki = kusok_staging.ptr;
|
||||||
|
|
||||||
vk_render_geometry_t *geom = render_model->geometries + index;
|
vk_render_geometry_t *geom = render_model->geometries + index;
|
||||||
applyMaterialToKusok(kusochki + 0, geom, render_model->color, material_mode);
|
applyMaterialToKusok(kusochki + 0, geom);
|
||||||
Matrix4x4_ToArrayFloatGL(render_model->prev_transform, (float*)(kusochki + 0)->model.prev_transform);
|
|
||||||
|
|
||||||
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
|
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
|
||||||
/* render_model->debug_name, */
|
/* render_model->debug_name, */
|
||||||
|
@ -413,8 +406,7 @@ static qboolean uploadKusochki(const vk_ray_model_t *const model, const vk_rende
|
||||||
|
|
||||||
for (int i = 0; i < render_model->num_geometries; ++i) {
|
for (int i = 0; i < render_model->num_geometries; ++i) {
|
||||||
vk_render_geometry_t *geom = render_model->geometries + i;
|
vk_render_geometry_t *geom = render_model->geometries + i;
|
||||||
applyMaterialToKusok(kusochki + i, geom, render_model->color, material_mode);
|
applyMaterialToKusok(kusochki + i, geom);
|
||||||
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", */
|
/* gEngine.Con_Reportf("model %s: geom=%d kuoffs=%d kustoff=%d kustsz=%d sthndl=%d\n", */
|
||||||
|
|
|
@ -25,7 +25,7 @@ typedef enum {
|
||||||
kXVkMaterialRegular = 0,
|
kXVkMaterialRegular = 0,
|
||||||
|
|
||||||
// Set for SURF_DRAWSKY surfaces in vk_brush.c.
|
// Set for SURF_DRAWSKY surfaces in vk_brush.c.
|
||||||
// Used: for setting MATERIAL_MODE_SKYBOX for skybox texture sampling and environment shadows.
|
// Used: for setting TEX_BASE_SKYBOX for skybox texture sampling and environment shadows.
|
||||||
// Remove: pass it as a special texture/material index (e.g. -2).
|
// Remove: pass it as a special texture/material index (e.g. -2).
|
||||||
kXVkMaterialSky,
|
kXVkMaterialSky,
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
X(TLAS, tlas) \
|
X(TLAS, tlas) \
|
||||||
X(Buffer, ubo) \
|
X(Buffer, ubo) \
|
||||||
X(Buffer, kusochki) \
|
X(Buffer, kusochki) \
|
||||||
|
X(Buffer, model_headers) \
|
||||||
X(Buffer, indices) \
|
X(Buffer, indices) \
|
||||||
X(Buffer, vertices) \
|
X(Buffer, vertices) \
|
||||||
X(Buffer, lights) \
|
X(Buffer, lights) \
|
||||||
|
@ -201,6 +202,7 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a
|
||||||
|
|
||||||
// TODO move this to ray model producer
|
// TODO move this to ray model producer
|
||||||
RES_SET_SBUFFER_FULL(kusochki, g_ray_model_state.kusochki_buffer);
|
RES_SET_SBUFFER_FULL(kusochki, g_ray_model_state.kusochki_buffer);
|
||||||
|
RES_SET_SBUFFER_FULL(model_headers, g_ray_model_state.model_headers_buffer);
|
||||||
|
|
||||||
// TODO move these to vk_geometry
|
// TODO move these to vk_geometry
|
||||||
RES_SET_SBUFFER_FULL(indices, args->render_args->geometry_data);
|
RES_SET_SBUFFER_FULL(indices, args->render_args->geometry_data);
|
||||||
|
@ -221,6 +223,13 @@ static void performTracing( vk_combuf_t *combuf, const perform_tracing_args_t* a
|
||||||
.buffer = g_ray_model_state.kusochki_buffer.buffer,
|
.buffer = g_ray_model_state.kusochki_buffer.buffer,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = VK_WHOLE_SIZE,
|
.size = VK_WHOLE_SIZE,
|
||||||
|
}, {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
|
||||||
|
.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
|
.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
|
||||||
|
.buffer = g_ray_model_state.model_headers_buffer.buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.size = VK_WHOLE_SIZE,
|
||||||
} };
|
} };
|
||||||
|
|
||||||
vkCmdPipelineBarrier(cmdbuf,
|
vkCmdPipelineBarrier(cmdbuf,
|
||||||
|
@ -631,6 +640,14 @@ qboolean VK_RayInit( void )
|
||||||
// FIXME complain, handle
|
// FIXME complain, handle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!VK_BufferCreate("model headers", &g_ray_model_state.model_headers_buffer, sizeof(struct ModelHeader) * MAX_ACCELS,
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||||
|
// FIXME complain, handle
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RT_RayModel_Clear();
|
RT_RayModel_Clear();
|
||||||
|
|
||||||
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
||||||
|
@ -643,6 +660,7 @@ void VK_RayShutdown( void ) {
|
||||||
|
|
||||||
destroyMainpipe();
|
destroyMainpipe();
|
||||||
|
|
||||||
|
VK_BufferDestroy(&g_ray_model_state.model_headers_buffer);
|
||||||
VK_BufferDestroy(&g_ray_model_state.kusochki_buffer);
|
VK_BufferDestroy(&g_ray_model_state.kusochki_buffer);
|
||||||
VK_BufferDestroy(&g_rtx.uniform_buffer);
|
VK_BufferDestroy(&g_rtx.uniform_buffer);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue