mirror of
https://github.com/w23/xash3d-fwgs
synced 2024-12-16 06:00:33 +01:00
93 lines
3.4 KiB
Plaintext
93 lines
3.4 KiB
Plaintext
#version 460 core
|
|
#extension GL_GOOGLE_include_directive : require
|
|
#extension GL_EXT_nonuniform_qualifier : enable
|
|
#extension GL_EXT_ray_query: require
|
|
|
|
#define RAY_QUERY
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
|
|
#include "ray_primary_common.glsl"
|
|
#include "ray_primary_hit.glsl"
|
|
|
|
#define RAY_PRIMARY_OUTPUTS(X) \
|
|
X(10, base_color_a, rgba8) \
|
|
X(11, position_t, rgba32f) \
|
|
X(12, normals_gs, rgba16f) \
|
|
X(13, material_rmxx, rgba8) \
|
|
X(14, emissive, rgba16f) \
|
|
X(15, geometry_prev_position, rgba32f) \
|
|
|
|
#define X(index, name, format) layout(set=0,binding=index,format) uniform writeonly image2D out_##name;
|
|
RAY_PRIMARY_OUTPUTS(X)
|
|
#undef X
|
|
|
|
layout(set = 0, binding = 1) uniform accelerationStructureEXT tlas;
|
|
|
|
#include "trace_additive.glsl"
|
|
|
|
void main() {
|
|
const ivec2 pix = ivec2(gl_GlobalInvocationID);
|
|
const ivec2 res = ivec2(imageSize(out_position_t));
|
|
if (any(greaterThanEqual(pix, res))) {
|
|
return;
|
|
}
|
|
const vec2 uv = (gl_GlobalInvocationID.xy + .5) / res * 2. - 1.;
|
|
|
|
// FIXME start on a near plane
|
|
const vec3 origin = (ubo.ubo.inv_view * vec4(0, 0, 0, 1)).xyz;
|
|
const vec4 target = ubo.ubo.inv_proj * vec4(uv.x, uv.y, 1, 1);
|
|
const vec3 direction = normalize((ubo.ubo.inv_view * vec4(target.xyz, 0)).xyz);
|
|
|
|
RayPayloadPrimary payload;
|
|
payload.hit_t = vec4(0.);
|
|
payload.prev_pos_t = vec4(0.);
|
|
payload.base_color_a = vec4(0.);
|
|
payload.normals_gs = vec4(0.);
|
|
payload.material_rmxx = vec4(0.);
|
|
payload.emissive = vec4(0.);
|
|
|
|
rayQueryEXT rq;
|
|
const uint flags = 0
|
|
| gl_RayFlagsCullFrontFacingTrianglesEXT
|
|
//| gl_RayFlagsOpaqueEXT
|
|
//| gl_RayFlagsTerminateOnFirstHitEXT
|
|
//| gl_RayFlagsSkipClosestHitShaderEXT
|
|
;
|
|
float L = 10000.; // TODO Why 10k?
|
|
rayQueryInitializeEXT(rq, tlas, flags, GEOMETRY_BIT_OPAQUE | GEOMETRY_BIT_ALPHA_TEST | GEOMETRY_BIT_REFRACTIVE, origin, 0., direction, L);
|
|
while (rayQueryProceedEXT(rq)) {
|
|
if (0 != (rayQueryGetRayFlagsEXT(rq) & gl_RayFlagsOpaqueEXT))
|
|
continue;
|
|
|
|
// alpha test
|
|
// TODO check other possible ways of doing alpha test. They might be more efficient
|
|
// (although in this particular primary ray case it's not taht important):
|
|
// 1. Do a separate ray query for alpha masked geometry. Reason: here we might accidentally do the expensive
|
|
// texture sampling for geometry that's ultimately invisible (i.e. behind walls). Also, shader threads congruence.
|
|
// 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 vec4 texture_color = texture(textures[nonuniformEXT(tex_base_color)], geom.uv);
|
|
|
|
const float alpha_mask_threshold = .1f;
|
|
if (texture_color.a >= alpha_mask_threshold) {
|
|
rayQueryConfirmIntersectionEXT(rq);
|
|
}
|
|
}
|
|
|
|
if (rayQueryGetIntersectionTypeEXT(rq, true) == gl_RayQueryCommittedIntersectionTriangleEXT) {
|
|
primaryRayHit(rq, payload);
|
|
L = rayQueryGetIntersectionTEXT(rq, true);
|
|
}
|
|
|
|
payload.emissive.rgb += traceAdditive(origin, direction, L);
|
|
|
|
imageStore(out_position_t, pix, payload.hit_t);
|
|
imageStore(out_base_color_a, pix, payload.base_color_a);
|
|
imageStore(out_normals_gs, pix, payload.normals_gs);
|
|
imageStore(out_material_rmxx, pix, payload.material_rmxx);
|
|
imageStore(out_emissive, pix, payload.emissive);
|
|
imageStore(out_geometry_prev_position, pix, payload.prev_pos_t);
|
|
}
|