OverviewFilesCommitsIssuesDocsReleasesPeers

nvidia-rtx-godot / servers / rendering / renderer_rd / shaders / raytracing / raytracing_custom_fragment_inc.glsl

135 lines · glsl ref:
// Custom shader fragment setup for RT hit groups (closest-hit and any-hit).
// Include inside main() under #ifdef RT_CUSTOM_HIT_GROUP.
//
// Required variables before inclusion:
//   uint  rt_geometry_idx   -- geometry/material index
//   vec3  rt_hit_pos        -- world-space hit position
//   vec2  rt_uv             -- interpolated UV
//   vec3  rt_normal         -- world-space geometry normal (flipped for back-face)
//   vec3  rt_tangent        -- world-space tangent
//   vec3  rt_bitangent      -- world-space bitangent
//   bool  rt_front_face     -- true if front-face hit
//   vec4  rt_custom0..3     -- CUSTOM0-3 vertex attributes (vec4(0) if absent)
//
// Required bindings/types:
//   materials[], CustomMaterialUniforms, scene_data_block

MaterialData rt_mat = materials[rt_geometry_idx];
material = CustomMaterialUniforms(rt_mat.uniform_address);

// packed_bounces_flags is a plain field on the payload, so this is a mask rather
// than a full path_unpack.
rt_bounce_index = get_total_bounces(payload.packed_bounces_flags);
rt_primary_hit = (rt_bounce_index == 0u);

// Matrices.
mat4 rt_view_matrix = transpose(mat4(scene_data_block.data.view_matrix[0],
		scene_data_block.data.view_matrix[1],
		scene_data_block.data.view_matrix[2],
		vec4(0.0, 0.0, 0.0, 1.0)));

GeometryData rt_geom = geometries[rt_geometry_idx];
mat4 rt_aabb_xform;
mat4 rt_inv_aabb_xform;
get_aabb_compression_xforms(rt_geom, rt_aabb_xform, rt_inv_aabb_xform);

read_model_matrix = mat4(gl_ObjectToWorldEXT) * rt_inv_aabb_xform;
read_view_matrix = rt_view_matrix;
inv_view_matrix = transpose(mat4(scene_data_block.data.inv_view_matrix[0],
		scene_data_block.data.inv_view_matrix[1],
		scene_data_block.data.inv_view_matrix[2],
		vec4(0.0, 0.0, 0.0, 1.0)));
projection_matrix = scene_data_block.data.projection_matrix;
inv_projection_matrix = scene_data_block.data.inv_projection_matrix;
read_viewport_size = scene_data_block.data.viewport_size;
global_time = scene_data_block.data.time;

mat4 rt_world_to_object_decomp = rt_aabb_xform * mat4(gl_WorldToObjectEXT);

vertex = (rt_world_to_object_decomp * vec4(rt_hit_pos, 1.0)).xyz;
normal = mat3(rt_world_to_object_decomp) * rt_normal;
tangent = mat3(rt_world_to_object_decomp) * rt_tangent;
binormal = mat3(rt_world_to_object_decomp) * rt_bitangent;
uv_interp = rt_uv;
uv2_interp = rt_uv;
color_interp = rt_color;
custom0_attrib = rt_custom0;
custom1_attrib = rt_custom1;
custom2_attrib = rt_custom2;
custom3_attrib = rt_custom3;
view = -gl_WorldRayDirectionEXT;
rt_front_facing = rt_front_face;
rt_screen_uv = vec2(gl_LaunchIDEXT.xy) / vec2(gl_LaunchSizeEXT.xy);
rt_frag_coord = vec4(gl_LaunchIDEXT.xy, 0.0, 1.0);

// Per-pixel world-space footprint at the hit (ray differentials). The camera's
// right/up axes, scaled by the world size of one pixel at this distance, then
// slid along the ray onto the surface plane so grazing angles stretch the
// footprint the way real derivatives would.
//
// projection_matrix[1][1] is 1/tan(fovy/2), so 2*t/(that * viewport_height) is the
// world height of a pixel at distance t. On secondary bounces gl_HitTEXT is that
// bounce's length rather than a camera distance, which makes this an
// approximation there -- still far better than the zero derivative it replaces.
{
	float rt_t = gl_HitTEXT;
	vec3 rt_dir = gl_WorldRayDirectionEXT;
	// abs(): projection_matrix[1][1] is NEGATIVE under Vulkan's Y-flip. update_ubo
	// builds projection = correction * cam_projection, and Projection::set_depth_correction
	// sets columns[1][1] = flip_y ? -1 : 1 (projection.cpp:796), so this term is about
	// -1/tan(fovy/2). Without abs() the product goes negative, max(negative, 1e-6)
	// returns the epsilon, and the footprint inflates by ~1e6 -- every textureGrad in a
	// custom hit group then takes the coarsest mip. MEASURED on map_dc_level: median LOD
	// 6.000 (clamp ceiling) against the rasterizer's ground-truth 0.494.
	float rt_px = 2.0 * rt_t / max(abs(projection_matrix[1][1]) * read_viewport_size.y, 1e-6);
	vec3 rt_fx = inv_view_matrix[0].xyz * rt_px;
	vec3 rt_fy = inv_view_matrix[1].xyz * rt_px;
	vec3 rt_n = normalize(rt_normal);
	float rt_ndotd = dot(rt_n, rt_dir);
	if (abs(rt_ndotd) > 1e-4) {
		rt_footprint_x = rt_fx - rt_dir * (dot(rt_fx, rt_n) / rt_ndotd);
		rt_footprint_y = rt_fy - rt_dir * (dot(rt_fy, rt_n) / rt_ndotd);
	} else {
		rt_footprint_x = rt_fx;
		rt_footprint_y = rt_fy;
	}
}

// Run vertex shader (computes varyings, may modify built-ins).
/* RT_CUSTOM_VERTEX_CALL */

// Post-vertex transform: object-space -> view-space (mirrors rasterizer post-vertex).
mat4 rt_modelview = rt_view_matrix * read_model_matrix;
vertex = (rt_modelview * vec4(vertex, 1.0)).xyz;
normal = normalize(mat3(rt_modelview) * normal);
tangent = normalize(mat3(rt_modelview) * tangent);
binormal = normalize(mat3(rt_modelview) * binormal);

// Fragment outputs with sensible defaults.
vec3 albedo = vec3(1.0);
float alpha = 1.0;
float metallic = 0.0;
float roughness = 0.5;
float specular = 0.5;
vec3 emission = vec3(0.0);
vec3 normal_map = vec3(0.5, 0.5, 1.0);
float normal_map_depth = 1.0;
float ao = 1.0;
float ao_light_affect = 0.0;
vec3 backlight = vec3(0.0);
float sss_strength = 0.0;
float rim = 0.0;
float rim_tint = 0.0;
float clearcoat = 0.0;
float clearcoat_roughness = 0.0;
float anisotropy = 0.0;
vec2 anisotropy_flow = vec2(1.0, 0.0);
float alpha_scissor_threshold = 0.0;
float alpha_hash_scale = 1.0;
float alpha_antialiasing_edge = 0.0;
vec2 alpha_texture_coordinate = vec2(0.0);

{
	/* RT_CUSTOM_FRAGMENT_CODE */
}