diff --git a/ref/vk/shaders/bounce.comp b/ref/vk/shaders/bounce.comp index 9a43c8a1..094f24b0 100644 --- a/ref/vk/shaders/bounce.comp +++ b/ref/vk/shaders/bounce.comp @@ -20,7 +20,6 @@ RAY_LIGHT_DIRECT_INPUTS(X) layout(set=0, binding=20, rgba16f) uniform writeonly image2D out_indirect_diffuse; layout(set=0, binding=21, rgba16f) uniform writeonly image2D out_indirect_specular; -layout(set=0, binding=27) uniform samplerCube skybox; #include "ray_primary_common.glsl" #include "ray_primary_hit.glsl" @@ -73,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 const MiniGeometry geom = readCandidateMiniGeometry(rq); 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 float alpha_mask_threshold = .1f; @@ -149,14 +149,8 @@ void computeBounce(ivec2 pix, vec3 direction, out vec3 diffuse, out vec3 specula payload.base_color_a = vec4(0.); payload.emissive = vec4(0.); const vec3 pos = imageLoad(position_t, pix).xyz + geometry_normal * ray_normal_fudge; - if (!getHit(pos, bounce_direction, payload)) { - const vec3 skycolor = SRGBtoLINEAR(texture(skybox, bounce_direction).rgb); - if (brdf_type == DIFFUSE_TYPE) { - diffuse += skycolor; - } else - specular += skycolor; + if (!getHit(pos, bounce_direction, payload)) return; - } throughput *= payload.base_color_a.rgb; diff --git a/ref/vk/shaders/light_common.glsl b/ref/vk/shaders/light_common.glsl index fc6b9591..01db0564 100644 --- a/ref/vk/shaders/light_common.glsl +++ b/ref/vk/shaders/light_common.glsl @@ -117,7 +117,7 @@ bool shadowedSky(vec3 pos, vec3 dir) { | gl_RayFlagsSkipClosestHitShaderEXT ; const uint hit_type = traceShadowRay(pos, dir, dist, flags); - return payload_shadow.hit_type != SHADOW_MISS; + return payload_shadow.hit_type != SHADOW_SKY; #elif defined(RAY_QUERY) rayQueryEXT rq; @@ -125,22 +125,28 @@ bool shadowedSky(vec3 pos, vec3 dir) { // Culling for shadows breaks more things (e.g. de_cbble slightly off the ground boxes) than it probably fixes. Keep it turned off. //| gl_RayFlagsCullFrontFacingTrianglesEXT | gl_RayFlagsOpaqueEXT - | gl_RayFlagsTerminateOnFirstHitEXT + //| gl_RayFlagsTerminateOnFirstHitEXT //| gl_RayFlagsSkipClosestHitShaderEXT ; const float L = 10000.; // TODO Why 10k? rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE, pos, 0., dir, L); - // Any intersection results in a shadow + // Find closest intersection, and then check whether that was a skybox while (rayQueryProceedEXT(rq)) {} if (rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT) { - return true; + const uint instance_kusochki_offset = rayQueryGetIntersectionInstanceCustomIndexEXT(rq, true); + const uint geometry_index = rayQueryGetIntersectionGeometryIndexEXT(rq, true); + const uint kusok_index = instance_kusochki_offset + geometry_index; + const Kusok kusok = getKusok(kusok_index); + + if (kusok.material.tex_base_color != TEX_BASE_SKYBOX) + return true; } // check for alpha-masked surfaces separately - // TODO compare with doing it in the same loop as above - return shadowTestAlphaMask(pos, dir, L); + const float hit_t = rayQueryGetIntersectionTEXT(rq, true); + return shadowTestAlphaMask(pos, dir, hit_t); #else #error RAY_TRACE or RAY_QUERY diff --git a/ref/vk/shaders/ray_common.glsl b/ref/vk/shaders/ray_common.glsl index b48590d7..bf9ad41f 100644 --- a/ref/vk/shaders/ray_common.glsl +++ b/ref/vk/shaders/ray_common.glsl @@ -23,6 +23,7 @@ struct RayPayloadOpaque { #define SHADOW_MISS 0 #define SHADOW_HIT 1 +#define SHADOW_SKY 2 struct RayPayloadShadow { uint hit_type; diff --git a/ref/vk/shaders/ray_interop.h b/ref/vk/shaders/ray_interop.h index fefbd40c..5124b260 100644 --- a/ref/vk/shaders/ray_interop.h +++ b/ref/vk/shaders/ray_interop.h @@ -71,6 +71,8 @@ LIST_SPECIALIZATION_CONSTANTS(DECLARE_SPECIALIZATION_CONSTANT) #define MATERIAL_MODE_BLEND_GLOW 5 #define MATERIAL_MODE_COUNT 6 +#define TEX_BASE_SKYBOX 0xffffffffu + struct Material { uint tex_base_color; diff --git a/ref/vk/shaders/ray_primary.comp b/ref/vk/shaders/ray_primary.comp index 94d4fda3..768e8fa7 100644 --- a/ref/vk/shaders/ray_primary.comp +++ b/ref/vk/shaders/ray_primary.comp @@ -24,8 +24,6 @@ RAY_PRIMARY_OUTPUTS(X) layout(set = 0, binding = 1) uniform accelerationStructureEXT tlas; -layout(set = 0, binding = 7) uniform samplerCube skybox; - #include "trace_simple_blending.glsl" struct Ray { @@ -78,6 +76,7 @@ void main() { ; rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE | GEOMETRY_BIT_ALPHA_TEST | GEOMETRY_BIT_REFRACTIVE, ray.origin, 0., ray.direction, ray.dist); while (rayQueryProceedEXT(rq)) { + // FIXME this is a no-op. It doesn't do what I though it did. Should check for SBT index for alpha-test material instead. if (0 != (rayQueryGetRayFlagsEXT(rq) & gl_RayFlagsOpaqueEXT)) continue; @@ -90,6 +89,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 const MiniGeometry geom = readCandidateMiniGeometry(rq); 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 float alpha_mask_threshold = .1f; @@ -105,9 +105,6 @@ void main() { //debug_geometry_index = rayQueryGetIntersectionPrimitiveIndexEXT(rq, true); primaryRayHit(rq, payload); L = rayQueryGetIntersectionTEXT(rq, true); - } else { - payload.hit_t = payload.prev_pos_t = vec4(ray.origin + ray.direction * ray.dist, ray.dist); - payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, ray.direction).rgb); } traceSimpleBlending(ray.origin, ray.direction, L, payload.emissive.rgb, payload.base_color_a.rgb); diff --git a/ref/vk/shaders/ray_primary.rchit b/ref/vk/shaders/ray_primary.rchit index 54826a94..d52a9e53 100644 --- a/ref/vk/shaders/ray_primary.rchit +++ b/ref/vk/shaders/ray_primary.rchit @@ -29,7 +29,10 @@ void main() { const Kusok kusok = getKusok(geom.kusok_index); - { + if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) { + payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb); + return; + } else { 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; diff --git a/ref/vk/shaders/ray_primary.rmiss b/ref/vk/shaders/ray_primary.rmiss index 134e1d39..4b072ab7 100644 --- a/ref/vk/shaders/ray_primary.rmiss +++ b/ref/vk/shaders/ray_primary.rmiss @@ -1,14 +1,4 @@ #version 460 core #extension GL_EXT_ray_tracing: require -#include "ray_primary_common.glsl" -#include "color_spaces.glsl" - -layout(set = 0, binding = 7) uniform samplerCube skybox; - -layout(location = PAYLOAD_LOCATION_PRIMARY) rayPayloadEXT RayPayloadPrimary payload; - -void main() { - // TODO payload.prev_pos_t = payload.hit_t = vec4(geom.pos, gl_HitTEXT); - payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, gl_WorldRayDirectionEXT).rgb); -} +void main() {} diff --git a/ref/vk/shaders/ray_primary_hit.glsl b/ref/vk/shaders/ray_primary_hit.glsl index 8d6c38d8..1a115042 100644 --- a/ref/vk/shaders/ray_primary_hit.glsl +++ b/ref/vk/shaders/ray_primary_hit.glsl @@ -10,6 +10,7 @@ layout(set = 0, binding = 6) uniform sampler2D textures[MAX_TEXTURES]; layout(set = 0, binding = 2) uniform UBO { UniformBuffer ubo; } ubo; +layout(set = 0, binding = 7) uniform samplerCube skybox; vec4 sampleTexture(uint tex_index, vec2 uv, vec4 uv_lods) { #ifndef RAY_BOUNCE @@ -29,7 +30,10 @@ void primaryRayHit(rayQueryEXT rq, inout RayPayloadPrimary payload) { const Kusok kusok = getKusok(geom.kusok_index); const Material material = kusok.material; - { + if (kusok.material.tex_base_color == TEX_BASE_SKYBOX) { + payload.emissive.rgb = SRGBtoLINEAR(texture(skybox, rayDirection).rgb); + return; + } else { 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; diff --git a/ref/vk/shaders/ray_shadow.rchit b/ref/vk/shaders/ray_shadow.rchit index f6b1f70b..b63f7208 100644 --- a/ref/vk/shaders/ray_shadow.rchit +++ b/ref/vk/shaders/ray_shadow.rchit @@ -7,5 +7,10 @@ layout(location = PAYLOAD_LOCATION_SHADOW) rayPayloadInEXT RayPayloadShadow payload_shadow; void main() { - payload_shadow.hit_type = SHADOW_HIT; + const int instance_kusochki_offset = gl_InstanceCustomIndexEXT; + const int kusok_index = instance_kusochki_offset + gl_GeometryIndexEXT; + const Kusok kusok = getKusok(kusok_index); + const uint tex_base_color = kusok.material.tex_base_color; + + payload_shadow.hit_type = (kusok.material.tex_base_color != TEX_BASE_SKYBOX) ? SHADOW_HIT : SHADOW_SKY ; } diff --git a/ref/vk/shaders/ray_shadow_interface.glsl b/ref/vk/shaders/ray_shadow_interface.glsl index 9b386926..73d83be7 100644 --- a/ref/vk/shaders/ray_shadow_interface.glsl +++ b/ref/vk/shaders/ray_shadow_interface.glsl @@ -3,6 +3,7 @@ #define SHADOW_MISS 0 #define SHADOW_HIT 1 +#define SHADOW_SKY 2 struct RayPayloadShadow { uint hit_type; diff --git a/ref/vk/vk_brush.c b/ref/vk/vk_brush.c index cd84eb66..5e7d6da7 100644 --- a/ref/vk/vk_brush.c +++ b/ref/vk/vk_brush.c @@ -778,13 +778,13 @@ static model_sizes_t computeSizes( const model_t *mod ) { case BrushSurface_Water: sizes.water_surfaces++; addWarpVertIndCounts(surf, &sizes.water_vertices, &sizes.water_indices); - case BrushSurface_Sky: case BrushSurface_Hidden: continue; case BrushSurface_Animated: sizes.animated_count++; case BrushSurface_Regular: + case BrushSurface_Sky: break; } @@ -1058,11 +1058,11 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { switch (type) { case BrushSurface_Water: case BrushSurface_Hidden: - case BrushSurface_Sky: continue; case BrushSurface_Animated: args.bmodel->animated_indexes[animated_count++] = num_geometries; case BrushSurface_Regular: + case BrushSurface_Sky: break; } @@ -1089,7 +1089,10 @@ static qboolean fillBrushSurfaces(fill_geometries_args_t args) { model_geometry->index_offset = index_offset; - { + if ( type == BrushSurface_Sky ) { +#define TEX_BASE_SKYBOX 0xffffffffu // FIXME ray_interop.h + model_geometry->material.tex_base_color = TEX_BASE_SKYBOX; + } else { ASSERT(!FBitSet( surf->flags, SURF_DRAWTILED )); VK_CreateSurfaceLightmap( surf, args.mod ); }