#ifdef DISTANT_HORIZONS

vec3 RT_SIMPLE_DH(vec3 dir, vec3 position, float roughness, float dither, float quality)
{
    vec3 rtPos = vec3(1.1);

    vec3 clipPosition = toClipSpace3(position);
    vec3 clipPosition_DH = toClipSpace3DH(position);

    vec3 direction = normalize(toClipSpace3(position + dir) - clipPosition);
    vec3 direction_DH = normalize(toClipSpace3DH(position + dir) - clipPosition_DH);

    vec3 maxLengths = (step(0.0, direction) - clipPosition) / direction;
    vec3 maxLengths_DH = (step(0.0, direction_DH) - clipPosition_DH) / direction_DH;

    float mult = min(maxLengths.x, min(maxLengths.y, maxLengths.z));
    float mult_DH = min(maxLengths_DH.x, min(maxLengths_DH.y, maxLengths_DH.z));

    vec3 stepv = direction * mult / quality;
    vec3 stepv_DH = direction_DH * mult_DH / quality;

    vec3 spos = clipPosition + stepv * dither;
    vec3 spos_DH = clipPosition_DH + stepv_DH * dither;

    float tolerance = abs(stepv.z) * 4.0;
    float tolerance_DH = abs(stepv_DH.z) * 4.0;

    for (int i = 0; i <= quality; ++i)
    {
        float depthSample = texelFetch2D(depthtex1, ivec2(spos.xy / texelSize), 0).r;
        float depthSample_DH = texelFetch2D(dhDepthTex1, ivec2(spos_DH.xy / texelSize), 0).r;
        if (depthSample < spos.z && abs(spos.z - depthSample) < tolerance && depthSample < 1.0)
        {
            rtPos = vec3(spos.xy, depthSample);
            break;
        }

        else if (depthSample_DH < spos_DH.z && abs(spos_DH.z - depthSample_DH) < tolerance_DH)
        {
            rtPos = vec3(spos_DH.xy, depthSample_DH);
            break;
        }

        spos += stepv;
        spos_DH += stepv_DH;
    }

    return rtPos;
}

#endif

vec3 RT_SIMPLE(vec3 dir, vec3 position, float roughness, float dither, float quality)
{
    vec3 rtPos = vec3(1.1);

    vec3 farthestClipPos = toClipSpace3(position + dir * clamp(length(viewVector) * 2.0, 1, far));

    if (all(greaterThan(farthestClipPos.xy, vec2(0.0))) && all(lessThan(farthestClipPos.xy, vec2(1.0))))
    {
        float sampledDepth = texture(depthtex0, farthestClipPos.xy).r;
        float currentDepth = (farthestClipPos.z * far);

        if (sampledDepth < 1.0 && currentDepth <= (sampledDepth * far))
        {
            rtPos = farthestClipPos;
        }
    }
    //  return rtPos;

    vec3 clipPosition = toClipSpace3(position);
    vec3 direction = normalize(toClipSpace3(position + dir) - clipPosition);
    vec3 maxLengths = (step(0.0, direction) - clipPosition) / direction;

    float mult = min(maxLengths.x, min(maxLengths.y, maxLengths.z));

    vec3 stepv = direction * mult / quality;
    vec3 spos = clipPosition + stepv * dither;
    float tolerance = abs(stepv.z) * 4.0;

    for (int i = 0; i <= quality; ++i)
    {

        float depthSample = texelFetch2D(depthtex1, ivec2(spos.xy / texelSize), 0).r;

        if (depthSample < spos.z && abs(spos.z - depthSample) < tolerance)
        {

            rtPos = vec3(spos.xy, depthSample);
            break;
        }
        spos += stepv;
    }

    return rtPos;
}
vec3 rotateAroundXAxis(vec3 v)
{

    float angle = radians(0.8); // convert 0.5 degrees to radians
    float c = cos(angle);
    float s = sin(angle);

    vec3 L = vec3(v.x, c * v.y - s * v.z, s * v.y + c * v.z);

    L.y += 0.005;     // Tiny Y offset to counter the tilt
    L = normalize(L); // Re-normalize just to be safe
    return L;
}

vec4 mergeSpecularLighting(
    vec3 reflectionColor,
    vec3 rayContrib, // fresnel
    vec3 specTerm,
    vec3 albedo,
    vec3 sunLight,
    vec4 scene,
    float alpha0,
    bool inWater)
{
    vec3 indirectSpecular = reflectionColor * rayContrib;
    vec3 fresnelDiffuse = rayContrib;

    vec3 specularContribution = indirectSpecular + specTerm * sunLight;
    vec3 inverseFresnel = 1.0 - fresnelDiffuse;

    float effectiveAlpha = mix(scene.a, 1.0, luma(fresnelDiffuse));

    if (inWater)
        specularContribution *= scene.a;

    vec3 baseColorCorrected = scene.rgb * alpha0 * inverseFresnel;
    vec3 outColor = (specularContribution + inverseFresnel * baseColorCorrected) * albedo;

    return vec4(outColor, effectiveAlpha);
}
