diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index 25704d34a..74dc3be3f 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -518,6 +518,7 @@ void MaterialWindow::Create(EditorComponent* _editor) colorComboBox.AddItem("Emissive color"); colorComboBox.AddItem("Subsurface color"); colorComboBox.AddItem("Sheen color"); + colorComboBox.AddItem("Extinction color"); colorComboBox.SetTooltip("Choose the destination data of the color picker."); AddWidget(&colorComboBox); @@ -550,6 +551,9 @@ void MaterialWindow::Create(EditorComponent* _editor) case 4: material->SetSheenColor(args.color.toFloat3()); break; + case 5: + material->SetExtinctionColor(args.color.toFloat4()); + break; } } }); @@ -874,6 +878,9 @@ void MaterialWindow::SetEntity(Entity entity) case 4: colorPicker.SetPickColor(wi::Color::fromFloat3(XMFLOAT3(material->sheenColor.x, material->sheenColor.y, material->sheenColor.z))); break; + case 5: + colorPicker.SetPickColor(wi::Color::fromFloat4(material->extinctionColor)); + break; } sheenRoughnessSlider.SetEnabled(false); diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index a0a241144..93584d170 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -57,6 +57,7 @@ void WeatherWindow::Create(EditorComponent* _editor) colorComboBox.AddItem("Horizon color"); colorComboBox.AddItem("Zenith color"); colorComboBox.AddItem("Ocean color"); + colorComboBox.AddItem("Ocean extinction"); colorComboBox.AddItem("Cloud color 1"); colorComboBox.AddItem("Cloud color 2"); colorComboBox.AddItem("Cloud extinction 1"); @@ -88,18 +89,21 @@ void WeatherWindow::Create(EditorComponent* _editor) weather.oceanParameters.waterColor = args.color.toFloat4(); break; case 4: - weather.volumetricCloudParameters.layerFirst.albedo = args.color.toFloat3(); + weather.oceanParameters.extinctionColor = args.color.toFloat4(); break; case 5: - weather.volumetricCloudParameters.layerSecond.albedo = args.color.toFloat3(); + weather.volumetricCloudParameters.layerFirst.albedo = args.color.toFloat3(); break; case 6: - weather.volumetricCloudParameters.layerFirst.extinctionCoefficient = args.color.toFloat3(); + weather.volumetricCloudParameters.layerSecond.albedo = args.color.toFloat3(); break; case 7: - weather.volumetricCloudParameters.layerSecond.extinctionCoefficient = args.color.toFloat3(); + weather.volumetricCloudParameters.layerFirst.extinctionCoefficient = args.color.toFloat3(); break; case 8: + weather.volumetricCloudParameters.layerSecond.extinctionCoefficient = args.color.toFloat3(); + break; + case 9: weather.rain_color = args.color.toFloat4(); break; } @@ -1093,18 +1097,21 @@ void WeatherWindow::Update() colorPicker.SetPickColor(wi::Color::fromFloat4(weather.oceanParameters.waterColor)); break; case 4: - colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerFirst.albedo)); + colorPicker.SetPickColor(wi::Color::fromFloat4(weather.oceanParameters.extinctionColor)); break; case 5: - colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerSecond.albedo)); + colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerFirst.albedo)); break; case 6: - colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerFirst.extinctionCoefficient)); + colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerSecond.albedo)); break; case 7: - colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerSecond.extinctionCoefficient)); + colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerFirst.extinctionCoefficient)); break; case 8: + colorPicker.SetPickColor(wi::Color::fromFloat3(weather.volumetricCloudParameters.layerSecond.extinctionCoefficient)); + break; + case 9: colorPicker.SetPickColor(wi::Color::fromFloat4(weather.rain_color)); break; } diff --git a/WickedEngine/shaders/ShaderInterop_Ocean.h b/WickedEngine/shaders/ShaderInterop_Ocean.h index 7892c0c85..133509458 100644 --- a/WickedEngine/shaders/ShaderInterop_Ocean.h +++ b/WickedEngine/shaders/ShaderInterop_Ocean.h @@ -31,6 +31,7 @@ CBUFFER(Ocean_Simulation_PerFrameCB, CBSLOT_OTHER_OCEAN_SIMULATION_PERFRAME) CBUFFER(Ocean_RenderCB, CBSLOT_OTHER_OCEAN_RENDER) { float4 xOceanWaterColor; + float4 xOceanExtinctionColor; float4 xOceanScreenSpaceParams; float xOceanTexelLength; diff --git a/WickedEngine/shaders/ShaderInterop_Weather.h b/WickedEngine/shaders/ShaderInterop_Weather.h index 080e1bef9..ee210a5d4 100644 --- a/WickedEngine/shaders/ShaderInterop_Weather.h +++ b/WickedEngine/shaders/ShaderInterop_Weather.h @@ -341,10 +341,13 @@ struct ShaderWind struct ShaderOcean { float4 water_color; + float4 extinction_color; float water_height; float patch_size_rcp; int texture_displacementmap; int texture_gradientmap; + + bool IsValid() { return texture_displacementmap >= 0; } }; struct ShaderWeather diff --git a/WickedEngine/shaders/globals.hlsli b/WickedEngine/shaders/globals.hlsli index 2738203da..b9cd6a88a 100644 --- a/WickedEngine/shaders/globals.hlsli +++ b/WickedEngine/shaders/globals.hlsli @@ -568,6 +568,16 @@ inline float GetTimePrev() { return GetFrame().time_previous; } inline uint2 GetTemporalAASampleRotation() { return uint2((GetFrame().temporalaa_samplerotation >> 0u) & 0x000000FF, (GetFrame().temporalaa_samplerotation >> 8) & 0x000000FF); } inline bool IsStaticSky() { return GetScene().globalenvmap >= 0; } +// Mie scaterring approximated with Henyey-Greenstein phase function. +// https://www.alexandre-pestana.com/volumetric-lights/ +#define G_SCATTERING 0.66 +float ComputeScattering(float lightDotView) +{ + float result = 1.0f - G_SCATTERING * G_SCATTERING; + result /= (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) * lightDotView, 1.5f)); + return result; +} + inline float3 tonemap(float3 x) { return x / (x + 1); // Reinhard tonemap diff --git a/WickedEngine/shaders/lightingHF.hlsli b/WickedEngine/shaders/lightingHF.hlsli index e64f4744d..01c06cb9e 100644 --- a/WickedEngine/shaders/lightingHF.hlsli +++ b/WickedEngine/shaders/lightingHF.hlsli @@ -120,7 +120,12 @@ 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 +#ifdef WATER + // Water extinction scattering: + const float scattering = ComputeScattering(saturate(dot(L, -surface.V))); + lighting.direct.specular += scattering * light_color * (1 - surface.extinction) * (1 - sqr(1 - saturate(1 - surface.N.y))); +#else + // On non-water surfaces there can be procedural caustic if it's under ocean: const ShaderOcean ocean = GetWeather().ocean; if (ocean.texture_displacementmap >= 0) { diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 82ba61863..8a70e30bc 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -828,10 +828,13 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_Target #endif // OBJECTSHADER_USE_UVSETS #endif // CLEARCOAT - surface.sss = GetMaterial().subsurfaceScattering; surface.sss_inv = GetMaterial().subsurfaceScattering_inv; +#ifdef WATER + surface.extinction = GetMaterial().GetSheenColor().rgb; // Note: sheen color is repurposed as extinction color for water +#endif // WATER + surface.pixel = pixel; surface.screenUV = ScreenCoord; @@ -996,7 +999,10 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_Target if(camera_above_water) water_depth = -water_depth; // Water fog computation: - surface.refraction.a = saturate(exp(-water_depth * color.a)); + float waterfog = saturate(exp(-water_depth * color.a)); + float3 transmittance = saturate(exp(-water_depth * surface.extinction * color.a)); + surface.refraction.a = waterfog; + surface.refraction.rgb *= transmittance; color.a = 1; } #endif // WATER diff --git a/WickedEngine/shaders/oceanSurfacePS.hlsl b/WickedEngine/shaders/oceanSurfacePS.hlsl index df721cb26..51fc0fd60 100644 --- a/WickedEngine/shaders/oceanSurfacePS.hlsl +++ b/WickedEngine/shaders/oceanSurfacePS.hlsl @@ -25,7 +25,6 @@ float4 main(PSIn input) : SV_TARGET const float4 gradientNear = texture_gradientmap.Sample(sampler_aniso_wrap, input.uv); const float4 gradientFar = texture_gradientmap.Sample(sampler_aniso_wrap, input.uv * 0.125); float4 gradient = lerp(gradientNear, gradientFar, gradient_fade); - const float sss_amount = gradient.a; float2 ScreenCoord = pixel * GetCamera().internal_resolution_rcp; @@ -46,8 +45,9 @@ float4 main(PSIn input) : SV_TARGET surface.P = input.pos3D; surface.N = normalize(float3(gradient.x, xOceanTexelLength * 2, gradient.y)); surface.V = V; - //surface.sss = color * sss_amount; - //surface.sss_inv = 1.0f / ((1 + surface.sss) * (1 + surface.sss)); + surface.sss = 1; + surface.sss_inv = 1.0f / ((1 + surface.sss) * (1 + surface.sss)); + surface.extinction = xOceanExtinctionColor.rgb; surface.update(); Lighting lighting; @@ -113,13 +113,18 @@ float4 main(PSIn input) : SV_TARGET if (camera_above_water) water_depth = -water_depth; // Water fog computation: - surface.refraction.a = saturate(exp(-water_depth * color.a)); + float waterfog = saturate(exp(-water_depth * color.a)); + float3 transmittance = saturate(exp(-water_depth * surface.extinction * color.a)); + surface.refraction.a = waterfog; + surface.refraction.rgb *= transmittance; color.a = 1; } - + #if 1 // FOAM: float foam_shore = saturate(exp(-water_depth * 4)); + float foam_wave = pow(saturate(gradient.a), 4) * saturate(exp(-water_depth * 0.1)); + float foam_combined = saturate(foam_shore + foam_wave); float foam_simplex = 0; foam_simplex += smoothstep(0, 0.8, noise_simplex_2D(surface.P.xz * 1 + GetTime())); foam_simplex += smoothstep(0, 0.8, noise_simplex_2D(surface.P.xz * 2 + GetTime())); @@ -129,8 +134,8 @@ float4 main(PSIn input) : SV_TARGET foam_voronoi += smoothstep(0.5, 0.8, noise_voronoi(surface.P.xz * 2, GetTime()).x); foam_voronoi += smoothstep(0.5, 0.8, noise_voronoi(surface.P.xz * 4, GetTime()).x); float foam = 0; - foam += foam_voronoi * foam_simplex * foam_shore; - foam += smoothstep(0.5, 0.6, foam_shore + 0.2); + foam += foam_voronoi * foam_simplex * foam_combined; + foam += smoothstep(0.5, 0.6, saturate(foam_combined + 0.2)); foam *= 2; foam = saturate(foam); surface.albedo = lerp(surface.albedo, 1, foam); diff --git a/WickedEngine/shaders/skyPS_dynamic.hlsl b/WickedEngine/shaders/skyPS_dynamic.hlsl index 259528e1a..3987d8da1 100644 --- a/WickedEngine/shaders/skyPS_dynamic.hlsl +++ b/WickedEngine/shaders/skyPS_dynamic.hlsl @@ -4,14 +4,6 @@ #include "skyHF.hlsli" #include "fogHF.hlsli" -#define G_SCATTERING 0.66 -float ComputeScattering(float lightDotView) -{ - float result = 1.0f - G_SCATTERING * G_SCATTERING; - result /= (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) * lightDotView, 1.5f)); - return result; -} - float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET { float4 unprojected = mul(GetCamera().inverse_view_projection, float4(clipspace, 0.0f, 1.0f)); diff --git a/WickedEngine/shaders/surfaceHF.hlsli b/WickedEngine/shaders/surfaceHF.hlsli index ff72c76d2..4cc72022f 100644 --- a/WickedEngine/shaders/surfaceHF.hlsli +++ b/WickedEngine/shaders/surfaceHF.hlsli @@ -99,6 +99,7 @@ struct Surface float3 gi; float3 bumpColor; float3 ssgi; + float3 extinction; // These will be computed when calling Update(): float NdotV; // cos(angle between normal and view vector) @@ -147,6 +148,7 @@ struct Surface gi = 0; bumpColor = 0; ssgi = 0; + extinction = 0; uid_validate = 0; hit_depth = 0; diff --git a/WickedEngine/shaders/underwaterCS.hlsl b/WickedEngine/shaders/underwaterCS.hlsl index f9e02d2ae..7663a7dab 100644 --- a/WickedEngine/shaders/underwaterCS.hlsl +++ b/WickedEngine/shaders/underwaterCS.hlsl @@ -66,8 +66,11 @@ void main(uint3 DTid : SV_DispatchThreadID) } float water_depth = ocean_pos.y - surface_position.y; water_depth = max(min(lineardepth, ocean_dist), water_depth); - - color.rgb = lerp(ocean.water_color.rgb, color.rgb, saturate(exp(-water_depth * ocean.water_color.a))); + + float waterfog = saturate(exp(-water_depth * ocean.water_color.a)); + float3 transmittance = saturate(exp(-water_depth * ocean.extinction_color.rgb * ocean.water_color.a)); + color.rgb *= transmittance; + color.rgb = lerp(ocean.water_color.rgb, color.rgb, waterfog); //color = float4(1, 0, 0, 1); } diff --git a/WickedEngine/shaders/volumetricLightHF.hlsli b/WickedEngine/shaders/volumetricLightHF.hlsli index 837c7fd51..5385f5996 100644 --- a/WickedEngine/shaders/volumetricLightHF.hlsli +++ b/WickedEngine/shaders/volumetricLightHF.hlsli @@ -9,14 +9,4 @@ struct VertexToPixel { float4 pos2D : POSITION2D; }; -// Mie scaterring approximated with Henyey-Greenstein phase function. -// https://www.alexandre-pestana.com/volumetric-lights/ -#define G_SCATTERING 0.66 -float ComputeScattering(float lightDotView) -{ - float result = 1.0f - G_SCATTERING * G_SCATTERING; - result /= (4.0f * PI * pow(1.0f + G_SCATTERING * G_SCATTERING - (2.0f * G_SCATTERING) * lightDotView, 1.5f)); - return result; -} - #endif // WI_VOLUMETRICLIGHT_HF diff --git a/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl b/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl index ada0660f9..8e0a24f32 100644 --- a/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl @@ -3,17 +3,12 @@ #include "volumetricLightHF.hlsli" #include "volumetricCloudsHF.hlsli" #include "fogHF.hlsli" +#include "oceanSurfaceHF.hlsli" float4 main(VertexToPixel input) : SV_TARGET { ShaderEntity light = load_entity(GetFrame().lightarray_offset + (uint)g_xColor.x); - - if (!light.IsCastingShadow()) - { - // Dirlight volume has no meaning without shadows!! - return 0; - } - + float2 ScreenCoord = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; float4 depths = texture_depth.GatherRed(sampler_point_clamp, ScreenCoord); float depth = max(depths.x, max(depths.y, max(depths.z, depths.w))); @@ -22,6 +17,19 @@ float4 main(VertexToPixel input) : SV_TARGET float cameraDistance = length(V); V /= cameraDistance; + // Fix for ocean: because ocean is not in linear depth, we trace it instead + const ShaderOcean ocean = GetWeather().ocean; + if(ocean.IsValid() && V.y > 0) + { + float3 ocean_surface_pos = intersectPlaneClampInfinite(GetCamera().position, V, float3(0, 1, 0), ocean.water_height); + float dist = distance(ocean_surface_pos, GetCamera().position); + if(dist < cameraDistance) + { + P = ocean_surface_pos; + cameraDistance = dist; + } + } + float marchedDistance = 0; float3 accumulation = 0; diff --git a/WickedEngine/shaders/volumetricLight_PointPS.hlsl b/WickedEngine/shaders/volumetricLight_PointPS.hlsl index ce498e560..eaba99ecf 100644 --- a/WickedEngine/shaders/volumetricLight_PointPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_PointPS.hlsl @@ -2,6 +2,7 @@ #define TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK // fix the lack of depth testing #include "volumetricLightHF.hlsli" #include "fogHF.hlsli" +#include "oceanSurfaceHF.hlsli" float4 main(VertexToPixel input) : SV_TARGET { @@ -15,6 +16,19 @@ float4 main(VertexToPixel input) : SV_TARGET float cameraDistance = length(V); V /= cameraDistance; + // Fix for ocean: because ocean is not in linear depth, we trace it instead + const ShaderOcean ocean = GetWeather().ocean; + if(ocean.IsValid() && V.y > 0) + { + float3 ocean_surface_pos = intersectPlaneClampInfinite(GetCamera().position, V, float3(0, 1, 0), ocean.water_height); + float dist = distance(ocean_surface_pos, GetCamera().position); + if(dist < cameraDistance) + { + P = ocean_surface_pos; + cameraDistance = dist; + } + } + float marchedDistance = 0; float3 accumulation = 0; diff --git a/WickedEngine/shaders/volumetricLight_SpotPS.hlsl b/WickedEngine/shaders/volumetricLight_SpotPS.hlsl index 3564daa0b..852aa41b5 100644 --- a/WickedEngine/shaders/volumetricLight_SpotPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_SpotPS.hlsl @@ -2,6 +2,7 @@ #define TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK // fix the lack of depth testing #include "volumetricLightHF.hlsli" #include "fogHF.hlsli" +#include "oceanSurfaceHF.hlsli" // https://github.com/dong-zhan/ray-tracer/blob/master/ray%20cone%20intersect.hlsl //p: ray o @@ -47,6 +48,19 @@ float4 main(VertexToPixel input) : SV_TARGET float cameraDistance = length(V); V /= cameraDistance; + // Fix for ocean: because ocean is not in linear depth, we trace it instead + const ShaderOcean ocean = GetWeather().ocean; + if(ocean.IsValid() && V.y > 0) + { + float3 ocean_surface_pos = intersectPlaneClampInfinite(GetCamera().position, V, float3(0, 1, 0), ocean.water_height); + float dist = distance(ocean_surface_pos, GetCamera().position); + if(dist < cameraDistance) + { + P = ocean_surface_pos; + cameraDistance = dist; + } + } + float marchedDistance = 0; float3 accumulation = 0; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index db6b5f80c..8d3d01672 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -4487,6 +4487,7 @@ using namespace vulkan_internal; } copyOffset += dst_slicepitch * depth; + copyOffset = AlignTo(copyOffset, VkDeviceSize(4)); // fix for validation: on transfer queue the srcOffset must be 4-byte aligned width = std::max(1u, width / 2); height = std::max(1u, height / 2); diff --git a/WickedEngine/wiOcean.cpp b/WickedEngine/wiOcean.cpp index 736d4f981..455cb7b9e 100644 --- a/WickedEngine/wiOcean.cpp +++ b/WickedEngine/wiOcean.cpp @@ -368,12 +368,7 @@ namespace wi device->BindResources(cs_srvs, 0, 1, cmd); device->Barrier(GPUBarrier::Image(&displacementMap, displacementMap.desc.layout, ResourceState::UNORDERED_ACCESS), cmd); device->Dispatch(params.dmap_dim / OCEAN_COMPUTE_TILESIZE, params.dmap_dim / OCEAN_COMPUTE_TILESIZE, 1, cmd); - device->Barrier(GPUBarrier::Image(&displacementMap, ResourceState::UNORDERED_ACCESS, ResourceState::COPY_SRC), cmd); - - device->CopyResource(&displacementMap_readback[displacement_readback_index], &displacementMap, cmd); - displacement_readback_valid[displacement_readback_index] = true; - displacement_readback_index = (displacement_readback_index + 1) % device->GetBufferCount(); - device->Barrier(GPUBarrier::Image(&displacementMap, ResourceState::COPY_SRC, displacementMap.desc.layout), cmd); + device->Barrier(GPUBarrier::Image(&displacementMap, ResourceState::UNORDERED_ACCESS, displacementMap.desc.layout), cmd); // Update gradient map: device->BindComputeShader(&updateGradientFoldingCS, cmd); @@ -381,22 +376,18 @@ namespace wi device->BindUAVs(cs_uavs, 0, 1, cmd); cs_srvs[0] = &displacementMap; device->BindResources(cs_srvs, 0, 1, cmd); - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&gradientMap, gradientMap.desc.layout, ResourceState::UNORDERED_ACCESS), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } + device->Barrier(GPUBarrier::Image(&gradientMap, gradientMap.desc.layout, ResourceState::UNORDERED_ACCESS), cmd); device->Dispatch(params.dmap_dim / OCEAN_COMPUTE_TILESIZE, params.dmap_dim / OCEAN_COMPUTE_TILESIZE, 1, cmd); - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&gradientMap, ResourceState::UNORDERED_ACCESS, gradientMap.desc.layout), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } + device->Barrier(GPUBarrier::Image(&gradientMap, ResourceState::UNORDERED_ACCESS, gradientMap.desc.layout), cmd); wi::renderer::GenerateMipChain(gradientMap, wi::renderer::MIPGENFILTER_LINEAR, cmd); + device->Barrier(GPUBarrier::Image(&displacementMap, displacementMap.desc.layout, ResourceState::COPY_SRC), cmd); + device->CopyResource(&displacementMap_readback[displacement_readback_index], &displacementMap, cmd); + displacement_readback_valid[displacement_readback_index] = true; + displacement_readback_index = (displacement_readback_index + 1) % device->GetBufferCount(); + device->Barrier(GPUBarrier::Image(&displacementMap, ResourceState::COPY_SRC, displacementMap.desc.layout), cmd); + device->EventEnd(cmd); } @@ -455,6 +446,7 @@ namespace wi Ocean_RenderCB cb; cb.xOceanWaterColor = params.waterColor; + cb.xOceanExtinctionColor = XMFLOAT4(1 - params.extinctionColor.x, 1 - params.extinctionColor.y, 1 - params.extinctionColor.z, 1); cb.xOceanTexelLength = params.patch_length / params.dmap_dim; cb.xOceanScreenSpaceParams = XMFLOAT4((float)dim.x, (float)dim.y, 1.0f / (float)dim.x, 1.0f / (float)dim.y); cb.xOceanPatchSizeRecip = 1.0f / params.patch_length; diff --git a/WickedEngine/wiOcean.h b/WickedEngine/wiOcean.h index c6e278fbd..beb2e2cef 100644 --- a/WickedEngine/wiOcean.h +++ b/WickedEngine/wiOcean.h @@ -32,7 +32,8 @@ namespace wi float choppy_scale = 1.3f; - XMFLOAT4 waterColor = XMFLOAT4(0.0f, 3.0f / 255.0f, 31.0f / 255.0f, 1); + XMFLOAT4 waterColor = XMFLOAT4(0.0f, 2.0f / 255.0f, 6.0f / 255.0f, 0.6f); + XMFLOAT4 extinctionColor = XMFLOAT4(0, 0.9f, 1, 1); float waterHeight = 0.0f; uint32_t surfaceDetail = 4; float surfaceDisplacementTolerance = 2; diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 5e07650c0..b509bc3e9 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -1331,6 +1331,14 @@ namespace wi }); } + if (scene->weather.IsOceanEnabled()) + { + // Ocean simulation can be updated async to opaque passes: + CommandList cmd_ocean = device->BeginCommandList(QUEUE_COMPUTE); + device->WaitCommandList(cmd_ocean, cmd); + wi::renderer::UpdateOcean(visibility_main, cmd_ocean); + } + // Main camera opaque color pass: cmd = device->BeginCommandList(); device->WaitCommandList(cmd, cmd_maincamera_compute_effects); @@ -1968,6 +1976,14 @@ namespace wi vp.max_depth = 1; device->BindViewports(1, &vp, cmd); + // Draw only the ocean first, fog and lightshafts will be blended on top: + wi::renderer::DrawScene( + visibility_main, + RENDERPASS_MAIN, + cmd, + wi::renderer::DRAWSCENE_OCEAN + ); + // Note: volumetrics and light shafts are blended before transparent scene, because they used depth of the opaques if (getVolumeLightsEnabled() && visibility_main.IsRequestedVolumetricLights()) @@ -2024,7 +2040,6 @@ namespace wi wi::renderer::DRAWSCENE_TRANSPARENT | wi::renderer::DRAWSCENE_TESSELLATION | wi::renderer::DRAWSCENE_OCCLUSIONCULLING | - wi::renderer::DRAWSCENE_OCEAN | wi::renderer::DRAWSCENE_MAINCAMERA ); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 55918188f..7026bf136 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -4731,22 +4731,6 @@ void UpdateRenderDataAsync( wi::profiler::EndRange(range); } - // Compute water simulation: - if (vis.scene->weather.IsOceanEnabled()) - { - bool occluded = false; - if (vis.flags & Visibility::ALLOW_OCCLUSION_CULLING) - { - occluded = vis.scene->ocean.IsOccluded(); - } - if (!occluded) - { - auto range = wi::profiler::BeginRangeGPU("Ocean - Simulate", cmd); - vis.scene->ocean.UpdateDisplacementMap(cmd); - wi::profiler::EndRange(range); - } - } - for (size_t i = 0; i < vis.scene->terrains.GetCount(); ++i) { vis.scene->terrains[i].UpdateVirtualTexturesGPU(cmd); @@ -4776,6 +4760,25 @@ void TextureStreamingReadbackCopy( } } +void UpdateOcean( + const Visibility& vis, + CommandList cmd +) +{ + bool occluded = false; + if (vis.flags & wi::renderer::Visibility::ALLOW_OCCLUSION_CULLING) + { + occluded = vis.scene->ocean.IsOccluded(); + } + if (!occluded) + { + auto range = wi::profiler::BeginRangeGPU("Ocean - Simulate", cmd); + wi::renderer::BindCommonResources(cmd); + vis.scene->ocean.UpdateDisplacementMap(cmd); + wi::profiler::EndRange(range); + } +} + void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) { if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING)) @@ -6206,42 +6209,45 @@ void DrawScene( filterMask = FILTER_ALL; } - static thread_local RenderQueue renderQueue; - renderQueue.init(); - for (uint32_t instanceIndex : vis.visibleObjects) + if (opaque || transparent) { - if (occlusion && vis.scene->occlusion_results_objects[instanceIndex].IsOccluded()) - continue; - - const ObjectComponent& object = vis.scene->objects[instanceIndex]; - if (!object.IsRenderable()) - continue; - if (foreground != object.IsForeground()) - continue; - if (maincamera && object.IsNotVisibleInMainCamera()) - continue; - if (skip_planar_reflection_objects && object.IsNotVisibleInReflections()) - continue; - if ((object.GetFilterMask() & filterMask) == 0) - continue; - - const float distance = wi::math::Distance(vis.camera->Eye, object.center); - if (distance > object.fadeDistance + object.radius) - continue; - - renderQueue.add(object.mesh_index, instanceIndex, distance, object.sort_bits); - } - if (!renderQueue.empty()) - { - if (transparent) + static thread_local RenderQueue renderQueue; + renderQueue.init(); + for (uint32_t instanceIndex : vis.visibleObjects) { - renderQueue.sort_transparent(); + if (occlusion && vis.scene->occlusion_results_objects[instanceIndex].IsOccluded()) + continue; + + const ObjectComponent& object = vis.scene->objects[instanceIndex]; + if (!object.IsRenderable()) + continue; + if (foreground != object.IsForeground()) + continue; + if (maincamera && object.IsNotVisibleInMainCamera()) + continue; + if (skip_planar_reflection_objects && object.IsNotVisibleInReflections()) + continue; + if ((object.GetFilterMask() & filterMask) == 0) + continue; + + const float distance = wi::math::Distance(vis.camera->Eye, object.center); + if (distance > object.fadeDistance + object.radius) + continue; + + renderQueue.add(object.mesh_index, instanceIndex, distance, object.sort_bits); } - else + if (!renderQueue.empty()) { - renderQueue.sort_opaque(); + if (transparent) + { + renderQueue.sort_transparent(); + } + else + { + renderQueue.sort_opaque(); + } + RenderMeshes(vis, renderQueue, renderPass, filterMask, cmd, flags); } - RenderMeshes(vis, renderQueue, renderPass, filterMask, cmd, flags); } if (impostor) diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 348aa5a2a..6185b034a 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -200,6 +200,12 @@ namespace wi::renderer wi::graphics::CommandList cmd ); + // Updates the ocean, can be on async compute + void UpdateOcean( + const Visibility& vis, + wi::graphics::CommandList cmd + ); + void UpdateRaytracingAccelerationStructures(const wi::scene::Scene& scene, wi::graphics::CommandList cmd); // Binds all common constant buffers and samplers that may be used in all shaders diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 21ba08aed..ecce2ff1c 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -955,6 +955,7 @@ namespace wi::scene shaderscene.weather.atmosphere = weather.atmosphereParameters; shaderscene.weather.volumetric_clouds = weather.volumetricCloudParameters; shaderscene.weather.ocean.water_color = weather.oceanParameters.waterColor; + shaderscene.weather.ocean.extinction_color = XMFLOAT4(1 - weather.oceanParameters.extinctionColor.x, 1 - weather.oceanParameters.extinctionColor.y, 1 - weather.oceanParameters.extinctionColor.z, 1); shaderscene.weather.ocean.water_height = weather.oceanParameters.waterHeight; shaderscene.weather.ocean.patch_size_rcp = 1.0f / weather.oceanParameters.patch_length; shaderscene.weather.ocean.texture_displacementmap = device->GetDescriptorIndex(ocean.getDisplacementMap(), SubresourceType::SRV); diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 91a131008..fbea6fc4e 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -32,7 +32,7 @@ namespace wi::scene wi::ecs::ComponentManager& layers = componentLibrary.Register("wi::scene::Scene::layers"); wi::ecs::ComponentManager& transforms = componentLibrary.Register("wi::scene::Scene::transforms"); wi::ecs::ComponentManager& hierarchy = componentLibrary.Register("wi::scene::Scene::hierarchy"); - wi::ecs::ComponentManager& materials = componentLibrary.Register("wi::scene::Scene::materials", 4); // version = 4 + wi::ecs::ComponentManager& materials = componentLibrary.Register("wi::scene::Scene::materials", 5); // version = 5 wi::ecs::ComponentManager& meshes = componentLibrary.Register("wi::scene::Scene::meshes", 3); // version = 3 wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects", 3); // version = 3 @@ -48,7 +48,7 @@ namespace wi::scene wi::ecs::ComponentManager& animation_datas = componentLibrary.Register("wi::scene::Scene::animation_datas"); wi::ecs::ComponentManager& emitters = componentLibrary.Register("wi::scene::Scene::emitters"); wi::ecs::ComponentManager& hairs = componentLibrary.Register("wi::scene::Scene::hairs"); - wi::ecs::ComponentManager& weathers = componentLibrary.Register("wi::scene::Scene::weathers", 5); // version = 5 + wi::ecs::ComponentManager& weathers = componentLibrary.Register("wi::scene::Scene::weathers", 6); // version = 6 wi::ecs::ComponentManager& sounds = componentLibrary.Register("wi::scene::Scene::sounds", 1); // version = 1 wi::ecs::ComponentManager& videos = componentLibrary.Register("wi::scene::Scene::videos"); wi::ecs::ComponentManager& inverse_kinematics = componentLibrary.Register("wi::scene::Scene::inverse_kinematics"); diff --git a/WickedEngine/wiScene_Components.cpp b/WickedEngine/wiScene_Components.cpp index e2046a6a5..326e29011 100644 --- a/WickedEngine/wiScene_Components.cpp +++ b/WickedEngine/wiScene_Components.cpp @@ -292,7 +292,14 @@ namespace wi::scene material.subsurfaceScattering = sss; material.subsurfaceScattering_inv = sss_inv; - material.sheenColor_r11g11b10 = wi::math::Pack_R11G11B10_FLOAT(XMFLOAT3(sheenColor.x, sheenColor.y, sheenColor.z)); + if (shaderType == SHADERTYPE_WATER) + { + material.sheenColor_r11g11b10 = wi::math::Pack_R11G11B10_FLOAT(XMFLOAT3(1 - extinctionColor.x, 1 - extinctionColor.y, 1 - extinctionColor.z)); + } + else + { + material.sheenColor_r11g11b10 = wi::math::Pack_R11G11B10_FLOAT(XMFLOAT3(sheenColor.x, sheenColor.y, sheenColor.z)); + } material.sheenRoughness = sheenRoughness; material.clearcoat = clearcoat; material.clearcoatRoughness = clearcoatRoughness; diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 2c42485c4..4efc7202a 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -173,6 +173,7 @@ namespace wi::scene XMFLOAT4 specularColor = XMFLOAT4(1, 1, 1, 1); XMFLOAT4 emissiveColor = XMFLOAT4(1, 1, 1, 0); XMFLOAT4 subsurfaceScattering = XMFLOAT4(1, 1, 1, 0); + XMFLOAT4 extinctionColor = XMFLOAT4(0, 0.9f, 1, 1); XMFLOAT4 texMulAdd = XMFLOAT4(1, 1, 0, 0); float roughness = 0.2f; float reflectance = 0.02f; @@ -312,6 +313,11 @@ namespace wi::scene sheenColor = XMFLOAT4(value.x, value.y, value.z, sheenColor.w); SetDirty(); } + inline void SetExtinctionColor(const XMFLOAT4& value) + { + extinctionColor = XMFLOAT4(value.x, value.y, value.z, value.w); + SetDirty(); + } inline void SetSheenRoughness(float value) { sheenRoughness = value; SetDirty(); } inline void SetClearcoatFactor(float value) { clearcoat = value; SetDirty(); } inline void SetClearcoatRoughness(float value) { clearcoatRoughness = value; SetDirty(); } diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 089f43229..65a2b883c 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -236,11 +236,14 @@ namespace wi::scene archive >> textures[TRANSPARENCYMAP].name; archive >> textures[TRANSPARENCYMAP].uvset; } - if (seri.GetVersion() >= 4) { archive >> blend_with_terrain_height; } + if (seri.GetVersion() >= 5) + { + archive >> extinctionColor; + } for (auto& x : textures) { @@ -386,11 +389,14 @@ namespace wi::scene archive << wi::helper::GetPathRelative(dir, textures[TRANSPARENCYMAP].name); archive << textures[TRANSPARENCYMAP].uvset; } - if (seri.GetVersion() >= 4) { archive << blend_with_terrain_height; } + if (seri.GetVersion() >= 5) + { + archive << extinctionColor; + } } } void MeshComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) @@ -1565,6 +1571,10 @@ namespace wi::scene archive >> rain_splash_scale; archive >> rain_color; } + if (seri.GetVersion() >= 6) + { + archive >> oceanParameters.extinctionColor; + } } else { @@ -1785,6 +1795,10 @@ namespace wi::scene archive << rain_splash_scale; archive << rain_color; } + if (seri.GetVersion() >= 6) + { + archive << oceanParameters.extinctionColor; + } } } void SoundComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index f6878bf1c..f6cc45a70 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 505; + const int revision = 506; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);