underwater caustics

This commit is contained in:
Turánszki János
2022-03-20 20:14:14 +01:00
parent 3cfbd86f46
commit b24a3e13b8
9 changed files with 56 additions and 39 deletions
+6 -4
View File
@@ -276,9 +276,9 @@ struct ShaderOcean
{
float4 water_color;
float water_height;
float patch_size;
float patch_size_rcp;
int texture_displacementmap;
int texture_gradientmap;
};
struct ShaderWeather
@@ -286,12 +286,14 @@ struct ShaderWeather
float3 sun_color;
float sun_energy;
float3 sun_direction;
float sky_exposure;
uint most_important_light_index;
float3 horizon;
float cloudiness;
float sky_exposure;
float3 zenith;
float cloud_scale;
float cloudiness;
float3 ambient;
float cloud_scale;
float3 padding;
float cloud_speed;
ShaderFog fog;
+10
View File
@@ -505,6 +505,16 @@ inline float3 reconstruct_position(in float2 uv, in float z)
return reconstruct_position(uv, z, GetCamera().inverse_view_projection);
}
// Caustic pattern from: https://www.shadertoy.com/view/XtKfRG
inline float caustic_pattern(float2 uv, float time)
{
float3 k = float3(uv, time);
float3x3 m = float3x3(-2, -1, 2, 3, -2, 1, 1, 2, 2);
float3 a = mul(k, m) * 0.5;
float3 b = mul(a, m) * 0.4;
float3 c = mul(b, m) * 0.3;
return pow(min(min(length(0.5 - frac(a)), length(0.5 - frac(b))), length(0.5 - frac(c))), 7) * 25.;
}
// Convert texture coordinates on a cubemap face to cubemap sampling coordinates:
// uv : UV texture coordinates on cubemap face in range [0, 1]
+19 -1
View File
@@ -115,7 +115,6 @@ inline float3 shadow_cube(in ShaderEntity light, in float3 L, in float3 Lunnorma
return shadow;
}
inline void light_directional(in ShaderEntity light, in Surface surface, inout Lighting lighting, in float shadow_mask = 1)
{
float3 L = light.GetDirection();
@@ -187,6 +186,25 @@ inline void light_directional(in ShaderEntity light, in Surface surface, inout L
lighting.direct.diffuse = mad(light_color, BRDF_GetDiffuse(surface, surface_to_light), lighting.direct.diffuse);
lighting.direct.specular = mad(light_color, BRDF_GetSpecular(surface, surface_to_light), lighting.direct.specular);
#ifndef WATER
const ShaderOcean ocean = GetWeather().ocean;
if (ocean.texture_displacementmap >= 0)
{
Texture2D displacementmap = bindless_textures[ocean.texture_displacementmap];
float2 ocean_uv = surface.P.xz * ocean.patch_size_rcp;
float3 displacement = displacementmap.SampleLevel(sampler_linear_wrap, ocean_uv, 0).xzy;
float water_height = ocean.water_height + displacement.y;
if (surface.P.y < water_height)
{
float3 caustic = caustic_pattern(ocean_uv * 20, GetFrame().time);
caustic *= sqr(saturate((water_height - surface.P.y) * 0.5)); // fade out at shoreline
caustic *= light_color;
lighting.indirect.diffuse += caustic;
}
}
#endif // WATER
}
}
}
+13 -9
View File
@@ -2,6 +2,7 @@
#define DISABLE_ENVMAPS
#define DISABLE_TRANSPARENT_SHADOWMAP
#define TRANSPARENT
#define WATER
#include "globals.hlsli"
#include "oceanSurfaceHF.hlsli"
#include "objectHF.hlsli"
@@ -19,6 +20,10 @@ float4 main(PSIn input) : SV_TARGET
V /= dist;
float emissive = 0;
float ocean_level_at_camera_pos = xOceanWaterHeight;
ocean_level_at_camera_pos += texture_ocean_displacementmap.SampleLevel(sampler_linear_wrap, GetCamera().position.xz * xOceanPatchSizeRecip, 0).z; // texture contains xzy!
const bool camera_above_water = GetCamera().position.y > ocean_level_at_camera_pos;
const float gradient_fade = saturate(dist * 0.001);
const float4 gradientNear = texture_gradientmap.Sample(sampler_aniso_wrap, input.uv);
const float4 gradientFar = texture_gradientmap.Sample(sampler_aniso_wrap, input.uv * 0.125);
@@ -31,7 +36,7 @@ float4 main(PSIn input) : SV_TARGET
surface.pixel = input.pos.xy;
float depth = input.pos.z;
surface.albedo = color.rgb;
surface.f0 = 0.02;
surface.f0 = camera_above_water ? 0.02 : 0.1;
surface.roughness = 0.1;
surface.P = input.pos3D;
surface.N = normalize(float3(gradient.x, xOceanTexelLength * 2, gradient.y));
@@ -46,6 +51,7 @@ float4 main(PSIn input) : SV_TARGET
TiledLighting(surface, lighting);
float2 ScreenCoord = surface.pixel * GetCamera().internal_resolution_rcp;
const float bump_strength = camera_above_water ? 0.04 : 0.1;
[branch]
if (GetCamera().texture_reflection_index >= 0)
@@ -53,21 +59,19 @@ float4 main(PSIn input) : SV_TARGET
//REFLECTION
float4 reflectionPos = mul(GetCamera().reflection_view_projection, float4(input.pos3D, 1));
float2 reflectionUV = clipspace_to_uv(reflectionPos.xy / reflectionPos.w);
float4 reflectiveColor = bindless_textures[GetCamera().texture_reflection_index].SampleLevel(sampler_linear_mirror, reflectionUV + surface.N.xz * 0.04f, 0);
float4 reflectiveColor = bindless_textures[GetCamera().texture_reflection_index].SampleLevel(sampler_linear_mirror, reflectionUV + surface.N.xz * bump_strength, 0);
lighting.indirect.specular = reflectiveColor.rgb * surface.F;
}
[branch]
if (GetCamera().texture_refraction_index >= 0)
{
// WATER REFRACTION
// WATER REFRACTION
Texture2D texture_refraction = bindless_textures[GetCamera().texture_refraction_index];
float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + surface.N.xz * 0.04f, 0) * GetCamera().z_far;
float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + surface.N.xz * bump_strength, 0) * GetCamera().z_far;
float depth_difference = sampled_lineardepth - lineardepth;
surface.refraction.rgb = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + surface.N.xz * 0.04f * saturate(0.5 * depth_difference), 0).rgb;
float ocean_level_at_camera_pos = xOceanWaterHeight;
ocean_level_at_camera_pos += texture_ocean_displacementmap.SampleLevel(sampler_linear_wrap, GetCamera().position.xz * xOceanPatchSizeRecip, 0).z; // texture contains xzy!
if (GetCamera().position.y > ocean_level_at_camera_pos)
surface.refraction.rgb = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + surface.N.xz * bump_strength * saturate(0.5 * depth_difference), 0).rgb;
if (camera_above_water)
{
if (depth_difference < 0)
{
@@ -85,7 +89,7 @@ float4 main(PSIn input) : SV_TARGET
}
// Blend out at distance:
color.a = pow(saturate(1 - saturate(dist / GetCamera().z_far)), 2);
color.a = saturate(1 - saturate(dist / GetCamera().z_far - 0.8) * 5.0); // fade will be on edge and inwards 20%
color.a = lerp(0, color.a, saturate(pow(lineardepth, 2))); // fade when very close to camera
ApplyLighting(surface, lighting, color);
+2
View File
@@ -30,6 +30,8 @@ PSIn main(uint vertexID : SV_VertexID)
{
// Displace surface:
float3 displacement = texture_displacementmap.SampleLevel(sampler_linear_wrap, uv, 0).xzy;
float dist = length(worldPos - GetCamera().position);
displacement *= saturate(1 - saturate(dist / GetCamera().z_far - 0.8) * 5.0); // fade will be on edge and inwards 20%
worldPos += displacement;
}
+1 -22
View File
@@ -25,28 +25,7 @@ float4 main(PixelInput input) : SV_TARGET
color.rgb = 1; // disable water shadow because it has already fog
[branch]
if (GetMaterial().uvset_normalMap >= 0)
{
float3 bumpColor;
float2 bumpColor0 = 0;
float2 bumpColor1 = 0;
float2 bumpColor2 = 0;
const float2 UV_normalMap = GetMaterial().uvset_normalMap == 0 ? input.uvsets.xy : input.uvsets.zw;
bumpColor0 = 2.0f * texture_normalmap.Sample(sampler_objectshader, UV_normalMap - GetMaterial().texMulAdd.ww).rg - 1.0f;
bumpColor1 = 2.0f * texture_normalmap.Sample(sampler_objectshader, UV_normalMap + GetMaterial().texMulAdd.zw).rg - 1.0f;
bumpColor = float3(bumpColor0 + bumpColor1 + bumpColor2, 1) * GetMaterial().refraction;
bumpColor.rg *= GetMaterial().normalMapStrength;
bumpColor = normalize(max(bumpColor, float3(0, 0, 0.0001f)));
float caustic = abs(dot(bumpColor, float3(0, 1, 0)));
caustic = saturate(caustic);
caustic = pow(caustic, 2);
caustic *= 20;
color.rgb += caustic;
}
color.rgb += caustic_pattern(input.uvsets.xy * 20, GetFrame().time);
color.a = input.pos.z; // secondary depth
+2 -1
View File
@@ -1,6 +1,7 @@
#include "globals.hlsli"
#include "ShaderInterop_Postprocess.h"
#include "oceanSurfaceHF.hlsli"
#include "lightingHF.hlsli"
PUSHCONSTANT(postprocess, PostProcess);
@@ -52,7 +53,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
const float ocean_dist = length(ocean_surface_pos - o);
const float min_dist = min(lineardepth, ocean_dist);
float3 modified_color = lerp(color.rgb, ocean.water_color.rgb, saturate(0.5 + min_dist * 0.025));
float3 modified_color = lerp(color.rgb, ocean.water_color.rgb, saturate(0.5 + min_dist * 0.025 * ocean.water_color.a));
color.rgb = lerp(color.rgb, modified_color, pow(saturate(ocean_pos.y - world_pos.y), 0.25));
}
output[DTid.xy] = color;
+2 -1
View File
@@ -1862,6 +1862,7 @@ namespace wi::scene
shaderscene.weather.sun_color = weather.sunColor;
shaderscene.weather.sun_direction = weather.sunDirection;
shaderscene.weather.sun_energy = weather.sunEnergy;
shaderscene.weather.most_important_light_index = weather.most_important_light_index;
shaderscene.weather.ambient = weather.ambient;
shaderscene.weather.cloudiness = weather.cloudiness;
shaderscene.weather.cloud_scale = weather.cloudScale;
@@ -1882,9 +1883,9 @@ namespace wi::scene
shaderscene.weather.volumetric_clouds = weather.volumetricCloudParameters;
shaderscene.weather.ocean.water_color = weather.oceanParameters.waterColor;
shaderscene.weather.ocean.water_height = weather.oceanParameters.waterHeight;
shaderscene.weather.ocean.patch_size = weather.oceanParameters.patch_length;
shaderscene.weather.ocean.patch_size_rcp = 1.0f / weather.oceanParameters.patch_length;
shaderscene.weather.ocean.texture_displacementmap = device->GetDescriptorIndex(ocean.getDisplacementMap(), SubresourceType::SRV);
shaderscene.weather.ocean.texture_gradientmap = device->GetDescriptorIndex(ocean.getGradientMap(), SubresourceType::SRV);
shaderscene.ddgi.color_texture = device->GetDescriptorIndex(&ddgiColorTexture[0], SubresourceType::SRV);
shaderscene.ddgi.depth_texture = device->GetDescriptorIndex(&ddgiDepthTexture[0], SubresourceType::SRV);
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 60;
// minor bug fixes, alterations, refactors, updates
const int revision = 47;
const int revision = 48;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);