engine/bin/data/shaders/common/rt.h

261 lines
8.8 KiB
C

// RT
RayTracePayload payload;
void populateSurface( RayTracePayload payload );
void directLighting();
void trace( Ray ray, float tMin, float tMax ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
payload.hit = false;
surface.position.eye.z = tMax;
// traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery));
payload.hit = rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
payload.instanceID = rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true); //rayQueryGetIntersectionInstanceIdEXT(rayQuery, true);
payload.primitiveID = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
payload.attributes = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
}
void trace( Ray ray, float tMin ) {
uint rayFlags = gl_RayFlagsOpaqueEXT;
uint cullMask = 0xFF;
float tMax = ubo.settings.rt.defaultRayBounds.y;
payload.hit = false;
surface.position.eye.z = tMax;
// traceRayEXT(tlas, rayFlags, cullMask, 0, 0, 0, ray.origin, tMin, ray.direction, tMax, 0);
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery));
payload.hit = rayQueryGetIntersectionTypeEXT(rayQuery, true) != gl_RayQueryCommittedIntersectionNoneEXT;
payload.instanceID = rayQueryGetIntersectionInstanceCustomIndexEXT(rayQuery, true); //rayQueryGetIntersectionInstanceIdEXT(rayQuery, true);
payload.primitiveID = rayQueryGetIntersectionPrimitiveIndexEXT(rayQuery, true);
payload.attributes = rayQueryGetIntersectionBarycentricsEXT(rayQuery, true);
}
void trace( Ray ray ) {
trace( ray, ubo.settings.rt.defaultRayBounds.x, ubo.settings.rt.defaultRayBounds.y );
}
vec4 traceStep( Ray ray ) {
Surface previousSurface = surface;
float eyeDepth = 0;
vec4 outFrag = vec4(0);
// initial condition
{
trace( ray );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
} else {
surface.fragment = vec4(ubo.settings.lighting.ambient.rgb, 0.5);
}
#if FOG
fog( ray, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag = surface.fragment;
eyeDepth = surface.position.eye.z;
}
#if 0
// "transparency"
if ( payload.hit && surface.material.albedo.a < 0.999 ) {
const vec4 TRANSPARENCY_COLOR = vec4(1.0 - surface.material.albedo.a);
if ( surface.material.albedo.a < 0.001 ) outFrag = vec4(0);
RayTracePayload surfacePayload = payload;
Ray transparency;
transparency.direction = ray.direction;
transparency.origin = surface.position.world;
fogRay = transparency;
trace( transparency, ubo.settings.rt.alphaTestOffset );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], ray.direction );
surface.fragment.a = 4096;
surface.position.eye.z /= 8;
}
#if FOG
fog( transparency, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += TRANSPARENCY_COLOR * surface.fragment;
eyeDepth = surface.position.eye.z;
payload = surfacePayload;
populateSurface( payload );
}
#if FOG
{
// surface.position.eye.z = eyeDepth;
// fog( fogRay, outFrag.rgb, outFrag.a );
// fog( ray, surface.fragment.rgb, surface.fragment.a );
}
#endif
// reflection
if ( payload.hit ) {
const float REFLECTIVITY = 1.0 - surface.material.roughness;
const vec4 REFLECTED_ALBEDO = surface.material.albedo * REFLECTIVITY;
if ( REFLECTIVITY > 0.001 ) {
RayTracePayload surfacePayload = payload;
Ray reflection;
reflection.origin = surface.position.world;
reflection.direction = reflect( ray.direction, surface.normal.world );
trace( reflection );
if ( payload.hit ) {
populateSurface( payload );
directLighting();
} else if ( 0 <= ubo.settings.lighting.indexSkybox && ubo.settings.lighting.indexSkybox < CUBEMAPS ) {
surface.fragment = texture( samplerCubemaps[ubo.settings.lighting.indexSkybox], reflection.direction );
surface.fragment.a = 4096;
}
#if FOG
fog( reflection, surface.fragment.rgb, surface.fragment.a );
#endif
outFrag += REFLECTED_ALBEDO * surface.fragment;
payload = surfacePayload;
populateSurface( payload );
}
}
#endif
surface = previousSurface;
return outFrag;
}
float shadowFactorRT( const Light light, float def ) {
Ray ray;
ray.origin = surface.position.world;
ray.direction = light.position - ray.origin;
float tMin = ubo.settings.rt.defaultRayBounds.x;
float tMax = length(ray.direction) - ubo.settings.rt.defaultRayBounds.x;
ray.direction = normalize(ray.direction);
uint rayFlags = gl_RayFlagsOpaqueEXT | gl_RayFlagsTerminateOnFirstHitEXT | gl_RayFlagsSkipClosestHitShaderEXT;
uint cullMask = 0xFF;
rayQueryEXT rayQuery;
rayQueryInitializeEXT(rayQuery, tlas, rayFlags, cullMask, ray.origin, tMin, ray.direction, tMax);
while(rayQueryProceedEXT(rayQuery));
return rayQueryGetIntersectionTypeEXT(rayQuery, true) == gl_RayQueryCommittedIntersectionNoneEXT ? 1.0 : 0.0;
}
void indirectLightingRT() {
const vec3 P = surface.position.world;
const vec3 N = surface.normal.world;
#if 1
const vec3 right = normalize(orthogonal(N));
const vec3 up = normalize(cross(right, N));
const uint CONES_COUNT = 6;
const vec3 CONES[] = {
N,
normalize(N + 0.0f * right + 0.866025f * up),
normalize(N + 0.823639f * right + 0.267617f * up),
normalize(N + 0.509037f * right + -0.7006629f * up),
normalize(N + -0.50937f * right + -0.7006629f * up),
normalize(N + -0.823639f * right + 0.267617f * up),
};
#else
const vec3 ortho = normalize(orthogonal(N));
const vec3 ortho2 = normalize(cross(ortho, N));
const vec3 corner = 0.5f * (ortho + ortho2);
const vec3 corner2 = 0.5f * (ortho - ortho2);
const uint CONES_COUNT = 9;
const vec3 CONES[] = {
N,
normalize(mix(N, ortho, 0.5)),
normalize(mix(N, -ortho, 0.5)),
normalize(mix(N, ortho2, 0.5)),
normalize(mix(N, -ortho2, 0.5)),
normalize(mix(N, corner, 0.5)),
normalize(mix(N, -corner, 0.5)),
normalize(mix(N, corner2, 0.5)),
normalize(mix(N, -corner2, 0.5)),
};
#endif
const float DIFFUSE_CONE_APERTURE = 2.0 * 0.57735f;
const float DIFFUSE_INDIRECT_FACTOR = 0; // 1.0f / float(CONES_COUNT) * 0.125f;
const float SPECULAR_CONE_APERTURE = clamp(tan(PI * 0.5f * surface.material.roughness), 0.0174533f, PI); // tan( R * PI * 0.5f * 0.1f );
const float SPECULAR_INDIRECT_FACTOR = (1.0 - surface.material.metallic) * (1.0 - surface.material.roughness); // * 0.25; // 1.0f;
vec4 indirectDiffuse = vec4(0);
vec4 indirectSpecular = vec4(0);
// outFragColor.rgb = voxelConeTrace( surface.ray, 0 ).rgb; return;
#if !VXGI
if ( DIFFUSE_INDIRECT_FACTOR > 0.0f ) {
float weight = PI * 0.25f;
for ( uint i = 0; i < CONES_COUNT; ++i ) {
Ray ray;
ray.direction = CONES[i].xyz;
ray.origin = P; // + ray.direction;
indirectDiffuse += traceStep( ray/*, DIFFUSE_CONE_APERTURE*/ ) * weight;
weight = PI * 0.15f;
}
indirectDiffuse.rgb *= surface.material.albedo.rgb;
surface.material.occlusion += 1.0 - clamp(indirectDiffuse.a, 0.0, 1.0);
// outFragColor.rgb = indirectDiffuse.rgb; return;
// outFragColor.rgb = vec3(surface.material.occlusion); return;
}
#endif
if ( SPECULAR_INDIRECT_FACTOR > 0.0f ) {
const vec3 R = reflect( normalize(P - surface.ray.origin), N );
Ray ray;
ray.direction = R;
ray.origin = P; // + ray.direction;
indirectSpecular = traceStep( ray/*, SPECULAR_CONE_APERTURE*/ );
indirectSpecular.rgb *= surface.material.albedo.rgb;
// outFragColor.rgb = indirectSpecular.rgb; return;
}
indirectDiffuse *= DIFFUSE_INDIRECT_FACTOR;
indirectSpecular *= SPECULAR_INDIRECT_FACTOR;
surface.material.indirect += indirectDiffuse + indirectSpecular;
// outFragColor.rgb = surface.material.indirect.rgb; return;
#if 1 || !VXGI
// deferred sampling doesn't have a blended albedo buffer
// in place we'll just cone trace behind the window
if ( surface.material.albedo.a < 1.0 ) {
Ray ray;
ray.direction = surface.ray.direction;
ray.origin = surface.position.world + ray.direction;
vec4 radiance = traceStep( ray/*, surface.material.albedo.a * 0.5*/ );
surface.fragment.rgb += (1.0 - surface.material.albedo.a) * radiance.rgb;
}
#endif
}