mirror of
https://github.com/w23/xash3d-fwgs
synced 2025-01-18 23:00:01 +01:00
rtx: sample mip levels based on ray cone width
this is mostly copied from ray tracing gems 2 chapter 7 (Texture Coordinate Gradients Estimation for Ray Cones, by Wessam Bahnassi). There's a weird bit about radians vs degrees. We'll figure it out later when the book becomes available.
This commit is contained in:
parent
71bf85d4f8
commit
94ac51a527
@ -1,5 +1,7 @@
|
||||
## 2021-08-02..04, E122-123
|
||||
- [x] mipmaps
|
||||
|
||||
# Next
|
||||
- [ ] mipmaps
|
||||
- [ ] rtx: split ray tracing into modules: pipeline mgmt, buffer mgmt
|
||||
- [ ] rtx: better light culling: normal, bsp visibility, light volumes and intensity, sort by intensity, etc
|
||||
- [ ] rtx: cluster dlights
|
||||
@ -10,6 +12,8 @@
|
||||
- [ ] studio models: fix lighting: should have white texture instead of lightmap OR we could write nearest surface lightmap coords to fake light
|
||||
|
||||
# Planned
|
||||
- [ ] rtx: better mip lods: there's a weird math that operates on fov degrees (not radians) that we copypasted from ray tracing gems 2 chapter 7. When the book is available, get through the math and figure this out.
|
||||
- [ ] sane texture memory management: do not allocate VKDeviceMemory for every texture
|
||||
- [ ] rtx: transparency layering issue, possible approaches:
|
||||
- [ ] trace a special transparent-only ray separately from opaque. This can at least be used to remove black texture areas
|
||||
- [ ] rtx: sky light/emissive skybox:
|
||||
|
@ -17,6 +17,32 @@ vec3 hashUintToVec3(uint i) { return vec3(hash(float(i)), hash(float(i)+15.43),
|
||||
|
||||
const float normal_offset_fudge = .01;
|
||||
|
||||
// Taken from Ray Tracing Gems II, Chapter 7. Texture Coordinate Gradients Estimation for Ray Cones, by Wessam Bahnassi
|
||||
// https://www.realtimerendering.com/raytracinggems/rtg2/index.html
|
||||
// https://github.com/Apress/Ray-Tracing-Gems-II/blob/main/Chapter_07/Raytracing.hlsl
|
||||
vec4 UVDerivsFromRayCone(vec3 vRayDir, vec3 vWorldNormal, float vRayConeWidth, vec2 aUV[3], vec3 aPos[3], mat3 matWorld)
|
||||
{
|
||||
vec2 vUV10 = aUV[1]-aUV[0];
|
||||
vec2 vUV20 = aUV[2]-aUV[0];
|
||||
float fQuadUVArea = abs(vUV10.x*vUV20.y - vUV20.x*vUV10.y);
|
||||
|
||||
// Since the ray cone's width is in world-space, we need to compute the quad
|
||||
// area in world-space as well to enable proper ratio calculation
|
||||
vec3 vEdge10 = (aPos[1]-aPos[0]) * matWorld;
|
||||
vec3 vEdge20 = (aPos[2]-aPos[0]) * matWorld;
|
||||
vec3 vFaceNrm = cross(vEdge10, vEdge20);
|
||||
float fQuadArea = length(vFaceNrm);
|
||||
|
||||
float fDistTerm = abs(vRayConeWidth);
|
||||
float fNormalTerm = abs(dot(vRayDir,vWorldNormal));
|
||||
float fProjectedConeWidth = vRayConeWidth/fNormalTerm;
|
||||
float fVisibleAreaRatio = (fProjectedConeWidth*fProjectedConeWidth) / fQuadArea;
|
||||
|
||||
float fVisibleUVArea = fQuadUVArea*fVisibleAreaRatio;
|
||||
float fULength = sqrt(fVisibleUVArea);
|
||||
return vec4(fULength,0,0,fULength);
|
||||
}
|
||||
|
||||
void main() {
|
||||
//const float l = gl_HitTEXT;
|
||||
//ray_result.color = vec3(fract(l / 10.));
|
||||
@ -25,6 +51,8 @@ void main() {
|
||||
//ray_result.color = vec3(.5);
|
||||
|
||||
vec3 hit_pos = gl_WorldRayOriginEXT + gl_WorldRayDirectionEXT * gl_HitTEXT;
|
||||
payload.t_offset += gl_HitTEXT;
|
||||
|
||||
// ray_result.color = fract((hit_pos + .5) / 10.);
|
||||
//ray_result.color = vec3(1.);
|
||||
//return;
|
||||
@ -43,14 +71,28 @@ void main() {
|
||||
const vec3 n3 = vertices[vi3].normal;
|
||||
|
||||
// TODO use already inverse gl_WorldToObject ?
|
||||
const vec3 normal = normalize(transpose(inverse(mat3(gl_ObjectToWorldEXT))) * (n1 * (1. - bary.x - bary.y) + n2 * bary.x + n3 * bary.y));
|
||||
const mat3 matWorld = mat3(gl_ObjectToWorldEXT);
|
||||
const vec3 normal = normalize(transpose(inverse(matWorld)) * (n1 * (1. - bary.x - bary.y) + n2 * bary.x + n3 * bary.y));
|
||||
hit_pos += normal * normal_offset_fudge;
|
||||
|
||||
// //C = normal * .5 + .5; break;
|
||||
|
||||
const vec2 uvs[3] = {
|
||||
vertices[vi1].gl_tc,
|
||||
vertices[vi2].gl_tc,
|
||||
vertices[vi3].gl_tc,
|
||||
};
|
||||
const vec3 pos[3] = {
|
||||
vertices[vi1].pos,
|
||||
vertices[vi2].pos,
|
||||
vertices[vi3].pos,
|
||||
};
|
||||
const vec2 texture_uv = vertices[vi1].gl_tc * (1. - bary.x - bary.y) + vertices[vi2].gl_tc * bary.x + vertices[vi3].gl_tc * bary.y;
|
||||
const uint tex_index = kusochki[kusok_index].texture;
|
||||
const vec3 base_color = pow(texture(textures[nonuniformEXT(tex_index)], texture_uv).rgb, vec3(2.));
|
||||
|
||||
const float ray_cone_width = payload.pixel_cone_spread_angle * payload.t_offset;
|
||||
const vec4 uv_lods = UVDerivsFromRayCone(gl_WorldRayDirectionEXT, normal, ray_cone_width, uvs, pos, matWorld);
|
||||
const vec3 base_color = pow(textureGrad(textures[nonuniformEXT(tex_index)], texture_uv, uv_lods.xy, uv_lods.zw).rgb, vec3(2.));
|
||||
|
||||
payload.hit_pos_t = vec4(hit_pos, gl_HitTEXT);
|
||||
payload.albedo = base_color;
|
||||
|
@ -74,6 +74,7 @@ layout (push_constant) uniform PushConstants {
|
||||
uint random_seed;
|
||||
int bounces;
|
||||
float prev_frame_blend_factor;
|
||||
float pixel_cone_spread_angle;
|
||||
} push_constants;
|
||||
|
||||
// TODO find better random function
|
||||
@ -281,6 +282,9 @@ void main() {
|
||||
vec3 kc = vec3(1.);
|
||||
vec3 C = vec3(0.);
|
||||
|
||||
payload.t_offset = .0;
|
||||
payload.pixel_cone_spread_angle = push_constants.pixel_cone_spread_angle;
|
||||
|
||||
for (int bounce = 0; bounce < push_constants.bounces; ++bounce) {
|
||||
const uint flags = 0
|
||||
| gl_RayFlagsCullFrontFacingTrianglesEXT
|
||||
@ -293,7 +297,7 @@ void main() {
|
||||
const float L = 10000.;
|
||||
traceRayEXT(tlas, flags, 0xff,
|
||||
sbt_offset, sbt_stride, miss_index,
|
||||
origin, .001, direction, L,
|
||||
origin, 0., direction, L,
|
||||
ray_payload_loc);
|
||||
|
||||
if (payload.hit_pos_t.w <= 0.) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
#extension GL_EXT_ray_tracing: require
|
||||
struct RayPayload {
|
||||
float t_offset, pixel_cone_spread_angle;
|
||||
vec4 hit_pos_t;
|
||||
vec3 albedo;
|
||||
vec3 normal;
|
||||
|
@ -53,6 +53,8 @@ static struct {
|
||||
vec3_t origin, color;
|
||||
} static_lights[32];
|
||||
int num_static_lights;
|
||||
|
||||
float fov_angle_y;
|
||||
} g_render;
|
||||
|
||||
static qboolean createPipelines( void )
|
||||
@ -516,10 +518,11 @@ static const matrix4x4 vk_proj_fixup = {
|
||||
{0, 0, 0, 1}
|
||||
};
|
||||
|
||||
void VK_RenderStateSetMatrixProjection(const matrix4x4 projection)
|
||||
void VK_RenderStateSetMatrixProjection(const matrix4x4 projection, float fov_angle_y)
|
||||
{
|
||||
g_render_state.uniform_data_set_mask |= UNIFORM_SET_MATRIX_PROJECTION;
|
||||
Matrix4x4_Concat( g_render_state.projection, vk_proj_fixup, projection );
|
||||
g_render.fov_angle_y = fov_angle_y;
|
||||
}
|
||||
|
||||
void VK_RenderStateSetMatrixView(const matrix4x4 view)
|
||||
@ -794,6 +797,8 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
|
||||
.buffer = g_render.buffer.buffer,
|
||||
.size = VK_WHOLE_SIZE,
|
||||
},
|
||||
|
||||
.fov_angle_y = g_render.fov_angle_y,
|
||||
};
|
||||
|
||||
if (args.ubo.offset == UINT32_MAX) {
|
||||
|
@ -48,7 +48,7 @@ void VK_RenderBufferPrintStats( void );
|
||||
void VK_RenderStateSetColor( float r, float g, float b, float a );
|
||||
// TODO void VK_RenderStateGetColor( vec4_t color );
|
||||
|
||||
void VK_RenderStateSetMatrixProjection(const matrix4x4 proj);
|
||||
void VK_RenderStateSetMatrixProjection(const matrix4x4 proj, float fov_angle_y);
|
||||
void VK_RenderStateSetMatrixView(const matrix4x4 view);
|
||||
void VK_RenderStateSetMatrixModel(const matrix4x4 model);
|
||||
|
||||
|
@ -42,6 +42,7 @@ typedef struct {
|
||||
uint32_t random_seed;
|
||||
int bounces;
|
||||
float prev_frame_blend_factor;
|
||||
float pixel_cone_spread_angle;
|
||||
} vk_rtx_push_constants_t;
|
||||
|
||||
typedef struct {
|
||||
@ -575,7 +576,7 @@ static void updateDescriptors( VkCommandBuffer cmdbuf, const vk_ray_frame_render
|
||||
VK_DescriptorsWrite(&g_rtx.descriptors);
|
||||
}
|
||||
|
||||
static qboolean rayTrace( VkCommandBuffer cmdbuf, VkImage frame_dst )
|
||||
static qboolean rayTrace( VkCommandBuffer cmdbuf, VkImage frame_dst, float fov_angle_y )
|
||||
{
|
||||
// 4. Barrier for TLAS build and dest image layout transfer
|
||||
{
|
||||
@ -613,6 +614,7 @@ static qboolean rayTrace( VkCommandBuffer cmdbuf, VkImage frame_dst )
|
||||
.random_seed = (uint32_t)gEngine.COM_RandomLong(0, INT32_MAX),
|
||||
.bounces = vk_rtx_bounces->value,
|
||||
.prev_frame_blend_factor = vk_rtx_prev_frame_blend_factor->value,
|
||||
.pixel_cone_spread_angle = atanf((2.0f*tanf(fov_angle_y * 0.5f)) / (float)FRAME_HEIGHT),
|
||||
};
|
||||
vkCmdPushConstants(cmdbuf, g_rtx.descriptors.pipeline_layout, VK_SHADER_STAGE_RAYGEN_BIT_KHR, 0, sizeof(push_constants), &push_constants);
|
||||
}
|
||||
@ -788,7 +790,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
||||
} else {
|
||||
prepareTlas(cmdbuf);
|
||||
updateDescriptors(cmdbuf, args, frame_src, frame_dst);
|
||||
rayTrace(cmdbuf, frame_dst->image);
|
||||
rayTrace(cmdbuf, frame_dst->image, args->fov_angle_y);
|
||||
|
||||
// Barrier for frame_dst image
|
||||
{
|
||||
|
@ -45,6 +45,8 @@ typedef struct {
|
||||
VkBuffer buffer; // must be the same as in vk_ray_model_create_t TODO: validate or make impossible to specify incorrectly
|
||||
uint32_t size;
|
||||
} geometry_data;
|
||||
|
||||
float fov_angle_y;
|
||||
} vk_ray_frame_render_args_t;
|
||||
void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args);
|
||||
|
||||
|
@ -657,7 +657,7 @@ void VK_SceneRender( const ref_viewpass_t *rvp )
|
||||
|
||||
setupCamera( rvp );
|
||||
|
||||
VK_RenderStateSetMatrixProjection( g_camera.projectionMatrix );
|
||||
VK_RenderStateSetMatrixProjection( g_camera.projectionMatrix, g_camera.fov_y ); // FIXME why is this in degrees, not in radians? * M_PI_F / 360.0f );
|
||||
VK_RenderStateSetMatrixView( g_camera.modelviewMatrix );
|
||||
VK_RenderStateSetMatrixModel( matrix4x4_identity );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user