Skip to content

Commit

Permalink
[Refraction] Greatly improved (physically based and does chromatic ab…
Browse files Browse the repository at this point in the history
…erration as well)
  • Loading branch information
PanosK92 committed Oct 24, 2023
1 parent bc466a8 commit c812d4e
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 12 deletions.
62 changes: 51 additions & 11 deletions data/shaders/light_composition.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,58 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "common.hlsl"
//====================

float compute_fade_factor(float2 uv)
{
float edge_threshold = 0.05f; // how close to the edge to start fading
float2 edge_distance = min(uv, 1.0f - uv);
return saturate(min(edge_distance.x, edge_distance.y) / edge_threshold);
}

float3 refract_vector(float3 i, float3 n, float eta)
{
float cosi = dot(-i, n);
float cost2 = 1.0f - eta * eta * (1.0f - cosi * cosi);
return eta * i + (eta * cosi - sqrt(abs(cost2))) * n;
}

float3 refraction(Surface surface, float ior, float scale, float depth_bias)
{
float distance_falloff = clamp(1.0f / world_to_view(surface.position).z, -3.0f, 3.0f);
float2 refraction_normal = world_to_view(surface.normal.xyz, false).xy ;
float2 refraction_uv_offset = refraction_normal * distance_falloff * scale * max(0.0f, ior - 1.0f);
float depth_surface = get_linear_depth(surface.depth);
float depth_surface_refracted = get_linear_depth(surface.uv + refraction_uv_offset);
float is_behind = step(depth_surface - depth_bias, depth_surface_refracted);
float frame_mip_count = pass_get_f3_value().x;
float mip_level = lerp(0, frame_mip_count, surface.roughness_alpha);

return tex_frame.SampleLevel(samplers[sampler_trilinear_clamp], surface.uv + refraction_uv_offset * is_behind, mip_level).rgb;
const float chromatic_aberration_strength = 0.0012f;

float3 view_pos = world_to_view(surface.position);
float3 view_normal = world_to_view(surface.normal, false);
float3 view_dir = normalize(view_pos);

// compute refracted uv
float3 refracted_dir = refract_vector(view_dir, view_normal, 1.0f / ior);
float2 refraction_uv_offset = refracted_dir.xy * scale;
float2 refracted_uv = surface.uv + refraction_uv_offset;

// get mip level
float frame_mip_count = pass_get_f3_value().x;
float mip_level = lerp(0, frame_mip_count, surface.roughness_alpha);

// chromatic aberration
float3 color_refracted = float3(0, 0, 0);
{
float2 ca_offsets[3];
ca_offsets[0] = float2(chromatic_aberration_strength, 0.0f);
ca_offsets[1] = float2(0.0f, 0.0f);
ca_offsets[2] = float2(-chromatic_aberration_strength, 0.0f);

[unroll]
for (int i = 0; i < 3; ++i)
{
float4 sampled_color = tex_frame.SampleLevel(samplers[sampler_trilinear_clamp], refracted_uv + ca_offsets[i], mip_level);
color_refracted[i] = sampled_color[i];
}
}

// screen fade
float fade_factor = compute_fade_factor(refracted_uv);
float3 color_original = tex_frame.SampleLevel(samplers[sampler_trilinear_clamp], surface.uv, mip_level).rgb;

return lerp(color_original, color_refracted, fade_factor);
}

[numthreads(THREAD_GROUP_COUNT_X, THREAD_GROUP_COUNT_Y, 1)]
Expand Down Expand Up @@ -71,7 +111,7 @@ void mainCS(uint3 thread_id : SV_DispatchThreadID)
if (surface.is_transparent())
{
float ior = 1.33; // water
float scale = 0.1f;
float scale = 0.05f;
float depth_bias = 0.02f;
light_refraction = refraction(surface, ior, scale, depth_bias);
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/World/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ namespace Spartan
{
shared_ptr<Material> material = make_shared<Material>();
material->SetObjectName("material_water");
material->SetColor(Color(0.0f, 48.0f / 255.0f, 75.0f / 255.0f, 70.0f / 255.0f));
material->SetColor(Color(0.0f, 48.0f / 255.0f, 75.0f / 255.0f, 50.0f / 255.0f));
material->SetTexture(MaterialTexture::Normal, "project\\terrain\\water_normal_2.jpeg");
material->SetProperty(MaterialProperty::AnimateUVs, 1.0f);
material->SetProperty(MaterialProperty::RoughnessMultiplier, 0.2f); // just a bit of roughness to diffuse the sun a little
Expand Down

0 comments on commit c812d4e

Please sign in to comment.