#version 460
#extension GL_NV_ray_tracing : require
#extension GL_GOOGLE_include_directive : enable
#include <light.h>
#include <rt-shdr-common.h>
#ifdef _RT_INTERSECTION_
#extension GL_EXT_nonuniform_qualifier : enable
void
main()
{
const uint ii = gl_InstanceID;
RT_Uni_Per_Instance upi = uni_per_instance_a[ii];
const int sphere_idx = gl_PrimitiveID;
vec4 pos_rad = pos[ii].pos[sphere_idx];
float radius = pos_rad.w;
vec3 c_o = pos_rad.xyz; vec3 vrc = c_o - gl_ObjectRayOriginNV;
float qa = dot(gl_ObjectRayDirectionNV,gl_ObjectRayDirectionNV);
float qb = -dot(gl_ObjectRayDirectionNV,vrc);
float qc = dot(vrc,vrc) - radius * radius;
float discr = qb * qb - qa * qc;
if ( discr < 0 ) return;
float discr_srt = sqrt(discr);
float t0 = (-qb - discr_srt) / qa;
float t1 = (-qb + discr_srt) / qa;
bool outside = t0 >= gl_RayTminNV;
float t = outside ? t0 : t1;
if ( t < gl_RayTminNV ) return;
uint hit_kind = outside
? gl_HitKindFrontFacingTriangleEXT : gl_HitKindBackFacingTriangleEXT;
reportIntersectionNV( t, hit_kind );
}
#endif
#ifdef _RT_CLOSEST_HIT_
#extension GL_EXT_nonuniform_qualifier : enable
layout(location = 0) rayPayloadInNV vec4 rp_color;
layout(location = 2) rayPayloadNV bool rp_shadowed;
struct Lighted_Colors { vec3 primary, specular; };
Lighted_Colors generic_lighting_specular
(vec4 vertex_e, vec4 color, vec3 normal_er, uint shadow_vec);
vec3 generic_lighting
(vec4 v_e, vec4 color, vec3 n_er, uint shadow_vec)
{ return generic_lighting_specular(v_e,color,n_er,shadow_vec).primary; }
vec4 homogenize(vec4 uh) { return uh / uh.w; }
void main()
{
const uint ii = gl_InstanceID;
const int sphere_idx = gl_PrimitiveID;
RT_Uni_Per_Instance upi = uni_per_instance_a[ii];
const bool do_lighting = true;
const float this_depth = rp_color.a + 1;
const bool can_cast = this_depth < ray_recursion_max;
const bool can_refl = com.opt_mirror > 0 && this_depth < ray_recursion_max-1;
rp_color.a = this_depth;
# define MIX(a) ( a[ii].a[sphere_idx] )
vec4 vertex_g =
vec4(gl_WorldRayOriginNV + gl_WorldRayDirectionNV * gl_HitTNV,1);
vec4 vertex_o =
vec4(gl_ObjectRayOriginNV + gl_ObjectRayDirectionNV * gl_HitTNV,1);
vec4 pos_rad = MIX(pos);
float rad = pos_rad.w;
vec3 c_o = pos_rad.xyz;
const bool per_vtx_color = bool( upi.in_usage & USAGE_BVEC_COLOR );
vec4 color_front, color_back;
if ( per_vtx_color )
{
color_back = color_front = MIX(color);
}
else
{
color_front = upi.color_front;
color_back = upi.color_back;
}
const bool front_facing = gl_HitKindNV == gl_HitKindFrontFacingTriangleEXT;
const vec4 color = front_facing ? color_front : color_back;
vec3 color_tex = color.rgb;
Lighted_Colors lc;
vec4 vertex_e = ut.eye_from_object * vertex_g;
vec3 normal_o = vertex_o.xyz - c_o.xyz;
vec3 normal_g = mat3(gl_ObjectToWorldNV) * normal_o;
rp_shadowed = true;
if ( do_lighting )
{
uint shadow_vec = 0;
if ( bool(com.opt_shadows) && can_cast )
for ( int i = 0; i<cgl_MaxLights; i++ )
{
uint lv = 1 << i;
if ( ( lv & com.light_on_vec ) == 0 ) continue;
vec4 light_g = ut.object_from_eye * ul.cgl_LightSource[i].position;
vec3 vtx_to_light_g = light_g.xyz - vertex_g.xyz;
float dist_min = 0.01; float tmin = dist_min / length(vtx_to_light_g);
float tmax = 1.0;
rp_shadowed = true;
traceNV
( topLevelAS,
gl_RayFlagsTerminateOnFirstHitNV
| gl_RayFlagsOpaqueNV | gl_RayFlagsSkipClosestHitShaderNV,
0xfe, 0, 0, 1, vertex_g.xyz,
tmin, vtx_to_light_g, tmax, 2 );
shadow_vec |= rp_shadowed ? lv : 0;
}
vec3 normal_e = mat3(ut.eye_from_object) * normal_g;
lc = generic_lighting_specular(vertex_e,color,normal_e,shadow_vec);
}
else
{
lc.primary = color.rgb;
lc.specular = vec3(0);
}
bool use_texture = bool( upi.in_usage & USAGE_BVEC_SAMPLER );
bool use_rot = bool( upi.in_usage & USAGE_BVEC_ROT );
const bool do_reflection = front_facing && can_refl && color.a < 0;
if ( use_texture )
{
vec3 c_g = vec3( mat4(gl_ObjectToWorldNV) * vec4(c_o,1) );
vec3 normal_g = vertex_g.xyz - c_g;
vec3 sur_l = normal_o;
if ( use_rot ) sur_l = transpose(mat3(MIX(rot))) * sur_l;
sur_l = normalize(sur_l);
float pi = 3.14159265359;
float tpi = 2 * pi;
float theta = atan(sur_l.x,sur_l.z);
float eta = acos(sur_l.y);
vec2 tcoord = vec2( ( 1.5f * pi + theta ) / tpi, eta / pi );
float dang = 0.01;
float sin_dang = dang;
float cos_dang = sqrt(1-sin_dang*sin_dang);
mat3 rot_th =
mat3( vec3( cos_dang, 0, sin_dang ),
vec3( 0, 1, 0 ),
vec3( -sin_dang, 0, cos_dang ) );
mat3 rot_et =
mat3( vec3( cos_dang, sin_dang, 0 ),
vec3( -sin_dang, cos_dang, 0 ),
vec3( 0, 0 , 1 ) );
vec2 win_dim_px = gl_LaunchSizeNV.xy;
vec2 tex_dim_px = textureSize(textureSamplers[ii],0);
vec3 norm_g1 = rot_th * normal_g;
vec3 norm_g2 = rot_et * normal_g;
vec4 vtx_g1 = vec4( c_g + norm_g1, 1 );
vec4 vtx_g2 = vec4( c_g + norm_g2, 1 );
vec2 vtx_c = homogenize( ut.clip_from_object * vertex_g ).xy;
vec2 vtx_c1 = homogenize( ut.clip_from_object * vtx_g1 ).xy;
vec2 vtx_c2 = homogenize( ut.clip_from_object * vtx_g2 ).xy;
vec2 vtx_p = 0.5f * win_dim_px * vtx_c.xy;
vec2 vtx_p1 = 0.5f * win_dim_px * vtx_c1;
vec2 vtx_p2 = 0.5f * win_dim_px * vtx_c2;
float dist_1_p = distance(vtx_p,vtx_p1);
float dist_2_p = distance(vtx_p,vtx_p2);
float dist_tex_1_t = tex_dim_px.x * dang / tpi;
float dist_tex_2_t = tex_dim_px.y * dang / pi;
float scale = dist_1_p > dist_2_p
? dist_tex_1_t / dist_1_p : dist_tex_2_t / dist_2_p;
float lod = log2( scale );
vec3 texel = textureLod(textureSamplers[ii], tcoord, lod).xyz;
lc.primary *= texel;
color_tex *= texel;
if ( do_reflection )
lc.specular *= 1.0f - color_tex;
}
vec3 c = lc.primary + lc.specular;
if ( do_reflection )
{
vec3 ray_gn = normalize(gl_WorldRayDirectionNV);
const vec3 normal_gn = normalize( normal_g );
float phase = dot( normal_gn, ray_gn );
vec3 ray_refl = ray_gn - 2 * phase * normal_gn;
float tmin = 0.001, tmax = 1000;
float blend_factor = -color.a;
rp_color.rgb = vec3(0);
traceNV
( topLevelAS, gl_RayFlagsOpaqueNV,
0xff,
0, 0, 0, vertex_g.xyz,
tmin, ray_refl, tmax, 0 );
rp_color.rgb = mix( c, color_tex * rp_color.rgb, blend_factor );
rp_color.a = this_depth;
}
else
{
rp_color.rgb = c;
}
}
Lighted_Colors
generic_lighting_specular
(vec4 vertex_e, vec4 color, vec3 normal_er, uint shade_vec)
{
const uint ii = gl_InstanceID;
RT_Uni_Per_Instance upi = uni_per_instance_a[ii];
#ifdef LIGHTING_SPECULAR
const bool specular_lighting = upi.shininess_front != 0;
#else
const bool specular_lighting = false;
#endif
vec3 nspc_color = color.rgb * ul.cgl_LightModel.ambient.rgb;
vec3 spec_color = vec3(0);
vec3 n_ray_e = normalize(mat3(ut.eye_from_object) * gl_WorldRayDirectionNV);
vec3 v_vtx_eye_n = -n_ray_e;
float n_er_eye = dot(v_vtx_eye_n,normal_er);
vec3 normal_ef = n_er_eye < 0 ? -normal_er : normal_er;
vec3 normal_e = normalize(normal_ef);
for ( int i=0; i<cgl_MaxLights; i++ )
{
uint lv = 1 << i;
if ( ( lv & com.light_on_vec ) == 0 ) continue;
if ( ( lv & shade_vec ) != 0 ) continue;
vec4 light_pos = ul.cgl_LightSource[i].position;
vec3 v_vtx_light = light_pos.xyz - vertex_e.xyz;
float dist = length(v_vtx_light);
float dist_vl_inv = 1.0f / dist;
vec3 v_vtx_l_n = v_vtx_light * dist_vl_inv;
float d_n_vl = dot(normal_e, v_vtx_l_n);
float phase_light = max(0, d_n_vl );
vec3 ambient_light = ul.cgl_LightSource[i].ambient.rgb;
vec3 diffuse_light = ul.cgl_LightSource[i].diffuse.rgb;
float distsq = dist * dist;
float atten_inv =
ul.cgl_LightSource[i].constantAttenuation +
ul.cgl_LightSource[i].linearAttenuation * dist +
ul.cgl_LightSource[i].quadraticAttenuation * distsq;
vec3 lighted_color =
color.rgb
* ( ambient_light + phase_light * diffuse_light ) / atten_inv;
nspc_color += lighted_color;
if ( !specular_lighting || phase_light == 0 ) continue;
vec3 h = normalize( v_vtx_l_n + v_vtx_eye_n );
spec_color +=
pow(max(0.0,dot(normal_e,h)),upi.shininess_front)
* ul.cgl_LightSource[i].specular.rgb / atten_inv;
}
return Lighted_Colors(nspc_color,spec_color);
}
#endif