Volumetric cloud updates (#544)
- Reprojection update - Cloud model changes - Weather map import - Local lights - Environment capture - Volumetric cloud shadow - Aerial perspective for clouds Co-authored-by: Silas Oler <silasmartins@outlook.dk>
This commit is contained in:
@@ -846,7 +846,7 @@ Describes a Force Field effector.
|
||||
- Range : float
|
||||
|
||||
#### WeatherComponent
|
||||
Describes a Rigid Body Physics object.
|
||||
Describes a Weather
|
||||
- OceanParameters : OceanParameters -- Returns a table to modify ocean parameters (if ocean is enabled)
|
||||
- AtmosphereParameters : AtmosphereParameters -- Returns a table to modify atmosphere parameters
|
||||
- VolumetricCloudParameters : VolumetricCloudParameters -- Returns a table to modify volumetric cloud parameters
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -69,6 +69,7 @@ void ComponentsWindow::Create(EditorComponent* _editor)
|
||||
newComponentCombo.AddItem("Soft Body " ICON_SOFTBODY, 17);
|
||||
newComponentCombo.AddItem("Collider " ICON_COLLIDER, 18);
|
||||
newComponentCombo.AddItem("Camera " ICON_CAMERA, 20);
|
||||
newComponentCombo.AddItem("Object " ICON_OBJECT, 21);
|
||||
newComponentCombo.OnSelect([=](wi::gui::EventArgs args) {
|
||||
newComponentCombo.SetSelectedWithoutCallback(-1);
|
||||
if (editor->translator.selected.empty())
|
||||
@@ -168,6 +169,10 @@ void ComponentsWindow::Create(EditorComponent* _editor)
|
||||
if (scene.cameras.Contains(entity))
|
||||
return;
|
||||
break;
|
||||
case 21:
|
||||
if (scene.objects.Contains(entity))
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -264,6 +269,10 @@ void ComponentsWindow::Create(EditorComponent* _editor)
|
||||
case 20:
|
||||
scene.cameras.Create(entity);
|
||||
break;
|
||||
case 21:
|
||||
scene.objects.Create(entity);
|
||||
scene.aabb_objects.Create(entity);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1001,7 +1001,7 @@ void EditorComponent::Update(float dt)
|
||||
}
|
||||
ForceFieldComponent& force = scene.forces.Create(grass_interaction_entity);
|
||||
TransformComponent& transform = scene.transforms.Create(grass_interaction_entity);
|
||||
force.type = ENTITY_TYPE_FORCEFIELD_POINT;
|
||||
force.type = ForceFieldComponent::Type::Point;
|
||||
force.gravity = -80;
|
||||
force.range = 3;
|
||||
transform.Translate(P);
|
||||
|
||||
@@ -42,10 +42,10 @@ void ForceFieldWindow::Create(EditorComponent* _editor)
|
||||
switch (args.iValue)
|
||||
{
|
||||
case 0:
|
||||
force->type = ENTITY_TYPE_FORCEFIELD_POINT;
|
||||
force->type = ForceFieldComponent::Type::Point;
|
||||
break;
|
||||
case 1:
|
||||
force->type = ENTITY_TYPE_FORCEFIELD_PLANE;
|
||||
force->type = ForceFieldComponent::Type::Plane;
|
||||
break;
|
||||
default:
|
||||
assert(0); // error
|
||||
@@ -53,8 +53,8 @@ void ForceFieldWindow::Create(EditorComponent* _editor)
|
||||
}
|
||||
}
|
||||
});
|
||||
typeComboBox.AddItem("Point");
|
||||
typeComboBox.AddItem("Plane");
|
||||
typeComboBox.AddItem("Point", (uint64_t)ForceFieldComponent::Type::Point);
|
||||
typeComboBox.AddItem("Plane", (uint64_t)ForceFieldComponent::Type::Plane);
|
||||
typeComboBox.SetEnabled(false);
|
||||
typeComboBox.SetTooltip("Choose the force field type.");
|
||||
AddWidget(&typeComboBox);
|
||||
@@ -105,7 +105,7 @@ void ForceFieldWindow::SetEntity(Entity entity)
|
||||
|
||||
if (force != nullptr)
|
||||
{
|
||||
typeComboBox.SetSelected(force->type == ENTITY_TYPE_FORCEFIELD_POINT ? 0 : 1);
|
||||
typeComboBox.SetSelectedByUserdataWithoutCallback((uint64_t)force->type);
|
||||
gravitySlider.SetValue(force->gravity);
|
||||
rangeSlider.SetValue(force->range);
|
||||
|
||||
|
||||
+19
-1
@@ -13,7 +13,7 @@ void LightWindow::Create(EditorComponent* _editor)
|
||||
{
|
||||
editor = _editor;
|
||||
wi::gui::Window::Create(ICON_POINTLIGHT " Light", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE);
|
||||
SetSize(XMFLOAT2(650, 740));
|
||||
SetSize(XMFLOAT2(650, 760));
|
||||
|
||||
closeButton.SetTooltip("Delete LightComponent");
|
||||
OnClose([=](wi::gui::EventArgs args) {
|
||||
@@ -167,6 +167,20 @@ void LightWindow::Create(EditorComponent* _editor)
|
||||
staticCheckBox.SetTooltip("Static lights will only be used for baking into lightmaps.");
|
||||
AddWidget(&staticCheckBox);
|
||||
|
||||
volumetricCloudsCheckBox.Create("Volumetric Clouds: ");
|
||||
volumetricCloudsCheckBox.SetSize(XMFLOAT2(hei, hei));
|
||||
volumetricCloudsCheckBox.SetPos(XMFLOAT2(x, y += step));
|
||||
volumetricCloudsCheckBox.OnClick([&](wi::gui::EventArgs args) {
|
||||
LightComponent* light = editor->GetCurrentScene().lights.GetComponent(entity);
|
||||
if (light != nullptr)
|
||||
{
|
||||
light->SetVolumetricCloudsEnabled(args.bValue);
|
||||
}
|
||||
});
|
||||
volumetricCloudsCheckBox.SetEnabled(false);
|
||||
volumetricCloudsCheckBox.SetTooltip("When enabled light emission will affect volumetric clouds.");
|
||||
AddWidget(&volumetricCloudsCheckBox);
|
||||
|
||||
typeSelectorComboBox.Create("Type: ");
|
||||
typeSelectorComboBox.SetSize(XMFLOAT2(wid, hei));
|
||||
typeSelectorComboBox.SetPos(XMFLOAT2(x, y += step));
|
||||
@@ -282,6 +296,8 @@ void LightWindow::SetEntity(Entity entity)
|
||||
volumetricsCheckBox.SetCheck(light->IsVolumetricsEnabled());
|
||||
staticCheckBox.SetEnabled(true);
|
||||
staticCheckBox.SetCheck(light->IsStatic());
|
||||
volumetricCloudsCheckBox.SetEnabled(true);
|
||||
volumetricCloudsCheckBox.SetCheck(light->IsVolumetricCloudsEnabled());
|
||||
colorPicker.SetEnabled(true);
|
||||
colorPicker.SetPickColor(wi::Color::fromFloat3(light->color));
|
||||
typeSelectorComboBox.SetSelected((int)light->GetType());
|
||||
@@ -312,6 +328,7 @@ void LightWindow::SetEntity(Entity entity)
|
||||
haloCheckBox.SetEnabled(false);
|
||||
volumetricsCheckBox.SetEnabled(false);
|
||||
staticCheckBox.SetEnabled(false);
|
||||
volumetricCloudsCheckBox.SetEnabled(false);
|
||||
intensitySlider.SetEnabled(false);
|
||||
colorPicker.SetEnabled(false);
|
||||
shadowResolutionComboBox.SetEnabled(false);
|
||||
@@ -394,6 +411,7 @@ void LightWindow::ResizeLayout()
|
||||
add_right(haloCheckBox);
|
||||
add_right(volumetricsCheckBox);
|
||||
add_right(staticCheckBox);
|
||||
add_right(volumetricCloudsCheckBox);
|
||||
add(shadowResolutionComboBox);
|
||||
|
||||
y += jump;
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
wi::gui::CheckBox haloCheckBox;
|
||||
wi::gui::CheckBox volumetricsCheckBox;
|
||||
wi::gui::CheckBox staticCheckBox;
|
||||
wi::gui::CheckBox volumetricCloudsCheckBox;
|
||||
wi::gui::ColorPicker colorPicker;
|
||||
wi::gui::ComboBox typeSelectorComboBox;
|
||||
wi::gui::ComboBox shadowResolutionComboBox;
|
||||
|
||||
@@ -794,8 +794,8 @@ void TerrainGenerator::Generation_Restart()
|
||||
weather.ambient = XMFLOAT3(0.2f, 0.2f, 0.2f);
|
||||
weather.SetRealisticSky(true);
|
||||
weather.SetVolumetricClouds(true);
|
||||
weather.volumetricCloudParameters.CoverageAmount = 0.4f;
|
||||
weather.volumetricCloudParameters.CoverageMinimum = 1.35f;
|
||||
weather.volumetricCloudParameters.CoverageAmount = 0.65f;
|
||||
weather.volumetricCloudParameters.CoverageMinimum = 0.15f;
|
||||
if (presetCombo.GetItemUserData(presetCombo.GetSelected()) == PRESET_ISLANDS)
|
||||
{
|
||||
weather.SetOceanEnabled(true);
|
||||
@@ -813,9 +813,6 @@ void TerrainGenerator::Generation_Restart()
|
||||
weather.fogHeightEnd = 100;
|
||||
weather.windDirection = XMFLOAT3(0.05f, 0.05f, 0.05f);
|
||||
weather.windSpeed = 4;
|
||||
weather.cloud_shadow_amount = 0.4f;
|
||||
weather.cloud_shadow_scale = 0.003f;
|
||||
weather.cloud_shadow_speed = 0.25f;
|
||||
weather.stars = 0.6f;
|
||||
}
|
||||
if (scene->lights.GetCount() == 0)
|
||||
|
||||
+58
-110
@@ -10,7 +10,7 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
{
|
||||
editor = _editor;
|
||||
wi::gui::Window::Create(ICON_WEATHER " Weather", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE);
|
||||
SetSize(XMFLOAT2(660, 1400));
|
||||
SetSize(XMFLOAT2(660, 1300));
|
||||
|
||||
closeButton.SetTooltip("Delete WeatherComponent");
|
||||
OnClose([=](wi::gui::EventArgs args) {
|
||||
@@ -58,7 +58,7 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
colorComboBox.AddItem("Horizon color");
|
||||
colorComboBox.AddItem("Zenith color");
|
||||
colorComboBox.AddItem("Ocean color");
|
||||
colorComboBox.AddItem("V. Cloud color");
|
||||
colorComboBox.AddItem("Cloud color");
|
||||
colorComboBox.SetTooltip("Choose the destination data of the color picker.");
|
||||
AddWidget(&colorComboBox);
|
||||
|
||||
@@ -137,62 +137,6 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&fogHeightEndSlider);
|
||||
|
||||
fogHeightSkySlider.Create(0, 1, 0, 10000, "Fog Height Sky: ");
|
||||
fogHeightSkySlider.SetSize(XMFLOAT2(wid, hei));
|
||||
fogHeightSkySlider.SetPos(XMFLOAT2(x, y += step));
|
||||
fogHeightSkySlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().fogHeightSky = args.fValue;
|
||||
});
|
||||
AddWidget(&fogHeightSkySlider);
|
||||
|
||||
cloudinessSlider.Create(0, 1, 0.0f, 10000, "Cloudiness: ");
|
||||
cloudinessSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudinessSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudinessSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloudiness = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudinessSlider);
|
||||
|
||||
cloudScaleSlider.Create(0.00005f, 0.001f, 0.0005f, 10000, "Cloud Scale: ");
|
||||
cloudScaleSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudScaleSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudScaleSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloudScale = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudScaleSlider);
|
||||
|
||||
cloudSpeedSlider.Create(0.001f, 0.2f, 0.1f, 10000, "Cloud Speed: ");
|
||||
cloudSpeedSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudSpeedSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudSpeedSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloudSpeed = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudSpeedSlider);
|
||||
|
||||
cloudShadowAmountSlider.Create(0, 1, 0, 10000, "Cloud Shadow: ");
|
||||
cloudShadowAmountSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudShadowAmountSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudShadowAmountSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloud_shadow_amount = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudShadowAmountSlider);
|
||||
|
||||
cloudShadowSpeedSlider.Create(0, 1, 0.2f, 10000, "Cloud Shadow Speed: ");
|
||||
cloudShadowSpeedSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudShadowSpeedSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudShadowSpeedSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloud_shadow_speed = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudShadowSpeedSlider);
|
||||
|
||||
cloudShadowScaleSlider.Create(0.0001f, 0.02f, 0.005f, 10000, "Cloud Shadow Scale: ");
|
||||
cloudShadowScaleSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
cloudShadowScaleSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
cloudShadowScaleSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
GetWeather().cloud_shadow_scale = args.fValue;
|
||||
});
|
||||
AddWidget(&cloudShadowScaleSlider);
|
||||
|
||||
windSpeedSlider.Create(0.0f, 4.0f, 1.0f, 10000, "Wind Speed: ");
|
||||
windSpeedSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
windSpeedSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
@@ -250,31 +194,13 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&starsSlider);
|
||||
|
||||
simpleskyCheckBox.Create("Simple sky: ");
|
||||
simpleskyCheckBox.SetTooltip("Simple sky will simply blend horizon and zenith color from bottom to top.");
|
||||
simpleskyCheckBox.SetSize(XMFLOAT2(hei, hei));
|
||||
simpleskyCheckBox.SetPos(XMFLOAT2(x, y += step));
|
||||
simpleskyCheckBox.OnClick([&](wi::gui::EventArgs args) {
|
||||
auto& weather = GetWeather();
|
||||
weather.SetSimpleSky(args.bValue);
|
||||
if (args.bValue)
|
||||
{
|
||||
weather.SetRealisticSky(false);
|
||||
}
|
||||
});
|
||||
AddWidget(&simpleskyCheckBox);
|
||||
|
||||
realisticskyCheckBox.Create("Realistic sky: ");
|
||||
realisticskyCheckBox.SetTooltip("Physically based sky rendering model.");
|
||||
realisticskyCheckBox.SetTooltip("Physically based sky rendering model.\nNote that realistic sky requires a sun (directional light) to be visible.");
|
||||
realisticskyCheckBox.SetSize(XMFLOAT2(hei, hei));
|
||||
realisticskyCheckBox.SetPos(XMFLOAT2(x, y += step));
|
||||
realisticskyCheckBox.OnClick([&](wi::gui::EventArgs args) {
|
||||
auto& weather = GetWeather();
|
||||
weather.SetRealisticSky(args.bValue);
|
||||
if (args.bValue)
|
||||
{
|
||||
weather.SetSimpleSky(false);
|
||||
}
|
||||
});
|
||||
AddWidget(&realisticskyCheckBox);
|
||||
|
||||
@@ -289,7 +215,17 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&volumetricCloudsCheckBox);
|
||||
|
||||
coverageAmountSlider.Create(0, 10, 0, 1000, "Coverage amount: ");
|
||||
volumetricCloudsShadowsCheckBox.Create("Volumetric clouds shadows: ");
|
||||
volumetricCloudsShadowsCheckBox.SetTooltip("Compute shadows for volumetric clouds that will be used for geometry and lighting.");
|
||||
volumetricCloudsShadowsCheckBox.SetSize(XMFLOAT2(hei, hei));
|
||||
volumetricCloudsShadowsCheckBox.SetPos(XMFLOAT2(x, y += step));
|
||||
volumetricCloudsShadowsCheckBox.OnClick([&](wi::gui::EventArgs args) {
|
||||
auto& weather = GetWeather();
|
||||
weather.SetVolumetricCloudsShadows(args.bValue);
|
||||
});
|
||||
AddWidget(&volumetricCloudsShadowsCheckBox);
|
||||
|
||||
coverageAmountSlider.Create(0, 10, 1, 1000, "Coverage amount: ");
|
||||
coverageAmountSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
coverageAmountSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
coverageAmountSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
@@ -298,7 +234,7 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&coverageAmountSlider);
|
||||
|
||||
coverageMinimumSlider.Create(1, 2, 1, 1000, "Coverage minimmum: ");
|
||||
coverageMinimumSlider.Create(0, 1, 0, 1000, "Coverage minimmum: ");
|
||||
coverageMinimumSlider.SetSize(XMFLOAT2(wid, hei));
|
||||
coverageMinimumSlider.SetPos(XMFLOAT2(x, y += step));
|
||||
coverageMinimumSlider.OnSlide([&](wi::gui::EventArgs args) {
|
||||
@@ -374,6 +310,38 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
});
|
||||
AddWidget(&colorgradingButton);
|
||||
|
||||
volumetricCloudsWeatherMapButton.Create("Load Volumetric Clouds Weather Map");
|
||||
volumetricCloudsWeatherMapButton.SetTooltip("Load a weather map for volumetric clouds. Red channel is coverage, green is type and blue is water density (rain).");
|
||||
volumetricCloudsWeatherMapButton.SetSize(XMFLOAT2(mod_wid, hei));
|
||||
volumetricCloudsWeatherMapButton.SetPos(XMFLOAT2(mod_x, y += step));
|
||||
volumetricCloudsWeatherMapButton.OnClick([=](wi::gui::EventArgs args) {
|
||||
auto& weather = GetWeather();
|
||||
|
||||
if (!weather.volumetricCloudsWeatherMap.IsValid())
|
||||
{
|
||||
wi::helper::FileDialogParams params;
|
||||
params.type = wi::helper::FileDialogParams::OPEN;
|
||||
params.description = "Texture";
|
||||
params.extensions = wi::resourcemanager::GetSupportedImageExtensions();
|
||||
wi::helper::FileDialog(params, [=](std::string fileName) {
|
||||
wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
|
||||
auto& weather = GetWeather();
|
||||
weather.volumetricCloudsWeatherMapName = fileName;
|
||||
weather.volumetricCloudsWeatherMap = wi::resourcemanager::Load(fileName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
|
||||
volumetricCloudsWeatherMapButton.SetText(wi::helper::GetFileNameFromPath(fileName));
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
weather.volumetricCloudsWeatherMap = {};
|
||||
weather.volumetricCloudsWeatherMapName.clear();
|
||||
volumetricCloudsWeatherMapButton.SetText("Load Volumetric Clouds Weather Map");
|
||||
}
|
||||
|
||||
});
|
||||
AddWidget(&volumetricCloudsWeatherMapButton);
|
||||
|
||||
|
||||
|
||||
// Ocean params:
|
||||
@@ -519,10 +487,8 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
weather.ambient = XMFLOAT3(33.0f / 255.0f, 47.0f / 255.0f, 127.0f / 255.0f);
|
||||
weather.horizon = XMFLOAT3(101.0f / 255.0f, 101.0f / 255.0f, 227.0f / 255.0f);
|
||||
weather.zenith = XMFLOAT3(99.0f / 255.0f, 133.0f / 255.0f, 255.0f / 255.0f);
|
||||
weather.cloudiness = 0.4f;
|
||||
weather.fogStart = 100;
|
||||
weather.fogEnd = 1000;
|
||||
weather.fogHeightSky = 0;
|
||||
|
||||
InvalidateProbes();
|
||||
|
||||
@@ -538,11 +504,9 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
auto& weather = GetWeather();
|
||||
weather.ambient = XMFLOAT3(86.0f / 255.0f, 29.0f / 255.0f, 29.0f / 255.0f);
|
||||
weather.horizon = XMFLOAT3(121.0f / 255.0f, 28.0f / 255.0f, 22.0f / 255.0f);
|
||||
weather.zenith = XMFLOAT3(146.0f / 255.0f, 51.0f / 255.0f, 51.0f / 255.0f);
|
||||
weather.cloudiness = 0.36f;
|
||||
weather.zenith = XMFLOAT3(80.0f / 255.0f, 10.0f / 255.0f, 10.0f / 255.0f);
|
||||
weather.fogStart = 50;
|
||||
weather.fogEnd = 600;
|
||||
weather.fogHeightSky = 0;
|
||||
|
||||
InvalidateProbes();
|
||||
|
||||
@@ -559,10 +523,8 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
weather.ambient = XMFLOAT3(0.1f, 0.1f, 0.1f);
|
||||
weather.horizon = XMFLOAT3(0.38f, 0.38f, 0.38f);
|
||||
weather.zenith = XMFLOAT3(0.42f, 0.42f, 0.42f);
|
||||
weather.cloudiness = 0.75f;
|
||||
weather.fogStart = 0;
|
||||
weather.fogEnd = 500;
|
||||
weather.fogHeightSky = 0;
|
||||
|
||||
InvalidateProbes();
|
||||
|
||||
@@ -577,12 +539,10 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
|
||||
auto& weather = GetWeather();
|
||||
weather.ambient = XMFLOAT3(12.0f / 255.0f, 21.0f / 255.0f, 77.0f / 255.0f);
|
||||
weather.horizon = XMFLOAT3(10.0f / 255.0f, 33.0f / 255.0f, 70.0f / 255.0f);
|
||||
weather.zenith = XMFLOAT3(4.0f / 255.0f, 20.0f / 255.0f, 51.0f / 255.0f);
|
||||
weather.cloudiness = 0.28f;
|
||||
weather.horizon = XMFLOAT3(2.0f / 255.0f, 10.0f / 255.0f, 20.0f / 255.0f);
|
||||
weather.zenith = XMFLOAT3(0, 0, 0);
|
||||
weather.fogStart = 10;
|
||||
weather.fogEnd = 400;
|
||||
weather.fogHeightSky = 0;
|
||||
|
||||
InvalidateProbes();
|
||||
|
||||
@@ -599,11 +559,8 @@ void WeatherWindow::Create(EditorComponent* _editor)
|
||||
weather.ambient = XMFLOAT3(0, 0, 0);
|
||||
weather.horizon = XMFLOAT3(1, 1, 1);
|
||||
weather.zenith = XMFLOAT3(1, 1, 1);
|
||||
weather.SetSimpleSky(true);
|
||||
weather.cloudiness = 0;
|
||||
weather.fogStart = 1000000;
|
||||
weather.fogEnd = 1000000;
|
||||
weather.fogHeightSky = 0;
|
||||
|
||||
InvalidateProbes();
|
||||
|
||||
@@ -712,18 +669,16 @@ void WeatherWindow::Update()
|
||||
colorgradingButton.SetText(wi::helper::GetFileNameFromPath(weather.colorGradingMapName));
|
||||
}
|
||||
|
||||
if (!weather.volumetricCloudsWeatherMapName.empty())
|
||||
{
|
||||
volumetricCloudsWeatherMapButton.SetText(wi::helper::GetFileNameFromPath(weather.volumetricCloudsWeatherMapName));
|
||||
}
|
||||
|
||||
heightFogCheckBox.SetCheck(weather.IsHeightFog());
|
||||
fogStartSlider.SetValue(weather.fogStart);
|
||||
fogEndSlider.SetValue(weather.fogEnd);
|
||||
fogHeightStartSlider.SetValue(weather.fogHeightStart);
|
||||
fogHeightEndSlider.SetValue(weather.fogHeightEnd);
|
||||
fogHeightSkySlider.SetValue(weather.fogHeightSky);
|
||||
cloudinessSlider.SetValue(weather.cloudiness);
|
||||
cloudScaleSlider.SetValue(weather.cloudScale);
|
||||
cloudSpeedSlider.SetValue(weather.cloudSpeed);
|
||||
cloudShadowAmountSlider.SetValue(weather.cloud_shadow_amount);
|
||||
cloudShadowScaleSlider.SetValue(weather.cloud_shadow_scale);
|
||||
cloudShadowSpeedSlider.SetValue(weather.cloud_shadow_speed);
|
||||
windSpeedSlider.SetValue(weather.windSpeed);
|
||||
windWaveSizeSlider.SetValue(weather.windWaveSize);
|
||||
windRandomnessSlider.SetValue(weather.windRandomness);
|
||||
@@ -751,7 +706,6 @@ void WeatherWindow::Update()
|
||||
break;
|
||||
}
|
||||
|
||||
simpleskyCheckBox.SetCheck(weather.IsSimpleSky());
|
||||
realisticskyCheckBox.SetCheck(weather.IsRealisticSky());
|
||||
|
||||
ocean_enabledCheckBox.SetCheck(weather.IsOceanEnabled());
|
||||
@@ -765,13 +719,13 @@ void WeatherWindow::Update()
|
||||
ocean_toleranceSlider.SetValue(weather.oceanParameters.surfaceDisplacementTolerance);
|
||||
|
||||
volumetricCloudsCheckBox.SetCheck(weather.IsVolumetricClouds());
|
||||
volumetricCloudsShadowsCheckBox.SetCheck(weather.IsVolumetricCloudsShadows());
|
||||
coverageAmountSlider.SetValue(weather.volumetricCloudParameters.CoverageAmount);
|
||||
coverageMinimumSlider.SetValue(weather.volumetricCloudParameters.CoverageMinimum);
|
||||
}
|
||||
else
|
||||
{
|
||||
scene.weather = {};
|
||||
scene.weather.SetSimpleSky(true);
|
||||
scene.weather.ambient = XMFLOAT3(0.5f, 0.5f, 0.5f);
|
||||
scene.weather.zenith = default_sky_zenith;
|
||||
scene.weather.horizon = default_sky_horizon;
|
||||
@@ -846,7 +800,6 @@ void WeatherWindow::ResizeLayout()
|
||||
};
|
||||
|
||||
add_fullwidth(primaryButton);
|
||||
add_right(simpleskyCheckBox);
|
||||
add_right(realisticskyCheckBox);
|
||||
add(colorComboBox);
|
||||
add_fullwidth(colorPicker);
|
||||
@@ -857,13 +810,6 @@ void WeatherWindow::ResizeLayout()
|
||||
add(fogEndSlider);
|
||||
add(fogHeightStartSlider);
|
||||
add(fogHeightEndSlider);
|
||||
add(fogHeightSkySlider);
|
||||
add(cloudinessSlider);
|
||||
add(cloudScaleSlider);
|
||||
add(cloudSpeedSlider);
|
||||
add(cloudShadowAmountSlider);
|
||||
add(cloudShadowScaleSlider);
|
||||
add(cloudShadowSpeedSlider);
|
||||
add(windSpeedSlider);
|
||||
add(windMagnitudeSlider);
|
||||
add(windDirectionSlider);
|
||||
@@ -875,8 +821,10 @@ void WeatherWindow::ResizeLayout()
|
||||
y += jump;
|
||||
|
||||
add_right(volumetricCloudsCheckBox);
|
||||
add_right(volumetricCloudsShadowsCheckBox);
|
||||
add(coverageAmountSlider);
|
||||
add(coverageMinimumSlider);
|
||||
add_fullwidth(volumetricCloudsWeatherMapButton);
|
||||
|
||||
y += jump;
|
||||
|
||||
|
||||
@@ -27,13 +27,6 @@ public:
|
||||
wi::gui::Slider fogEndSlider;
|
||||
wi::gui::Slider fogHeightStartSlider;
|
||||
wi::gui::Slider fogHeightEndSlider;
|
||||
wi::gui::Slider fogHeightSkySlider;
|
||||
wi::gui::Slider cloudinessSlider;
|
||||
wi::gui::Slider cloudScaleSlider;
|
||||
wi::gui::Slider cloudSpeedSlider;
|
||||
wi::gui::Slider cloudShadowAmountSlider;
|
||||
wi::gui::Slider cloudShadowScaleSlider;
|
||||
wi::gui::Slider cloudShadowSpeedSlider;
|
||||
wi::gui::Slider windSpeedSlider;
|
||||
wi::gui::Slider windMagnitudeSlider;
|
||||
wi::gui::Slider windDirectionSlider;
|
||||
@@ -41,7 +34,6 @@ public:
|
||||
wi::gui::Slider windRandomnessSlider;
|
||||
wi::gui::Slider skyExposureSlider;
|
||||
wi::gui::Slider starsSlider;
|
||||
wi::gui::CheckBox simpleskyCheckBox;
|
||||
wi::gui::CheckBox realisticskyCheckBox;
|
||||
wi::gui::Button skyButton;
|
||||
wi::gui::Button colorgradingButton;
|
||||
@@ -63,8 +55,10 @@ public:
|
||||
|
||||
// volumetric clouds:
|
||||
wi::gui::CheckBox volumetricCloudsCheckBox;
|
||||
wi::gui::CheckBox volumetricCloudsShadowsCheckBox;
|
||||
wi::gui::Slider coverageAmountSlider;
|
||||
wi::gui::Slider coverageMinimumSlider;
|
||||
wi::gui::Button volumetricCloudsWeatherMapButton;
|
||||
|
||||
wi::gui::Button preset0Button;
|
||||
wi::gui::Button preset1Button;
|
||||
|
||||
@@ -384,7 +384,6 @@ void TestsRenderer::Load()
|
||||
weather.ambient = XMFLOAT3(0.2f, 0.2f, 0.2f);
|
||||
weather.horizon = XMFLOAT3(0.38f, 0.38f, 0.38f);
|
||||
weather.zenith = XMFLOAT3(0.42f, 0.42f, 0.42f);
|
||||
weather.cloudiness = 0.75f;
|
||||
|
||||
wi::scene::GetScene().Merge(scene); // add lodaded scene to global scene
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ dofile("../Content/scripts/camera_animation_repeat.lua");
|
||||
ToggleCameraAnimation();
|
||||
|
||||
-- Load an image:
|
||||
local sprite = Sprite("../logo_small.png");
|
||||
local sprite = Sprite("../Content/logo_small.png");
|
||||
sprite.SetParams(ImageParams(100,100,128,128));
|
||||
-- Set this image as renderable to the active component:
|
||||
local component = main.GetActivePath();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
This file contains changelog of wi::Archive versions
|
||||
|
||||
86: serialized volumetric clouds weather map, removed unused values and remapped values from VolumetricCloudParameters
|
||||
85: DDGI serialization
|
||||
84: component library serialization
|
||||
83: physical light units
|
||||
|
||||
@@ -150,13 +150,16 @@ wi::vector<ShaderEntry> shaders = {
|
||||
{"blur_bilateral_unorm1CS", wi::graphics::ShaderStage::CS },
|
||||
{"voxelSceneCopyClearCS_TemporalSmoothing", wi::graphics::ShaderStage::CS },
|
||||
{"normalsfromdepthCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_shapenoiseCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_detailnoiseCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_curlnoiseCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_weathermapCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_detailnoiseCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_renderCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_renderCS_capture", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_renderCS_capture_MSAA", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_reprojectCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_temporalCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_shadow_filterCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_shadow_renderCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_shapenoiseCS", wi::graphics::ShaderStage::CS },
|
||||
{"volumetricCloud_weathermapCS", wi::graphics::ShaderStage::CS },
|
||||
{"shadingRateClassificationCS", wi::graphics::ShaderStage::CS },
|
||||
{"shadingRateClassificationCS_DEBUG", wi::graphics::ShaderStage::CS },
|
||||
{"skyAtmosphere_transmittanceLutCS", wi::graphics::ShaderStage::CS },
|
||||
|
||||
@@ -632,6 +632,7 @@ enum SHADER_ENTITY_TYPE
|
||||
};
|
||||
|
||||
static const uint ENTITY_FLAG_LIGHT_STATIC = 1 << 0;
|
||||
static const uint ENTITY_FLAG_LIGHT_VOLUMETRICCLOUDS = 1 << 1;
|
||||
|
||||
static const uint SHADER_ENTITY_COUNT = 256;
|
||||
static const uint SHADER_ENTITY_TILE_BUCKET_COUNT = SHADER_ENTITY_COUNT / 32;
|
||||
@@ -653,7 +654,6 @@ static const uint OPTION_BIT_TRANSPARENTSHADOWS_ENABLED = 1 << 1;
|
||||
static const uint OPTION_BIT_VOXELGI_ENABLED = 1 << 2;
|
||||
static const uint OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED = 1 << 3;
|
||||
static const uint OPTION_BIT_VOXELGI_RETARGETTED = 1 << 4;
|
||||
static const uint OPTION_BIT_SIMPLE_SKY = 1 << 5;
|
||||
static const uint OPTION_BIT_REALISTIC_SKY = 1 << 6;
|
||||
static const uint OPTION_BIT_HEIGHT_FOG = 1 << 7;
|
||||
static const uint OPTION_BIT_RAYTRACED_SHADOWS = 1 << 8;
|
||||
@@ -662,6 +662,7 @@ static const uint OPTION_BIT_SURFELGI_ENABLED = 1 << 10;
|
||||
static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 11;
|
||||
static const uint OPTION_BIT_FORCE_DIFFUSE_LIGHTING = 1 << 12;
|
||||
static const uint OPTION_BIT_STATIC_SKY_HDR = 1 << 13;
|
||||
static const uint OPTION_BIT_VOLUMETRICCLOUDS_SHADOWS = 1 << 14;
|
||||
|
||||
// ---------- Common Constant buffers: -----------------
|
||||
|
||||
@@ -680,6 +681,13 @@ struct FrameCB
|
||||
uint2 shadow_atlas_resolution;
|
||||
float2 shadow_atlas_resolution_rcp;
|
||||
|
||||
float4x4 cloudShadowLightSpaceMatrix;
|
||||
float4x4 cloudShadowLightSpaceMatrixInverse;
|
||||
|
||||
float cloudShadowFarPlaneKm;
|
||||
int texture_volumetricclouds_shadow_index;
|
||||
float2 padding0;
|
||||
|
||||
float3 voxelradiance_center; // center of the voxel grid in world space units
|
||||
float voxelradiance_max_distance; // maximum raymarch distance for voxel GI in world-space
|
||||
|
||||
@@ -840,6 +848,7 @@ struct LensFlarePush
|
||||
struct CubemapRenderCam
|
||||
{
|
||||
float4x4 view_projection;
|
||||
float4x4 inverse_view_projection;
|
||||
uint4 properties;
|
||||
};
|
||||
CBUFFER(CubemapRenderCB, CBSLOT_RENDERER_CUBEMAPRENDER)
|
||||
@@ -928,5 +937,21 @@ struct SkinningPushConstants
|
||||
int so_tan;
|
||||
};
|
||||
|
||||
struct VolumetricCloudCapturePushConstants
|
||||
{
|
||||
uint2 resolution;
|
||||
float2 resolution_rcp;
|
||||
|
||||
uint arrayIndex;
|
||||
int texture_input;
|
||||
int texture_output;
|
||||
int MaxStepCount;
|
||||
|
||||
float LODMin;
|
||||
float ShadowSampleCount;
|
||||
float GroundContributionSampleCount;
|
||||
float padding;
|
||||
};
|
||||
|
||||
|
||||
#endif // WI_SHADERINTEROP_RENDERER_H
|
||||
|
||||
@@ -95,7 +95,7 @@ struct VolumetricCloudParameters
|
||||
float3 Albedo; // Cloud albedo is normally very close to 1
|
||||
float CloudAmbientGroundMultiplier; // [0; 1] Amount of ambient light to reach the bottom of clouds
|
||||
|
||||
float3 ExtinctionCoefficient; // * 0.05 looks good too
|
||||
float3 ExtinctionCoefficient;
|
||||
float BeerPowder;
|
||||
|
||||
float BeerPowderPower;
|
||||
@@ -120,12 +120,8 @@ struct VolumetricCloudParameters
|
||||
|
||||
float WeatherScale;
|
||||
float CurlScale;
|
||||
float ShapeNoiseHeightGradientAmount;
|
||||
float ShapeNoiseMultiplier;
|
||||
|
||||
float2 ShapeNoiseMinMax;
|
||||
float ShapeNoisePower;
|
||||
float DetailNoiseModifier;
|
||||
float padding0;
|
||||
|
||||
float DetailNoiseHeightFraction;
|
||||
float CurlNoiseModifier;
|
||||
@@ -133,7 +129,7 @@ struct VolumetricCloudParameters
|
||||
float CoverageMinimum;
|
||||
|
||||
float TypeAmount;
|
||||
float TypeOverall;
|
||||
float TypeMinimum;
|
||||
float AnvilAmount; // Anvil clouds disabled by default.
|
||||
float AnvilOverhangHeight;
|
||||
|
||||
@@ -143,7 +139,7 @@ struct VolumetricCloudParameters
|
||||
float WindAngle;
|
||||
float WindUpAmount;
|
||||
|
||||
float2 padding0;
|
||||
float2 padding1;
|
||||
float CoverageWindSpeed;
|
||||
float CoverageWindAngle;
|
||||
|
||||
@@ -161,21 +157,19 @@ struct VolumetricCloudParameters
|
||||
|
||||
float LODDistance; // After a certain distance, noises will get higher LOD
|
||||
float LODMin; //
|
||||
float BigStepMarch; // How long inital rays should be until they hit something. Lower values may ives a better image but may be slower.
|
||||
float BigStepMarch; // How long inital rays should be until they hit something. Lower values may give a better image but may be slower.
|
||||
float TransmittanceThreshold; // Default: 0.005. If the clouds transmittance has reached it's desired opacity, there's no need to keep raymarching for performance.
|
||||
|
||||
float2 padding1;
|
||||
float2 padding2;
|
||||
float ShadowSampleCount;
|
||||
float GroundContributionSampleCount;
|
||||
|
||||
void init()
|
||||
{
|
||||
|
||||
|
||||
// Lighting
|
||||
Albedo = float3(0.9f, 0.9f, 0.9f);
|
||||
CloudAmbientGroundMultiplier = 0.75f;
|
||||
ExtinctionCoefficient = float3(0.71f * 0.1f, 0.86f * 0.1f, 1.0f * 0.1f);
|
||||
ExtinctionCoefficient = float3(0.71f * 0.05f, 0.86f * 0.05f, 1.0f * 0.05f);
|
||||
BeerPowder = 20.0f;
|
||||
BeerPowderPower = 0.5f;
|
||||
PhaseG = 0.5f; // [-0.999; 0.999]
|
||||
@@ -185,7 +179,7 @@ struct VolumetricCloudParameters
|
||||
MultiScatteringExtinction = 0.1f;
|
||||
MultiScatteringEccentricity = 0.2f;
|
||||
ShadowStepLength = 3000.0f;
|
||||
HorizonBlendAmount = 1.25f;
|
||||
HorizonBlendAmount = 0.0000125f;
|
||||
HorizonBlendPower = 2.0f;
|
||||
WeatherDensityAmount = 0.0f;
|
||||
|
||||
@@ -194,24 +188,19 @@ struct VolumetricCloudParameters
|
||||
CloudThickness = 4000.0f;
|
||||
SkewAlongWindDirection = 700.0f;
|
||||
|
||||
TotalNoiseScale = 1.0f;
|
||||
DetailScale = 5.0f;
|
||||
WeatherScale = 0.0625f;
|
||||
CurlScale = 7.5f;
|
||||
|
||||
ShapeNoiseHeightGradientAmount = 0.2f;
|
||||
ShapeNoiseMultiplier = 0.8f;
|
||||
ShapeNoisePower = 6.0f;
|
||||
ShapeNoiseMinMax = float2(0.25f, 1.1f);
|
||||
TotalNoiseScale = 0.0006f;
|
||||
DetailScale = 2.0f;
|
||||
WeatherScale = 0.000025f;
|
||||
CurlScale = 0.3f;
|
||||
|
||||
DetailNoiseModifier = 0.2f;
|
||||
DetailNoiseHeightFraction = 10.0f;
|
||||
CurlNoiseModifier = 550.0f;
|
||||
CurlNoiseModifier = 500.0f;
|
||||
|
||||
CoverageAmount = 2.0f;
|
||||
CoverageMinimum = 1.05f;
|
||||
CoverageAmount = 1.0f;
|
||||
CoverageMinimum = 0.0f;
|
||||
TypeAmount = 1.0f;
|
||||
TypeOverall = 0.0f;
|
||||
TypeMinimum = 0.0f;
|
||||
AnvilAmount = 0.0f;
|
||||
AnvilOverhangHeight = 3.0f;
|
||||
|
||||
@@ -225,21 +214,21 @@ struct VolumetricCloudParameters
|
||||
|
||||
// Cloud types
|
||||
// 4 positions of a black, white, white, black gradient
|
||||
CloudGradientSmall = float4(0.02f, 0.07f, 0.12f, 0.28f);
|
||||
CloudGradientMedium = float4(0.02f, 0.07f, 0.39f, 0.59f);
|
||||
CloudGradientSmall = float4(0.02f, 0.1f, 0.12f, 0.28f);
|
||||
CloudGradientMedium = float4(0.02f, 0.1f, 0.39f, 0.59f);
|
||||
CloudGradientLarge = float4(0.02f, 0.07f, 0.88f, 1.0f);
|
||||
|
||||
// Performance
|
||||
MaxStepCount = 128;
|
||||
MaxStepCount = 96;
|
||||
MaxMarchingDistance = 30000.0f;
|
||||
InverseDistanceStepCount = 15000.0f;
|
||||
RenderDistance = 70000.0f;
|
||||
LODDistance = 25000.0f;
|
||||
LODMin = 0.0f;
|
||||
BigStepMarch = 3.0f;
|
||||
BigStepMarch = 1.0f;
|
||||
TransmittanceThreshold = 0.005f;
|
||||
ShadowSampleCount = 5.0f;
|
||||
GroundContributionSampleCount = 2.0f;
|
||||
GroundContributionSampleCount = 3.0f;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -254,11 +243,6 @@ struct ShaderFog
|
||||
float end;
|
||||
float height_start;
|
||||
float height_end;
|
||||
|
||||
float height_sky;
|
||||
float padding0;
|
||||
float padding1;
|
||||
float padding2;
|
||||
};
|
||||
|
||||
struct ShaderWind
|
||||
@@ -293,15 +277,10 @@ struct ShaderWeather
|
||||
float sky_exposure;
|
||||
|
||||
float3 zenith;
|
||||
float cloudiness;
|
||||
float padding0;
|
||||
|
||||
float3 ambient;
|
||||
float cloud_scale;
|
||||
|
||||
float cloud_speed;
|
||||
float cloud_shadow_amount;
|
||||
float cloud_shadow_scale;
|
||||
float cloud_shadow_speed;
|
||||
float padding1;
|
||||
|
||||
float4x4 stars_rotation;
|
||||
|
||||
|
||||
@@ -1125,7 +1125,22 @@
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)visibility_velocityCS.hlsl" />
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_temporalCS.hlsl" />
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_renderCS_capture.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_renderCS_capture_MSAA.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_shadow_filterCS.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_shadow_renderCS.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
|
||||
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetriclight_directionalVS.hlsl">
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
|
||||
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
|
||||
|
||||
@@ -947,9 +947,6 @@
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)fsr_sharpenCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_temporalCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)surfel_coverageCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
@@ -1055,6 +1052,18 @@
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)impostor_prepareCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_renderCS_capture.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_shadow_renderCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_shadow_filterCS.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
<FxCompile Include="$(MSBuildThisFileDirectory)volumetricCloud_renderCS_capture_MSAA.hlsl">
|
||||
<Filter>CS</Filter>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop.h">
|
||||
|
||||
@@ -9,6 +9,5 @@ float4 main(PixelInput input) : SV_TARGET
|
||||
{
|
||||
float3 normal = normalize(input.nor);
|
||||
float3 sky = DEGAMMA(texture_sky.SampleLevel(sampler_linear_clamp, normal, 0).rgb);
|
||||
CalculateClouds(sky, normal, false);
|
||||
return float4(sky, 1);
|
||||
}
|
||||
|
||||
@@ -210,6 +210,9 @@ struct PrimitiveID
|
||||
#define sqr(a) ((a)*(a))
|
||||
#define pow5(x) pow(x, 5)
|
||||
|
||||
#define M_TO_SKY_UNIT 0.001f // Engine units are in meters
|
||||
#define SKY_UNIT_TO_M (1.0 / M_TO_SKY_UNIT)
|
||||
|
||||
// attribute computation with barycentric interpolation
|
||||
// a0 : attribute at triangle corner 0
|
||||
// a1 : attribute at triangle corner 1
|
||||
@@ -571,6 +574,14 @@ inline float compute_lineardepth(in float z)
|
||||
return compute_lineardepth(z, GetCamera().z_near, GetCamera().z_far);
|
||||
}
|
||||
|
||||
// Computes post-projection depth from linear depth
|
||||
inline float compute_inverse_lineardepth(in float lin, in float near, in float far)
|
||||
{
|
||||
float z_n = ((lin - 2 * far) * near + far * lin) / (lin * near - far * lin);
|
||||
float z = (z_n + 1) / 2;
|
||||
return z;
|
||||
}
|
||||
|
||||
inline float3x3 get_tangentspace(in float3 normal)
|
||||
{
|
||||
// Choose a helper vector for the cross product
|
||||
|
||||
@@ -131,13 +131,11 @@ inline void light_directional(in ShaderEntity light, in Surface surface, inout L
|
||||
[branch]
|
||||
if (light.IsCastingShadow() && surface.IsReceiveShadow())
|
||||
{
|
||||
if (GetWeather().cloud_shadow_amount > 0)
|
||||
if (GetFrame().options & OPTION_BIT_VOLUMETRICCLOUDS_SHADOWS)
|
||||
{
|
||||
// Fake cloud shadows:
|
||||
float cloud_shadow = noise_simplex_2D(surface.P.xz * GetWeather().cloud_shadow_scale + GetTime() * GetWeather().cloud_shadow_speed) * 0.5 + 0.5;
|
||||
shadow *= saturate(cloud_shadow + 1 - GetWeather().cloud_shadow_amount * 2);
|
||||
shadow *= shadow_2D_volumetricclouds(surface.P);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SHADOW_MASK_ENABLED
|
||||
[branch]
|
||||
if ((GetFrame().options & OPTION_BIT_RAYTRACED_SHADOWS) == 0 || GetCamera().texture_rtshadow_index < 0)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define DISABLE_VOXELGI
|
||||
#include "objectHF.hlsli"
|
||||
#include "voxelHF.hlsli"
|
||||
#include "volumetricCloudsHF.hlsli"
|
||||
|
||||
// Note: the voxelizer uses an overall simplified material and lighting model (no normal maps, only diffuse light and emissive)
|
||||
|
||||
@@ -102,10 +103,16 @@ void main(PSInput input)
|
||||
float3 ShPos = mul(load_entitymatrix(light.GetMatrixIndex() + cascade), float4(P, 1)).xyz; // ortho matrix, no divide by .w
|
||||
float3 ShTex = ShPos.xyz * float3(0.5f, -0.5f, 0.5f) + 0.5f;
|
||||
|
||||
[branch] if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y) && (saturate(ShTex.z) == ShTex.z))
|
||||
[branch]
|
||||
if ((saturate(ShTex.x) == ShTex.x) && (saturate(ShTex.y) == ShTex.y) && (saturate(ShTex.z) == ShTex.z))
|
||||
{
|
||||
lightColor *= shadow_2D(light, ShPos, ShTex.xy, cascade);
|
||||
}
|
||||
|
||||
if (GetFrame().options & OPTION_BIT_VOLUMETRICCLOUDS_SHADOWS)
|
||||
{
|
||||
lightColor *= shadow_2D_volumetricclouds(P);
|
||||
}
|
||||
}
|
||||
|
||||
lighting.direct.diffuse += lightColor;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef WI_SKYATMOSPHERE_HF
|
||||
#define WI_SKYATMOSPHERE_HF
|
||||
#include "globals.hlsli"
|
||||
#include "volumetricCloudsHF.hlsli"
|
||||
|
||||
/*
|
||||
*
|
||||
@@ -14,13 +15,11 @@
|
||||
|
||||
static const float2 transmittanceLUTRes = float2(256, 64);
|
||||
static const float2 multiScatteringLUTRes = float2(32, 32);
|
||||
static const float2 skyViewLUTRes = float2(192.0, 104);
|
||||
static const float2 skyViewLUTRes = float2(192, 104);
|
||||
static const float2 skyLuminanceLUTRes = float2(1, 1);
|
||||
|
||||
#define USE_CornetteShanks
|
||||
|
||||
#define M_TO_SKY_UNIT 0.001f // Engine units are in meters
|
||||
#define SKY_UNIT_TO_M (1.0 / M_TO_SKY_UNIT)
|
||||
|
||||
#define PLANET_RADIUS_OFFSET 0.001f // Float accuracy offset in Sky unit (km, so this is 1m)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -470,12 +469,12 @@ struct SamplingParameters
|
||||
float sampleCountIni; // Used when variableSampleCount is false
|
||||
float2 rayMarchMinMaxSPP;
|
||||
float distanceSPPMaxInv;
|
||||
//bool perPixelNoise;
|
||||
bool perPixelNoise;
|
||||
};
|
||||
|
||||
SingleScatteringResult IntegrateScatteredLuminance(
|
||||
in AtmosphereParameters atmosphere, in float2 pixPos, in float3 worldPosition, in float3 worldDirection, in float3 sunDirection, in float3 sunIlluminance,
|
||||
in SamplingParameters sampling, in bool ground, in float3 depthBufferWorldPos, in bool opaque, in bool mieRayPhase, in bool multiScatteringApprox,
|
||||
in AtmosphereParameters atmosphere, in float2 pixelPosition, in float3 worldPosition, in float3 worldDirection, in float3 sunDirection, in float3 sunIlluminance,
|
||||
in SamplingParameters sampling, in float tDepth, in bool opaque, in bool ground, in bool mieRayPhase, in bool multiScatteringApprox, in bool volumetricCloudShadow,
|
||||
in Texture2D<float4> transmittanceLutTexture, in Texture2D<float4> multiScatteringLUTTexture, in float tMaxMax = 9000000.0f)
|
||||
{
|
||||
SingleScatteringResult result = (SingleScatteringResult) 0;
|
||||
@@ -512,19 +511,10 @@ SingleScatteringResult IntegrateScatteredLuminance(
|
||||
{
|
||||
if (opaque)
|
||||
{
|
||||
float3 depthBufferWorldPosKm = depthBufferWorldPos * M_TO_SKY_UNIT;
|
||||
float3 traceStartWorldPosKm = worldPosition + atmosphere.planetCenter; // Planet center is in km
|
||||
float3 traceStartToSurfaceWorldKm = depthBufferWorldPosKm - traceStartWorldPosKm;
|
||||
float tDepth = length(traceStartToSurfaceWorldKm); // Apply earth offset to go back to origin as top of earth mode.
|
||||
if (tDepth < tMax)
|
||||
{
|
||||
tMax = tDepth;
|
||||
}
|
||||
|
||||
//if (dot(worldDirection, traceStartToSurfaceWorldKm) < 0.0)
|
||||
//{
|
||||
// return result;
|
||||
//}
|
||||
}
|
||||
tMax = min(tMax, tMaxMax);
|
||||
|
||||
@@ -579,16 +569,16 @@ SingleScatteringResult IntegrateScatteredLuminance(
|
||||
t1 = tMaxFloor * t1;
|
||||
}
|
||||
|
||||
//if (Sampling.PerPixelNoise)
|
||||
//{
|
||||
// t = t0 + (t1 - t0) * InterleavedGradientNoise(pixPos, GetFrame().frame_count % 16);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// t = t0 + (t1 - t0) * SampleSegmentT;
|
||||
//}
|
||||
t = t0 + (t1 - t0) * sampleSegmentT;
|
||||
|
||||
// Reduce sample count with noise and Temporal AA:
|
||||
if (sampling.perPixelNoise)
|
||||
{
|
||||
t = t0 + (t1 - t0) * InterleavedGradientNoise(pixelPosition, GetFrame().frame_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = t0 + (t1 - t0) * sampleSegmentT;
|
||||
}
|
||||
|
||||
dt = t1 - t0;
|
||||
}
|
||||
else
|
||||
@@ -625,6 +615,12 @@ SingleScatteringResult IntegrateScatteredLuminance(
|
||||
float tEarth = RaySphereIntersectNearest(P, sunDirection, earthO + PLANET_RADIUS_OFFSET * UpVector, atmosphere.bottomRadius);
|
||||
float earthShadow = tEarth >= 0.0f ? 0.0f : 1.0f;
|
||||
|
||||
// Volumetric cloud shadow
|
||||
if (volumetricCloudShadow && GetFrame().options & OPTION_BIT_VOLUMETRICCLOUDS_SHADOWS)
|
||||
{
|
||||
earthShadow *= shadow_2D_volumetricclouds(P * SKY_UNIT_TO_M + atmosphere.planetCenter * SKY_UNIT_TO_M);
|
||||
}
|
||||
|
||||
// Dual scattering for multi scattering
|
||||
|
||||
float3 multiScatteredLuminance = 0.0f;
|
||||
|
||||
@@ -16,7 +16,6 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
float2 pixelPosition = float2(DTid.xy) + 0.5;
|
||||
float2 uv = pixelPosition * rcp(multiScatteringLUTRes);
|
||||
|
||||
|
||||
uv = float2(FromSubUvsToUnit(uv.x, multiScatteringLUTRes.x), FromSubUvsToUnit(uv.y, multiScatteringLUTRes.y));
|
||||
|
||||
@@ -39,11 +38,12 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
sampling.variableSampleCount = false;
|
||||
sampling.sampleCountIni = 20; // a minimum set of step is required for accuracy unfortunately
|
||||
}
|
||||
const bool ground = true;
|
||||
const float depthBufferWorldPos = 0.0;
|
||||
const float tDepth = 0.0;
|
||||
const bool opaque = false;
|
||||
const bool ground = true;
|
||||
const bool mieRayPhase = false;
|
||||
const bool multiScatteringApprox = false;
|
||||
const bool volumetricCloudShadow = false;
|
||||
|
||||
const float sphereSolidAngle = 4.0 * PI;
|
||||
const float isotropicPhase = 1.0 / sphereSolidAngle;
|
||||
@@ -68,7 +68,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
worldDirection.z = cosPhi;
|
||||
SingleScatteringResult result = IntegrateScatteredLuminance(
|
||||
atmosphere, pixelPosition, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, ground, depthBufferWorldPos, opaque, mieRayPhase, multiScatteringApprox, transmittanceLUT, multiScatteringLUT);
|
||||
sampling, tDepth, opaque, ground, mieRayPhase, multiScatteringApprox, volumetricCloudShadow, transmittanceLUT, multiScatteringLUT);
|
||||
|
||||
MultiScatAs1SharedMem[DTid.z] = result.multiScatAs1 * sphereSolidAngle / (sqrtSample * sqrtSample);
|
||||
LSharedMem[DTid.z] = result.L * sphereSolidAngle / (sqrtSample * sqrtSample);
|
||||
|
||||
@@ -14,8 +14,7 @@ groupshared float3 SkyLuminanceSharedMem[64];
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
float2 pixelPosition = float2(DTid.xy) + 0.5;
|
||||
float2 uv = pixelPosition * rcp(multiScatteringLUTRes);
|
||||
|
||||
float2 uv = pixelPosition * rcp(skyLuminanceLUTRes);
|
||||
|
||||
AtmosphereParameters atmosphere = GetWeather().atmosphere;
|
||||
|
||||
@@ -32,11 +31,12 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
sampling.variableSampleCount = false;
|
||||
sampling.sampleCountIni = 10; // Should be enough since we're taking an approximation of luminance around a point
|
||||
}
|
||||
const bool ground = false;
|
||||
const float depthBufferWorldPos = 0.0;
|
||||
const float tDepth = 0.0;
|
||||
const bool opaque = false;
|
||||
const bool ground = false;
|
||||
const bool mieRayPhase = false; // Perhabs?
|
||||
const bool multiScatteringApprox = true;
|
||||
const bool volumetricCloudShadow = false;
|
||||
|
||||
const float sphereSolidAngle = 4.0 * PI;
|
||||
const float isotropicPhase = 1.0 / sphereSolidAngle;
|
||||
@@ -61,7 +61,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
worldDirection.z = cosPhi;
|
||||
SingleScatteringResult result = IntegrateScatteredLuminance(
|
||||
atmosphere, pixelPosition, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, ground, depthBufferWorldPos, opaque, mieRayPhase, multiScatteringApprox, transmittanceLUT, multiScatteringLUT);
|
||||
sampling, tDepth, opaque, ground, mieRayPhase, multiScatteringApprox, volumetricCloudShadow, transmittanceLUT, multiScatteringLUT);
|
||||
|
||||
SkyLuminanceSharedMem[DTid.z] = result.L * sphereSolidAngle / (sqrtSample * sqrtSample);
|
||||
}
|
||||
|
||||
@@ -57,15 +57,17 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
sampling.sampleCountIni = 30;
|
||||
sampling.rayMarchMinMaxSPP = float2(4, 14);
|
||||
sampling.distanceSPPMaxInv = 0.01;
|
||||
sampling.perPixelNoise = false;
|
||||
}
|
||||
const float tDepth = 0.0;
|
||||
const bool ground = false;
|
||||
const float depthBufferWorldPos = 0.0;
|
||||
const bool opaque = false;
|
||||
const bool mieRayPhase = true;
|
||||
const bool multiScatteringApprox = true;
|
||||
const bool volumetricCloudShadow = false;
|
||||
SingleScatteringResult ss = IntegrateScatteredLuminance(
|
||||
atmosphere, pixelPosition, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, ground, depthBufferWorldPos, opaque, mieRayPhase, multiScatteringApprox, transmittanceLUT, multiScatteringLUT);
|
||||
sampling, tDepth, opaque, ground, mieRayPhase, multiScatteringApprox, volumetricCloudShadow, transmittanceLUT, multiScatteringLUT);
|
||||
|
||||
float3 L = ss.L;
|
||||
|
||||
|
||||
@@ -29,14 +29,15 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
sampling.variableSampleCount = false;
|
||||
sampling.sampleCountIni = 40.0f; // Can go a low as 10 sample but energy lost starts to be visible.
|
||||
}
|
||||
const bool ground = false;
|
||||
const float depthBufferWorldPos = 0.0;
|
||||
const float tDepth = 0.0;
|
||||
const bool opaque = false;
|
||||
const bool ground = false;
|
||||
const bool mieRayPhase = false;
|
||||
const bool multiScatteringApprox = false;
|
||||
const bool volumetricCloudShadow = false;
|
||||
SingleScatteringResult ss = IntegrateScatteredLuminance(
|
||||
atmosphere, pixelPosition, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, ground, depthBufferWorldPos, opaque, mieRayPhase, multiScatteringApprox, transmittanceLUT, multiScatteringLUT);
|
||||
sampling, tDepth, opaque, ground, mieRayPhase, multiScatteringApprox, volumetricCloudShadow, transmittanceLUT, multiScatteringLUT);
|
||||
|
||||
float3 transmittance = exp(-ss.opticalDepth);
|
||||
|
||||
|
||||
@@ -56,16 +56,18 @@ float3 AccurateAtmosphericScattering(Texture2D<float4> skyViewLutTexture, Textur
|
||||
sampling.sampleCountIni = 0.0f;
|
||||
sampling.rayMarchMinMaxSPP = float2(4, 14);
|
||||
sampling.distanceSPPMaxInv = 0.01;
|
||||
}
|
||||
const bool ground = false;
|
||||
const float depthBufferWorldPos = 0.0;
|
||||
sampling.perPixelNoise = false;
|
||||
}
|
||||
const float2 pixelPosition = float2(0.0, 0.0);
|
||||
const float tDepth = 0.0;
|
||||
const bool opaque = false;
|
||||
const bool ground = false;
|
||||
const bool mieRayPhase = true;
|
||||
const bool multiScatteringApprox = true;
|
||||
const float2 pixPos = float2(0, 0);
|
||||
const bool volumetricCloudShadow = false;
|
||||
SingleScatteringResult ss = IntegrateScatteredLuminance(
|
||||
atmosphere, pixPos, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, ground, depthBufferWorldPos, opaque, mieRayPhase, multiScatteringApprox, transmittanceLUT, multiScatteringLUT);
|
||||
atmosphere, pixelPosition, worldPosition, worldDirection, sunDirection, sunIlluminance,
|
||||
sampling, tDepth, opaque, ground, mieRayPhase, multiScatteringApprox, volumetricCloudShadow, transmittanceLUT, multiScatteringLUT);
|
||||
|
||||
luminance = ss.L;
|
||||
}
|
||||
@@ -91,166 +93,11 @@ float3 AccurateAtmosphericScattering(Texture2D<float4> skyViewLutTexture, Textur
|
||||
return totalColor;
|
||||
}
|
||||
|
||||
float2 hash(float2 p)
|
||||
{
|
||||
p = float2(dot(p, float2(127.1, 311.7)), dot(p, float2(269.5, 183.3)));
|
||||
return -1.0 + 2.0 * frac(sin(p) * 43758.5453123);
|
||||
}
|
||||
float noise(in float2 p)
|
||||
{
|
||||
const float K1 = 0.366025404; // (sqrt(3)-1)/2;
|
||||
const float K2 = 0.211324865; // (3-sqrt(3))/6;
|
||||
float2 i = floor(p + (p.x + p.y) * K1);
|
||||
float2 a = p - i + (i.x + i.y) * K2;
|
||||
float2 o = (a.x > a.y) ? float2(1.0, 0.0) : float2(0.0, 1.0); //float2 of = 0.5 + 0.5*float2(sign(a.x-a.y), sign(a.y-a.x));
|
||||
float2 b = a - o + K2;
|
||||
float2 c = a - 1.0 + 2.0 * K2;
|
||||
float3 h = max(0.5 - float3(dot(a, a), dot(b, b), dot(c, c)), 0.0);
|
||||
float3 n = h * h * h * h * float3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0)));
|
||||
return dot(n, float3(70.0, 70.0, 70.0));
|
||||
}
|
||||
|
||||
float3 CustomAtmosphericScattering(float3 V, float3 sunDirection, float3 sunColor, bool sun_enabled, bool dark_enabled)
|
||||
{
|
||||
const float3 skyColor = GetZenithColor();
|
||||
const bool sunPresent = any(sunColor);
|
||||
const bool sunDisc = sun_enabled && sunPresent;
|
||||
|
||||
const float zenith = V.y; // how much is above (0: horizon, 1: directly above)
|
||||
const float sunScatter = saturate(sunDirection.y + 0.1f); // how much the sun is directly above. Even if sunis at horizon, we add a constant scattering amount so that light still scatters at horizon
|
||||
|
||||
const float atmosphereDensity = 0.5 + GetWeather().fog.height_sky; // constant of air density, or "fog height" as interpreted here (bigger is more obstruction of sun)
|
||||
const float zenithDensity = atmosphereDensity / pow(max(0.000001f, zenith), 0.75f);
|
||||
const float sunScatterDensity = atmosphereDensity / pow(max(0.000001f, sunScatter), 0.75f);
|
||||
|
||||
const float3 aberration = float3(0.39, 0.57, 1.0); // the chromatic aberration effect on the horizon-zenith fade line
|
||||
const float3 skyAbsorption = saturate(exp2(aberration * -zenithDensity) * 2.0f); // gradient on horizon
|
||||
const float3 sunAbsorption = sunPresent ? saturate(sunColor * exp2(aberration * -sunScatterDensity) * 2.0f) : 1; // gradient of sun when it's getting below horizon
|
||||
|
||||
const float sunAmount = distance(V, sunDirection); // sun falloff descreasing from mid point
|
||||
const float rayleigh = sunPresent ? 1.0 + pow(1.0 - saturate(sunAmount), 2.0) * PI * 0.5 : 1;
|
||||
const float mie_disk = saturate(1.0 - pow(sunAmount, 0.1));
|
||||
const float3 mie = mie_disk * mie_disk * (3.0 - 2.0 * mie_disk) * 2.0 * PI * sunAbsorption;
|
||||
|
||||
float3 totalColor = lerp(GetHorizonColor(), GetZenithColor() * zenithDensity * rayleigh, skyAbsorption);
|
||||
totalColor = lerp(totalColor * skyAbsorption, totalColor, sunScatter); // when sun goes below horizon, absorb sky color
|
||||
if (sunDisc)
|
||||
{
|
||||
const float3 sun = smoothstep(0.03, 0.026, sunAmount) * sunColor * 50.0 * skyAbsorption; // sun disc
|
||||
totalColor += sun;
|
||||
totalColor += mie;
|
||||
}
|
||||
totalColor *= (sunAbsorption + length(sunAbsorption)) * 0.5f; // when sun goes below horizon, fade out whole sky
|
||||
totalColor *= 0.25; // exposure level
|
||||
|
||||
if (dark_enabled)
|
||||
{
|
||||
totalColor = max(pow(saturate(dot(sunDirection, V)), 64) * sunColor, 0) * skyAbsorption;
|
||||
}
|
||||
|
||||
return totalColor;
|
||||
}
|
||||
|
||||
void CalculateClouds(inout float3 sky, float3 V, bool dark_enabled)
|
||||
{
|
||||
if (GetWeather().cloudiness <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace a cloud layer plane:
|
||||
const float3 o = GetCamera().position;
|
||||
const float3 d = V;
|
||||
const float3 planeOrigin = float3(0, 1000, 0);
|
||||
const float3 planeNormal = float3(0, -1, 0);
|
||||
const float t = trace_plane(o, d, planeOrigin, planeNormal);
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float3 cloudPos = o + d * t;
|
||||
const float2 cloudUV = cloudPos.xz * GetWeather().cloud_scale;
|
||||
const float cloudTime = GetFrame().time * GetWeather().cloud_speed;
|
||||
const float2x2 m = float2x2(1.6, 1.2, -1.2, 1.6);
|
||||
const uint quality = 8;
|
||||
|
||||
// rotate uvs like a flow effect:
|
||||
float flow = 0;
|
||||
{
|
||||
float2 uv = cloudUV * 0.5f;
|
||||
float amount = 0.1;
|
||||
for (uint i = 0; i < quality; i++)
|
||||
{
|
||||
flow += noise(uv) * amount;
|
||||
uv = mul(m, uv);
|
||||
amount *= 0.4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Main shape:
|
||||
float clouds = 0.0;
|
||||
{
|
||||
const float time = cloudTime * 0.2f;
|
||||
float density = 1.1f;
|
||||
float2 uv = cloudUV * 0.8f;
|
||||
uv -= flow - time;
|
||||
for (uint i = 0; i < quality; i++)
|
||||
{
|
||||
clouds += density * noise(uv);
|
||||
uv = mul(m, uv) + time;
|
||||
density *= 0.6f;
|
||||
}
|
||||
}
|
||||
|
||||
// Detail shape:
|
||||
{
|
||||
float detail_shape = 0.0;
|
||||
const float time = cloudTime * 0.1f;
|
||||
float density = 0.8f;
|
||||
float2 uv = cloudUV;
|
||||
uv -= flow - time;
|
||||
for (uint i = 0; i < quality; i++)
|
||||
{
|
||||
detail_shape += abs(density * noise(uv));
|
||||
uv = mul(m, uv) + time;
|
||||
density *= 0.7f;
|
||||
}
|
||||
clouds *= detail_shape + clouds;
|
||||
clouds *= detail_shape;
|
||||
}
|
||||
|
||||
|
||||
// lerp between "choppy clouds" and "uniform clouds". Lower cloudiness will produce choppy clouds, but very high cloudiness will switch to overcast unfiform clouds:
|
||||
clouds = lerp(clouds * 9.0f * GetWeather().cloudiness + 0.3f, clouds * 0.5f + 0.5f, pow(saturate(GetWeather().cloudiness), 8));
|
||||
clouds = saturate(clouds - (1 - GetWeather().cloudiness)); // modulate constant cloudiness
|
||||
clouds *= pow(1 - saturate(length(abs(cloudPos.xz * 0.00001f))), 16); //fade close to horizon
|
||||
|
||||
if (dark_enabled)
|
||||
{
|
||||
sky *= pow(saturate(1 - clouds), 16.0f); // only sun and clouds. Boost clouds to have nicer sun shafts occlusion
|
||||
}
|
||||
else
|
||||
{
|
||||
sky = lerp(sky, 1, clouds); // sky and clouds on top
|
||||
}
|
||||
}
|
||||
|
||||
// Returns sky color modulated by the sun and clouds
|
||||
// V : view direction
|
||||
float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enabled = true, bool dark_enabled = false, bool realistic_sky_stationary = false)
|
||||
{
|
||||
if (GetFrame().options & OPTION_BIT_SIMPLE_SKY)
|
||||
{
|
||||
return lerp(GetHorizonColor(), GetZenithColor(), saturate(V.y * 0.5f + 0.5f)) * GetWeather().sky_exposure;
|
||||
}
|
||||
|
||||
const float3 sunDirection = GetSunDirection();
|
||||
const float3 sunColor = GetSunColor();
|
||||
|
||||
float3 sky = float3(0, 0, 0);
|
||||
float3 sky = 0;
|
||||
|
||||
if (GetFrame().options & OPTION_BIT_REALISTIC_SKY)
|
||||
{
|
||||
@@ -261,8 +108,8 @@ float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enab
|
||||
texture_multiscatteringlut,
|
||||
GetCamera().position, // Ray origin
|
||||
V, // Ray direction
|
||||
sunDirection, // Position of the sun
|
||||
sunColor, // Sun Color
|
||||
GetSunDirection(), // Position of the sun
|
||||
GetSunColor(), // Sun Color
|
||||
sun_enabled, // Use sun and total
|
||||
dark_enabled, // Enable dark mode for light shafts etc.
|
||||
realistic_sky_stationary // Fixed position for ambient and environment capture.
|
||||
@@ -270,23 +117,11 @@ float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enab
|
||||
}
|
||||
else
|
||||
{
|
||||
sky = CustomAtmosphericScattering
|
||||
(
|
||||
V, // normalized ray direction
|
||||
sunDirection, // position of the sun
|
||||
sunColor, // color of the sun, for disc
|
||||
sun_enabled, // use sun and total
|
||||
dark_enabled // enable dark mode for light shafts etc.
|
||||
);
|
||||
sky = lerp(GetHorizonColor(), GetZenithColor(), saturate(V.y * 0.5f + 0.5f));
|
||||
}
|
||||
|
||||
sky *= GetWeather().sky_exposure;
|
||||
|
||||
if (clouds_enabled)
|
||||
{
|
||||
CalculateClouds(sky, V, dark_enabled);
|
||||
}
|
||||
|
||||
return sky;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET
|
||||
const float3 V = normalize(unprojected.xyz - GetCamera().position);
|
||||
|
||||
float4 color = float4(DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, V, 0).rgb), 1);
|
||||
CalculateClouds(color.rgb, V, false);
|
||||
|
||||
float4 pos2DPrev = mul(GetCamera().previous_view_projection, float4(unprojected.xyz, 1));
|
||||
float2 velocity = ((pos2DPrev.xy / pos2DPrev.w - GetCamera().temporalaa_jitter_prev) - (clipspace - GetCamera().temporalaa_jitter)) * float2(0.5f, -0.5f);
|
||||
|
||||
@@ -83,14 +83,6 @@ uint3 hash33(uint3 x)
|
||||
return uint3(n, n * 16807u, n * 48271u); //see: http://random.mat.sbg.ac.at/results/karl/server/node4.html
|
||||
}
|
||||
|
||||
// Computes post-projection depth from linear depth
|
||||
float getInverseLinearDepth(float lin, float near, float far)
|
||||
{
|
||||
float z_n = ((lin - 2 * far) * near + far * lin) / (lin * near - far * lin);
|
||||
float z = (z_n + 1) / 2;
|
||||
return z;
|
||||
}
|
||||
|
||||
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
@@ -164,7 +156,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
|
||||
// Convert to post-projection depth so we can construct dual source reprojection buffers later
|
||||
const float lineardepth = texture_lineardepth[DTid.xy] * GetCamera().z_far;
|
||||
float reprojectionDepth = getInverseLinearDepth(lineardepth + closestRayLength, GetCamera().z_near, GetCamera().z_far);
|
||||
float reprojectionDepth = compute_inverse_lineardepth(lineardepth + closestRayLength, GetCamera().z_near, GetCamera().z_far);
|
||||
|
||||
texture_resolve[DTid.xy] = max(result, 0.00001f);
|
||||
texture_resolve_variance[DTid.xy] = resolveVariance;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
#define VOLUMETRICCLOUD_CAPTURE
|
||||
#include "volumetricCloud_renderCS.hlsl"
|
||||
@@ -0,0 +1,2 @@
|
||||
#define MSAA
|
||||
#include "volumetricCloud_renderCS_capture.hlsl"
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "globals.hlsli"
|
||||
#include "volumetricCloudsHF.hlsli"
|
||||
#include "ShaderInterop_Postprocess.h"
|
||||
|
||||
PUSHCONSTANT(postprocess, PostProcess);
|
||||
@@ -7,32 +8,29 @@ Texture2D<float4> cloud_current : register(t0);
|
||||
Texture2D<float2> cloud_depth_current : register(t1);
|
||||
Texture2D<float4> cloud_history : register(t2);
|
||||
Texture2D<float2> cloud_depth_history : register(t3);
|
||||
Texture2D<float> cloud_additional_history : register(t4);
|
||||
|
||||
RWTexture2D<float4> output : register(u0);
|
||||
RWTexture2D<float2> output_depth : register(u1);
|
||||
RWTexture2D<float> output_additional : register(u2);
|
||||
RWTexture2D<unorm float4> output_cloudMask : register(u3);
|
||||
|
||||
// This function compute the checkerboard undersampling position
|
||||
int ComputeCheckerBoardIndex(int2 renderCoord, int subPixelIndex)
|
||||
{
|
||||
const int localOffset = (renderCoord.x & 1 + renderCoord.y & 1) & 1;
|
||||
const int checkerBoardLocation = (subPixelIndex + localOffset) & 0x3;
|
||||
return checkerBoardLocation;
|
||||
}
|
||||
static const float2 temporalResponseMinMax = float2(0.5, 0.9);
|
||||
|
||||
// Computes post-projection depth from linear depth
|
||||
float getInverseLinearDepth(float lin, float near, float far)
|
||||
{
|
||||
float z_n = ((lin - 2 * far) * near + far * lin) / (lin * near - far * lin);
|
||||
float z = (z_n + 1) / 2;
|
||||
return z;
|
||||
}
|
||||
// When moving fast reprojection cannot catch up. This value eliminates the ghosting but results in clipping artefacts
|
||||
//#define ADDITIONAL_BOX_CLAMP
|
||||
|
||||
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
uint2 renderCoord = DTid.xy / 2;
|
||||
const float2 uv = (DTid.xy + 0.5f) * postprocess.resolution_rcp;
|
||||
|
||||
uint2 renderResolution = postprocess.resolution / 2;
|
||||
uint2 renderCoord = DTid.xy / 2;
|
||||
|
||||
uint2 minRenderCoord = uint2(0, 0);
|
||||
uint2 maxRenderCoord = renderResolution - 1;
|
||||
|
||||
#if 0
|
||||
|
||||
// Calculate screen dependant motion vector
|
||||
@@ -55,7 +53,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
float2 screenPosition = float2(x, y);
|
||||
|
||||
float currentCloudLinearDepth = cloud_depth_current.SampleLevel(sampler_point_clamp, uv, 0).x;
|
||||
float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, GetCamera().z_near, GetCamera().z_far);
|
||||
float currentCloudDepth = compute_inverse_lineardepth(currentCloudLinearDepth, GetCamera().z_near, GetCamera().z_far);
|
||||
|
||||
float4 thisClip = float4(screenPosition, currentCloudDepth, 1.0);
|
||||
|
||||
@@ -83,6 +81,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
|
||||
float4 result = 0.0;
|
||||
float2 depthResult = 0.0;
|
||||
float additionalResult = 0.0;
|
||||
|
||||
|
||||
#if 0 // Simple reprojection version
|
||||
@@ -98,31 +97,78 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
}
|
||||
output[DTid.xy] = result;
|
||||
output_depth[DTid.xy] = depthResult;
|
||||
output_additional[DTid.xy] = 0.0;
|
||||
output_cloudMask[DTid.xy] = pow(saturate(1 - result.a), 64);
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
if (validHistory)
|
||||
{
|
||||
float4 newResult = cloud_current[renderCoord];
|
||||
float2 newDepthResult = cloud_depth_current[renderCoord];
|
||||
float4 newResult = cloud_current[clamp(renderCoord, minRenderCoord, maxRenderCoord)];
|
||||
float2 newDepthResult = cloud_depth_current[clamp(renderCoord, minRenderCoord, maxRenderCoord)];
|
||||
|
||||
float4 previousResult = cloud_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
float2 previousDepthResult = cloud_depth_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
float previousAdditionalResult = cloud_additional_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
|
||||
float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1).r; // Half res
|
||||
float3 depthWorldPosition = reconstruct_position(uv, depth);
|
||||
float tToDepthBuffer = length(depthWorldPosition - GetCamera().position);
|
||||
|
||||
// Accommodate so when we compare tToDepthBuffer (float precision) with cloud_depth_current (half float precision) we don't overshoot and get incorrect testing
|
||||
// No issues has been noticed so far
|
||||
tToDepthBuffer = depth == 0.0 ? HALF_FLT_MAX : tToDepthBuffer;
|
||||
|
||||
if (shouldUpdatePixel)
|
||||
{
|
||||
result = newResult;
|
||||
depthResult = newDepthResult;
|
||||
if (abs(tToDepthBuffer - previousDepthResult.y) > tToDepthBuffer * 0.1)
|
||||
{
|
||||
result = newResult;
|
||||
depthResult = newDepthResult;
|
||||
additionalResult = temporalResponseMinMax.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Based on Welford's online algorithm:
|
||||
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
|
||||
|
||||
float4 m1 = 0.0;
|
||||
float4 m2 = 0.0;
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
int2 offset = int2(x, y);
|
||||
int2 neighborCoord = renderCoord + offset;
|
||||
neighborCoord = clamp(neighborCoord, minRenderCoord, maxRenderCoord);
|
||||
|
||||
float4 neighborResult = cloud_current[neighborCoord];
|
||||
|
||||
m1 += neighborResult;
|
||||
m2 += neighborResult * neighborResult;
|
||||
}
|
||||
}
|
||||
|
||||
float4 mean = m1 / 9.0;
|
||||
float4 variance = (m2 / 9.0) - (mean * mean);
|
||||
float4 stddev = sqrt(max(variance, 0.0f));
|
||||
|
||||
// Color box clamp
|
||||
float4 colorMin = mean - stddev;
|
||||
float4 colorMax = mean + stddev;
|
||||
previousResult = clamp(previousResult, colorMin, colorMax);
|
||||
|
||||
result = lerp(newResult, previousResult, previousAdditionalResult);
|
||||
depthResult = newDepthResult;
|
||||
additionalResult = temporalResponseMinMax.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float4 previousResult = cloud_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
float2 previousDepthResult = cloud_depth_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
|
||||
result = previousResult;
|
||||
depthResult = previousDepthResult;
|
||||
|
||||
float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1).r; // Half res
|
||||
float3 depthWorldPosition = reconstruct_position(uv, depth);
|
||||
float tToDepthBuffer = length(depthWorldPosition - GetCamera().position);
|
||||
additionalResult = previousAdditionalResult;
|
||||
|
||||
if (abs(tToDepthBuffer - previousDepthResult.y) > tToDepthBuffer * 0.1)
|
||||
{
|
||||
@@ -135,31 +181,66 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
if ((abs(x) + abs(y)) == 0)
|
||||
continue;
|
||||
|
||||
int2 neighborCoord = renderCoord + int2(x, y);
|
||||
|
||||
int2 offset = int2(x, y);
|
||||
int2 neighborCoord = renderCoord + offset;
|
||||
neighborCoord = clamp(neighborCoord, minRenderCoord, maxRenderCoord);
|
||||
|
||||
float2 neighboorDepthResult = cloud_depth_current[neighborCoord];
|
||||
float neighborClosestDepth = abs(tToDepthBuffer - neighboorDepthResult.y);
|
||||
|
||||
if (neighborClosestDepth < closestDepth)
|
||||
{
|
||||
closestDepth = neighborClosestDepth;
|
||||
|
||||
float4 neighborResult = cloud_current[neighborCoord];
|
||||
|
||||
|
||||
result = neighborResult;
|
||||
depthResult = neighboorDepthResult;
|
||||
additionalResult = temporalResponseMinMax.x;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(tToDepthBuffer - newDepthResult.y) < closestDepth)
|
||||
{
|
||||
result = newResult;
|
||||
depthResult = newDepthResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
#ifdef ADDITIONAL_BOX_CLAMP
|
||||
// Simple box clamping from neighbour pixels
|
||||
float4 resultAABBMin = FLT_MAX;
|
||||
float4 resultAABBMax = 0.0;
|
||||
float2 depthResultAABBMin = FLT_MAX;
|
||||
float2 depthResultAABBMax = 0.0;
|
||||
|
||||
for (int y = -1; y <= 1; y++)
|
||||
{
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
// If it's middle then skip. We only evaluate neighbor samples
|
||||
if ((abs(x) + abs(y)) == 0)
|
||||
continue;
|
||||
|
||||
int2 offset = int2(x, y);
|
||||
int2 neighborCoord = renderCoord + offset;
|
||||
|
||||
float4 neighborResult = cloud_current[neighborCoord];
|
||||
float2 neighboorDepthResult = cloud_depth_current[neighborCoord];
|
||||
|
||||
resultAABBMin = min(resultAABBMin, neighborResult);
|
||||
resultAABBMax = max(resultAABBMax, neighborResult);
|
||||
depthResultAABBMin = min(depthResultAABBMin, neighboorDepthResult);
|
||||
depthResultAABBMax = max(depthResultAABBMax, neighboorDepthResult);
|
||||
}
|
||||
}
|
||||
|
||||
resultAABBMin = min(resultAABBMin, newResult);
|
||||
resultAABBMax = max(resultAABBMax, newResult);
|
||||
depthResultAABBMin = min(depthResultAABBMin, newDepthResult);
|
||||
depthResultAABBMax = max(depthResultAABBMax, newDepthResult);
|
||||
|
||||
result = clamp(result, resultAABBMin, resultAABBMax);
|
||||
depthResult = clamp(depthResult, depthResultAABBMin, depthResultAABBMax);
|
||||
#endif // ADDITIONAL_CLIPPING
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,8 +248,11 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
result = cloud_current.SampleLevel(sampler_linear_clamp, uv, 0);
|
||||
depthResult = cloud_depth_current.SampleLevel(sampler_linear_clamp, uv, 0);
|
||||
additionalResult = temporalResponseMinMax.x;
|
||||
}
|
||||
|
||||
|
||||
output[DTid.xy] = result;
|
||||
output_depth[DTid.xy] = depthResult;
|
||||
output_additional[DTid.xy] = additionalResult;
|
||||
output_cloudMask[DTid.xy] = pow(saturate(1 - result.a), 64);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "globals.hlsli"
|
||||
#include "ShaderInterop_Postprocess.h"
|
||||
|
||||
PUSHCONSTANT(postprocess, PostProcess);
|
||||
|
||||
Texture2D<float3> input : register(t0);
|
||||
RWTexture2D<float3> output : register(u0);
|
||||
|
||||
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
const float2 uv = (DTid.xy + 0.5) * postprocess.resolution_rcp;
|
||||
|
||||
#if 0 // Debug
|
||||
output[DTid.xy] = input[DTid.xy];
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Filter
|
||||
float3 filteredResult = 0.0;
|
||||
float sum = 0.0;
|
||||
|
||||
const int radius = 1;
|
||||
for (int x = -radius; x <= radius; x++)
|
||||
{
|
||||
for (int y = -radius; y <= radius; y++)
|
||||
{
|
||||
int2 offset = int2(x, y);
|
||||
int2 neighborCoord = DTid.xy + offset;
|
||||
|
||||
if (all(neighborCoord >= int2(0, 0) && neighborCoord < (int2) postprocess.resolution))
|
||||
{
|
||||
float3 neighborResult = input[neighborCoord];
|
||||
|
||||
filteredResult += neighborResult;
|
||||
sum += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
filteredResult /= sum;
|
||||
|
||||
output[DTid.xy] = filteredResult;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "globals.hlsli"
|
||||
#include "volumetricCloudsHF.hlsli"
|
||||
#include "skyAtmosphere.hlsli"
|
||||
#include "ShaderInterop_Postprocess.h"
|
||||
|
||||
PUSHCONSTANT(postprocess, PostProcess);
|
||||
|
||||
Texture3D<float4> texture_shapeNoise : register(t0);
|
||||
Texture3D<float4> texture_detailNoise : register(t1);
|
||||
Texture2D<float4> texture_curlNoise : register(t2);
|
||||
Texture2D<float4> texture_weatherMap : register(t3);
|
||||
|
||||
RWTexture2D<float3> texture_render : register(u0);
|
||||
|
||||
static const float2 sampleCountMinMax = float2(16.0, 32.0); // Based on sun angle, more angle more samples
|
||||
|
||||
void VolumetricShadowMap(out float3 result, in AtmosphereParameters atmosphere, float3 worldPosition, float3 sunDirection,
|
||||
float tMin, float tMax, float3 windOffset, float3 windDirection, float2 coverageWindOffset)
|
||||
{
|
||||
float nearDepth = 0.0;
|
||||
float3 extinctionAccumulation = 0.0f;
|
||||
float extinctionAccumulationCount = 0.0f;
|
||||
float3 maxOpticalDepth = 0.0f;
|
||||
|
||||
float3 planetSurfaceNormal = normalize(GetCamera().position - (atmosphere.planetCenter * SKY_UNIT_TO_M));
|
||||
float NdotL = saturate(dot(planetSurfaceNormal, sunDirection));
|
||||
float sampleCount = lerp(sampleCountMinMax.y, sampleCountMinMax.x, NdotL);
|
||||
|
||||
const float shadowLength = tMax - tMin;
|
||||
const float delta = shadowLength / sampleCount; // Since our samples our linear this stays constant
|
||||
|
||||
for (float s = 0.0f; s < sampleCount; s += 1.0)
|
||||
{
|
||||
// Linear Distribution
|
||||
float t = (s + 1.0f) / sampleCount;
|
||||
|
||||
float shadowSampleT = shadowLength * t;
|
||||
float3 samplePoint = worldPosition + sunDirection * shadowSampleT; // Step futher towards the light
|
||||
|
||||
float heightFraction = GetHeightFractionForPoint(atmosphere, samplePoint);
|
||||
if (heightFraction < 0.0 || heightFraction > 1.0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
float3 weatherData = SampleWeather(texture_weatherMap, samplePoint, heightFraction, coverageWindOffset);
|
||||
if (weatherData.r < 0.25)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float shadowCloudDensity = SampleCloudDensity(texture_shapeNoise, texture_detailNoise, texture_curlNoise, samplePoint, heightFraction, weatherData, windOffset, windDirection, 0.0f, true);
|
||||
|
||||
float3 shadowExtinction = GetWeather().volumetric_clouds.ExtinctionCoefficient * shadowCloudDensity;
|
||||
|
||||
if (any(shadowExtinction > 0.0f))
|
||||
{
|
||||
nearDepth = max(shadowSampleT, nearDepth); // If there exists extinction "push" the near depth futher
|
||||
extinctionAccumulationCount += 1.0;
|
||||
}
|
||||
|
||||
extinctionAccumulation += shadowExtinction;
|
||||
maxOpticalDepth += shadowExtinction * delta;
|
||||
}
|
||||
|
||||
const float averageGreyExtinction = dot(extinctionAccumulation / max(extinctionAccumulationCount, 1.0f), 1.0f / 3.0f);
|
||||
const float maxGreyOpticalDepth = dot(maxOpticalDepth, 1.0f / 3.0f);
|
||||
|
||||
// Values can get to big for the assigned texture, so we pack this into kilometer type
|
||||
const bool miss = nearDepth == 0.0;
|
||||
const float frontDepth = miss ? tMax * M_TO_SKY_UNIT : (tMin + nearDepth) * M_TO_SKY_UNIT;
|
||||
|
||||
result = float3(frontDepth, averageGreyExtinction, maxGreyOpticalDepth);
|
||||
}
|
||||
|
||||
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
|
||||
{
|
||||
const float2 uv = (DTid.xy + 0.5) * postprocess.resolution_rcp;
|
||||
|
||||
const float nearDepth = 1.0f;
|
||||
float3 nearPlaneWorldPosition = reconstruct_position(uv, nearDepth, GetFrame().cloudShadowLightSpaceMatrixInverse);
|
||||
|
||||
// Setup for shadow capture:
|
||||
float3 rayOrigin = nearPlaneWorldPosition;
|
||||
float3 rayDirection = GetSunDirection();
|
||||
|
||||
float3 result = float3(GetFrame().cloudShadowFarPlaneKm, 0.0, 0.0);
|
||||
|
||||
AtmosphereParameters parameters = GetWeather().atmosphere;
|
||||
|
||||
float planetRadius = parameters.bottomRadius * SKY_UNIT_TO_M;
|
||||
float3 planetCenterWorld = parameters.planetCenter * SKY_UNIT_TO_M;
|
||||
|
||||
const float cloudBottomRadius = planetRadius + GetWeather().volumetric_clouds.CloudStartHeight;
|
||||
const float cloudTopRadius = planetRadius + GetWeather().volumetric_clouds.CloudStartHeight + GetWeather().volumetric_clouds.CloudThickness;
|
||||
|
||||
float2 tTopSolutions = RaySphereIntersect(rayOrigin, rayDirection, planetCenterWorld, cloudTopRadius);
|
||||
if (tTopSolutions.x > 0.0 || tTopSolutions.y > 0.0) // Only calculate if any solutions are visible on screen!
|
||||
{
|
||||
float tMin = -FLT_MAX;
|
||||
float tMax = -FLT_MAX;
|
||||
|
||||
float2 tBottomSolutions = RaySphereIntersect(rayOrigin, rayDirection, planetCenterWorld, cloudBottomRadius);
|
||||
if (tBottomSolutions.x > 0.0 || tBottomSolutions.y > 0.0)
|
||||
{
|
||||
// If we see both intersections on the screen, keep the min closest, otherwise the max furthest
|
||||
float tempTop = all(tTopSolutions > 0.0f) ? min(tTopSolutions.x, tTopSolutions.y) : max(tTopSolutions.x, tTopSolutions.y);
|
||||
float tempBottom = all(tBottomSolutions > 0.0f) ? min(tBottomSolutions.x, tBottomSolutions.y) : max(tBottomSolutions.x, tBottomSolutions.y);
|
||||
|
||||
// But if we can see the bottom of the layer, make sure we use the camera view or the highest top layer intersection
|
||||
if (all(tBottomSolutions > 0.0f))
|
||||
{
|
||||
tempTop = max(0.0f, min(tTopSolutions.x, tTopSolutions.y));
|
||||
}
|
||||
|
||||
tMin = min(tempBottom, tempTop);
|
||||
tMax = max(tempBottom, tempTop);
|
||||
}
|
||||
else
|
||||
{
|
||||
tMin = tTopSolutions.x;
|
||||
tMax = tTopSolutions.y;
|
||||
}
|
||||
|
||||
tMin = max(0.0, tMin);
|
||||
tMax = max(0.0, tMax);
|
||||
|
||||
float3 worldPositionClosestToCloudLayer = rayOrigin + rayDirection * tMin; // Determined by tMin
|
||||
|
||||
// Wind animation offsets
|
||||
float3 windDirection = float3(cos(GetWeather().volumetric_clouds.WindAngle), -GetWeather().volumetric_clouds.WindUpAmount, sin(GetWeather().volumetric_clouds.WindAngle));
|
||||
float3 windOffset = GetWeather().volumetric_clouds.WindSpeed * GetWeather().volumetric_clouds.AnimationMultiplier * windDirection * GetFrame().time;
|
||||
|
||||
float2 coverageWindDirection = float2(cos(GetWeather().volumetric_clouds.CoverageWindAngle), sin(GetWeather().volumetric_clouds.CoverageWindAngle));
|
||||
float2 coverageWindOffset = GetWeather().volumetric_clouds.CoverageWindSpeed * GetWeather().volumetric_clouds.AnimationMultiplier * coverageWindDirection * GetFrame().time;
|
||||
|
||||
// Render
|
||||
VolumetricShadowMap(result, parameters, worldPositionClosestToCloudLayer, GetSunDirection(), tMin, tMax, windOffset, windDirection, coverageWindOffset);
|
||||
}
|
||||
|
||||
// Output
|
||||
texture_render[DTid.xy] = result;
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
#include "globals.hlsli"
|
||||
#include "ShaderInterop_Postprocess.h"
|
||||
|
||||
PUSHCONSTANT(postprocess, PostProcess);
|
||||
|
||||
Texture2D<float4> cloud_reproject : register(t0);
|
||||
Texture2D<float2> cloud_reproject_depth : register(t1);
|
||||
Texture2D<float4> cloud_history : register(t2);
|
||||
|
||||
RWTexture2D<float4> output : register(u0);
|
||||
RWTexture2D<unorm float4> output_cloudMask : register(u1);
|
||||
|
||||
|
||||
// If the clouds are moving fast, the upsampling will most likely not be able to keep up. You can modify these values to relax the effect:
|
||||
static const float temporalResponse = 0.05;
|
||||
static const float temporalScale = 2.0;
|
||||
static const float temporalExposure = 10.0;
|
||||
|
||||
// Different aabb clipping method from eg. SSR temporal, suitable for clouds in this case
|
||||
float4 clip_aabb(float4 aabb_min, float4 aabb_max, float4 prev_sample)
|
||||
{
|
||||
float4 p_clip = 0.5 * (aabb_max + aabb_min);
|
||||
float4 e_clip = 0.5 * (aabb_max - aabb_min) + 0.00000001f;
|
||||
|
||||
float4 v_clip = prev_sample - p_clip;
|
||||
float4 v_unit = v_clip / e_clip;
|
||||
float4 a_unit = abs(v_unit);
|
||||
float ma_unit = max(max(a_unit.x, max(a_unit.y, a_unit.z)), a_unit.w);
|
||||
|
||||
if (ma_unit > 1.0)
|
||||
return p_clip + v_clip / ma_unit;
|
||||
else
|
||||
return prev_sample; // point inside aabb
|
||||
}
|
||||
|
||||
inline void ResolverAABB(Texture2D<float4> currentColor, SamplerState currentSampler, float sharpness, float exposureScale, float AABBScale, float2 uv, float2 texelSize, inout float4 currentMin, inout float4 currentMax, inout float4 currentAverage, inout float4 currentOutput)
|
||||
{
|
||||
const int2 SampleOffset[9] = { int2(-1.0, -1.0), int2(0.0, -1.0), int2(1.0, -1.0), int2(-1.0, 0.0), int2(0.0, 0.0), int2(1.0, 0.0), int2(-1.0, 1.0), int2(0.0, 1.0), int2(1.0, 1.0) };
|
||||
|
||||
// Modulate Luma HDR
|
||||
|
||||
float4 sampleColors[9];
|
||||
[unroll]
|
||||
for (uint i = 0; i < 9; i++)
|
||||
{
|
||||
sampleColors[i] = currentColor.SampleLevel(currentSampler, uv + (SampleOffset[i] / texelSize), 0.0f);
|
||||
}
|
||||
|
||||
|
||||
#if 0 // Exaggerates outline between clouds and geometry
|
||||
float sampleWeights[9];
|
||||
[unroll]
|
||||
for (uint j = 0; j < 9; j++)
|
||||
{
|
||||
sampleWeights[j] = HdrWeight4(sampleColors[j].rgb, exposureScale);
|
||||
}
|
||||
|
||||
float totalWeight = 0;
|
||||
[unroll]
|
||||
for (uint k = 0; k < 9; k++)
|
||||
{
|
||||
totalWeight += sampleWeights[k];
|
||||
}
|
||||
sampleColors[4] = (sampleColors[0] * sampleWeights[0] + sampleColors[1] * sampleWeights[1] + sampleColors[2] * sampleWeights[2] + sampleColors[3] * sampleWeights[3] + sampleColors[4] * sampleWeights[4] +
|
||||
sampleColors[5] * sampleWeights[5] + sampleColors[6] * sampleWeights[6] + sampleColors[7] * sampleWeights[7] + sampleColors[8] * sampleWeights[8]) / totalWeight;
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 // Standard clipping
|
||||
|
||||
// Variance Clipping (AABB)
|
||||
|
||||
float4 m1 = 0.0;
|
||||
float4 m2 = 0.0;
|
||||
[unroll]
|
||||
for (uint x = 0; x < 9; x++)
|
||||
{
|
||||
m1 += sampleColors[x];
|
||||
m2 += sampleColors[x] * sampleColors[x];
|
||||
}
|
||||
|
||||
float4 mean = m1 / 9.0;
|
||||
float4 stddev = sqrt((m2 / 9.0) - sqr(mean));
|
||||
|
||||
#else // Depth check
|
||||
|
||||
float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1).r; // Half res
|
||||
float3 depthWorldPosition = reconstruct_position(uv, depth);
|
||||
float tToDepthBuffer = length(depthWorldPosition - GetCamera().position);
|
||||
|
||||
float validSampleCount = 1.0;
|
||||
|
||||
float4 m1 = 0.0;
|
||||
float4 m2 = 0.0;
|
||||
[unroll]
|
||||
for (uint x = 0; x < 9; x++)
|
||||
{
|
||||
if (x == 4)
|
||||
{
|
||||
m1 += sampleColors[x];
|
||||
m2 += sampleColors[x] * sampleColors[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
float2 reprojectionDepthResults = cloud_reproject_depth.SampleLevel(sampler_point_clamp, uv + (SampleOffset[x] / texelSize), 1);
|
||||
if (abs(tToDepthBuffer - reprojectionDepthResults.y) < tToDepthBuffer * 0.1)
|
||||
{
|
||||
m1 += sampleColors[x];
|
||||
m2 += sampleColors[x] * sampleColors[x];
|
||||
validSampleCount += 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float4 mean = m1 / validSampleCount;
|
||||
float4 stddev = sqrt((m2 / validSampleCount) - sqr(mean));
|
||||
|
||||
#endif
|
||||
|
||||
currentMin = mean - AABBScale * stddev;
|
||||
currentMax = mean + AABBScale * stddev;
|
||||
|
||||
currentOutput = sampleColors[4];
|
||||
currentMin = min(currentMin, currentOutput);
|
||||
currentMax = max(currentMax, currentOutput);
|
||||
currentAverage = mean;
|
||||
}
|
||||
|
||||
// Computes post-projection depth from linear depth
|
||||
float getInverseLinearDepth(float lin, float near, float far)
|
||||
{
|
||||
float z_n = ((lin - 2 * far) * near + far * lin) / (lin * near - far * lin);
|
||||
float z = (z_n + 1) / 2;
|
||||
return z;
|
||||
}
|
||||
|
||||
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
|
||||
void main(uint3 DTid : SV_DispatchThreadID)
|
||||
{
|
||||
const float2 uv = (DTid.xy + 0.5f) * postprocess.resolution_rcp;
|
||||
|
||||
#if 0
|
||||
|
||||
// Calculate screen dependant motion vector
|
||||
float4 prevPos = float4(uv * 2.0 - 1.0, 1.0, 1.0);
|
||||
prevPos = mul(GetCamera().inverse_projection, prevPos);
|
||||
prevPos = prevPos / prevPos.w;
|
||||
|
||||
prevPos.xyz = mul((float3x3)GetCamera().inverse_view, prevPos.xyz);
|
||||
prevPos.xyz = mul((float3x3)GetCamera().previous_view, prevPos.xyz);
|
||||
|
||||
float4 reproj = mul(GetCamera().projection, prevPos);
|
||||
reproj /= reproj.w;
|
||||
|
||||
float2 prevUV = reproj.xy * 0.5 + 0.5;
|
||||
|
||||
#else
|
||||
|
||||
// We must recalculate motion with new upscaled cloud depths:
|
||||
|
||||
float x = uv.x * 2 - 1;
|
||||
float y = (1 - uv.y) * 2 - 1;
|
||||
float2 screenPosition = float2(x, y);
|
||||
|
||||
float currentCloudLinearDepth = cloud_reproject_depth[DTid.xy].x;
|
||||
float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, GetCamera().z_near, GetCamera().z_far);
|
||||
|
||||
float4 thisClip = float4(screenPosition, currentCloudDepth, 1.0);
|
||||
|
||||
float4 prevClip = mul(GetCamera().inverse_view_projection, thisClip);
|
||||
prevClip = mul(GetCamera().previous_view_projection, prevClip);
|
||||
|
||||
//float4 prevClip = mul(GetCamera().previous_view_projection, worldPosition);
|
||||
float2 prevScreen = prevClip.xy / prevClip.w;
|
||||
|
||||
float2 screenVelocity = screenPosition - prevScreen;
|
||||
float2 prevScreenPosition = screenPosition - screenVelocity;
|
||||
|
||||
// Transform from screen position to uv
|
||||
float2 prevUV = prevScreenPosition * float2(0.5, -0.5) + 0.5;
|
||||
|
||||
#endif
|
||||
|
||||
float4 previous = cloud_history.SampleLevel(sampler_linear_clamp, prevUV, 0);
|
||||
|
||||
float4 current = 0;
|
||||
float4 currentMin, currentMax, currentAverage;
|
||||
ResolverAABB(cloud_reproject, sampler_point_clamp, 0, temporalExposure, temporalScale, uv, postprocess.resolution, currentMin, currentMax, currentAverage, current);
|
||||
|
||||
//previous = clip_aabb(currentMin.xyz, currentMax.xyz, clamp(currentAverage, currentMin, currentMax), previous);
|
||||
previous = clip_aabb(currentMin, currentMax, previous);
|
||||
|
||||
float4 result = lerp(previous, current, temporalResponse);
|
||||
|
||||
result = (is_saturated(prevUV) && volumetricclouds_frame > 0) ? result : current;
|
||||
|
||||
output[DTid.xy] = result;
|
||||
|
||||
[branch]
|
||||
if (DTid.x % 2 == 0 && DTid.y % 2 == 0)
|
||||
{
|
||||
// the mask is half the resolution of the clouds
|
||||
output_cloudMask[DTid.xy / 2] = pow(saturate(1 - result.a), 64);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
const float depthOffset4 = 200.0;
|
||||
|
||||
const float totalSize = 3.0; // Adjust the overall size for all channels
|
||||
const float coveragePerlinWorleyDifference = 0.7; // For more bigger and mean clouds, you can use something like 0.9 or 1.0
|
||||
const float coveragePerlinWorleyDifference = 0.4; // For more bigger and mean clouds, you can use something like 0.9 or 1.0
|
||||
const float worleySeed = 1.0; // Randomize the worley coverage noise with a seed.
|
||||
|
||||
const float totalRemapLow = 0.5;
|
||||
@@ -53,6 +53,8 @@ void main(uint3 DTid : SV_DispatchThreadID)
|
||||
|
||||
perlinNoise1 -= perlinNoise4;
|
||||
perlinNoise2 -= pow(perlinNoise4, 2.0);
|
||||
|
||||
|
||||
perlinNoise1 = RemapClamped(perlinNoise1 * 2.0, 0.0, 1.0, 0.05, 1.0);
|
||||
|
||||
output[DTid.xy] = float4(perlinNoise1, perlinNoise2, perlinNoise3, 1.0);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#ifndef WI_VOLUMETRICCLOUDS_HF
|
||||
#define WI_VOLUMETRICCLOUDS_HF
|
||||
#include "globals.hlsli"
|
||||
|
||||
#define HALF_FLT_MAX 65504.0
|
||||
|
||||
// Amazing noise and weather creation, modified from: https://github.com/greje656/clouds
|
||||
|
||||
@@ -351,4 +354,137 @@ float DilatePerlinWorley(float p, float w, float x)
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WI_VOLUMETRICCLOUDS_HF
|
||||
// Calculates checkerboard undersampling position
|
||||
int ComputeCheckerBoardIndex(int2 renderCoord, int subPixelIndex)
|
||||
{
|
||||
const int localOffset = (renderCoord.x & 1 + renderCoord.y & 1) & 1;
|
||||
const int checkerBoardLocation = (subPixelIndex + localOffset) & 0x3;
|
||||
return checkerBoardLocation;
|
||||
}
|
||||
|
||||
////////////////////////////////////// Cloud Model ////////////////////////////////////////////////
|
||||
|
||||
float GetHeightFractionForPoint(AtmosphereParameters atmosphere, float3 pos)
|
||||
{
|
||||
float planetRadius = atmosphere.bottomRadius * SKY_UNIT_TO_M;
|
||||
float3 planetCenterWorld = atmosphere.planetCenter * SKY_UNIT_TO_M;
|
||||
|
||||
return saturate((distance(pos, planetCenterWorld) - (planetRadius + GetWeather().volumetric_clouds.CloudStartHeight)) / GetWeather().volumetric_clouds.CloudThickness);
|
||||
}
|
||||
|
||||
float SampleGradient(float4 gradient, float heightFraction)
|
||||
{
|
||||
return smoothstep(gradient.x, gradient.y, heightFraction) - smoothstep(gradient.z, gradient.w, heightFraction);
|
||||
}
|
||||
|
||||
float GetDensityHeightGradient(float heightFraction, float3 weatherData)
|
||||
{
|
||||
float cloudType = weatherData.g;
|
||||
|
||||
float smallType = 1.0f - saturate(cloudType * 2.0f);
|
||||
float mediumType = 1.0f - abs(cloudType - 0.5f) * 2.0f;
|
||||
float largeType = saturate(cloudType - 0.5f) * 2.0f;
|
||||
|
||||
float4 cloudGradient =
|
||||
(GetWeather().volumetric_clouds.CloudGradientSmall * smallType) +
|
||||
(GetWeather().volumetric_clouds.CloudGradientMedium * mediumType) +
|
||||
(GetWeather().volumetric_clouds.CloudGradientLarge * largeType);
|
||||
|
||||
return SampleGradient(cloudGradient, heightFraction);
|
||||
}
|
||||
|
||||
float3 SampleWeather(Texture2D<float4> texture_weatherMap, float3 pos, float heightFraction, float2 coverageWindOffset)
|
||||
{
|
||||
float4 weatherData = texture_weatherMap.SampleLevel(sampler_linear_wrap, (pos.xz + coverageWindOffset) * GetWeather().volumetric_clouds.WeatherScale, 0);
|
||||
|
||||
// Apply effects for coverage
|
||||
weatherData.r = RemapClamped(weatherData.r * GetWeather().volumetric_clouds.CoverageAmount, 0.0, 1.0, GetWeather().volumetric_clouds.CoverageMinimum, 1.0);
|
||||
weatherData.g = RemapClamped(weatherData.g * GetWeather().volumetric_clouds.TypeAmount, 0.0, 1.0, GetWeather().volumetric_clouds.TypeMinimum, 1.0);
|
||||
|
||||
// Apply anvil clouds to coverage
|
||||
weatherData.r = pow(weatherData.r, max(Remap(pow(1.0 - heightFraction, GetWeather().volumetric_clouds.AnvilOverhangHeight), 0.7, 0.8, 1.0, GetWeather().volumetric_clouds.AnvilAmount + 1.0), 0.0));
|
||||
|
||||
return weatherData.rgb;
|
||||
}
|
||||
|
||||
float WeatherDensity(float3 weatherData)
|
||||
{
|
||||
const float wetness = saturate(weatherData.b);
|
||||
return lerp(1.0, 1.0 - GetWeather().volumetric_clouds.WeatherDensityAmount, wetness);
|
||||
}
|
||||
|
||||
float SampleCloudDensity(Texture3D<float4> texture_shapeNoise, Texture3D<float4> texture_detailNoise, Texture2D<float4> texture_curlNoise, float3 p, float heightFraction, float3 weatherData, float3 windOffset, float3 windDirection, float lod, bool sampleDetail)
|
||||
{
|
||||
float3 pos = p + windOffset;
|
||||
pos += heightFraction * windDirection * GetWeather().volumetric_clouds.SkewAlongWindDirection;
|
||||
|
||||
float4 lowFrequencyNoises = texture_shapeNoise.SampleLevel(sampler_linear_wrap, pos * GetWeather().volumetric_clouds.TotalNoiseScale, lod);
|
||||
|
||||
// Create an FBM out of the low-frequency Perlin-Worley Noises
|
||||
float lowFrequencyFBM = (lowFrequencyNoises.g * 0.625) + (lowFrequencyNoises.b * 0.25) + (lowFrequencyNoises.a * 0.125);
|
||||
lowFrequencyFBM = saturate(lowFrequencyFBM);
|
||||
|
||||
float cloudSample = Remap(lowFrequencyNoises.r, -(1.0 - lowFrequencyFBM), 1.0, 0.0, 1.0);
|
||||
|
||||
// Apply height gradients
|
||||
float densityHeightGradient = GetDensityHeightGradient(heightFraction, weatherData);
|
||||
cloudSample *= densityHeightGradient;
|
||||
|
||||
float cloudCoverage = weatherData.r;
|
||||
|
||||
// Apply Coverage to sample
|
||||
cloudSample = Remap(cloudSample, 1.0 - cloudCoverage, 1.0, 0.0, 1.0);
|
||||
cloudSample *= cloudCoverage;
|
||||
|
||||
// Erode with detail noise if cloud sample > 0
|
||||
if (cloudSample > 0.0 && sampleDetail)
|
||||
{
|
||||
// Apply our curl noise to erode with tiny details.
|
||||
float3 curlNoise = DecodeCurlNoise(texture_curlNoise.SampleLevel(sampler_linear_wrap, p.xz * GetWeather().volumetric_clouds.CurlScale * GetWeather().volumetric_clouds.TotalNoiseScale, 0).rgb);
|
||||
pos += float3(curlNoise.r, curlNoise.b, curlNoise.g) * (1.0 - heightFraction) * GetWeather().volumetric_clouds.CurlNoiseModifier;
|
||||
|
||||
float3 highFrequencyNoises = texture_detailNoise.SampleLevel(sampler_linear_wrap, pos * GetWeather().volumetric_clouds.DetailScale * GetWeather().volumetric_clouds.TotalNoiseScale, lod).rgb;
|
||||
|
||||
// Create an FBM out of the high-frequency Worley Noises
|
||||
float highFrequencyFBM = (highFrequencyNoises.r * 0.625) + (highFrequencyNoises.g * 0.25) + (highFrequencyNoises.b * 0.125);
|
||||
highFrequencyFBM = saturate(highFrequencyFBM);
|
||||
|
||||
// Dilate detail noise based on height
|
||||
float highFrequenceNoiseModifier = lerp(1.0 - highFrequencyFBM, highFrequencyFBM, saturate(heightFraction * GetWeather().volumetric_clouds.DetailNoiseHeightFraction));
|
||||
|
||||
// Erode with base of clouds
|
||||
cloudSample = Remap(cloudSample, highFrequenceNoiseModifier * GetWeather().volumetric_clouds.DetailNoiseModifier, 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
return max(cloudSample, 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////// Shadow ////////////////////////////////////////////////
|
||||
|
||||
inline float shadow_2D_volumetricclouds(float3 P)
|
||||
{
|
||||
// Project into shadow map space (no need to divide by .w because ortho projection!):
|
||||
float3 shadow_pos = mul(GetFrame().cloudShadowLightSpaceMatrix, float4(P, 1)).xyz;
|
||||
float3 shadow_uv = clipspace_to_uv(shadow_pos);
|
||||
|
||||
[branch]
|
||||
if (is_saturated(shadow_uv))
|
||||
{
|
||||
float cloudShadowSampleZ = shadow_pos.z;
|
||||
|
||||
Texture2D texture_volumetricclouds_shadow = bindless_textures[GetFrame().texture_volumetricclouds_shadow_index];
|
||||
float3 cloudShadowData = texture_volumetricclouds_shadow.SampleLevel(sampler_linear_clamp, shadow_uv.xy, 0.0f).rgb;
|
||||
|
||||
float sampleDepthKm = saturate(1.0 - cloudShadowSampleZ) * GetFrame().cloudShadowFarPlaneKm;
|
||||
|
||||
float opticalDepth = cloudShadowData.g * (max(0.0f, cloudShadowData.r - sampleDepthKm) * SKY_UNIT_TO_M);
|
||||
opticalDepth = min(cloudShadowData.b, opticalDepth);
|
||||
|
||||
float transmittance = saturate(exp(-opticalDepth));
|
||||
return transmittance;
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
#endif // WI_VOLUMETRICCLOUDS_HF
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define DISABLE_SOFT_SHADOWMAP
|
||||
#define TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK // fix the lack of depth testing
|
||||
#include "volumetricLightHF.hlsli"
|
||||
#include "volumetricCloudsHF.hlsli"
|
||||
|
||||
float4 main(VertexToPixel input) : SV_TARGET
|
||||
{
|
||||
@@ -38,7 +39,7 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
for (uint i = 0; i < sampleCount; ++i)
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
|
||||
for (uint cascade = 0; cascade < GetFrame().shadow_cascade_count; ++cascade)
|
||||
{
|
||||
float3 shadow_pos = mul(load_entitymatrix(light.GetMatrixIndex() + cascade), float4(P, 1)).xyz; // ortho matrix, no divide by .w
|
||||
@@ -49,6 +50,11 @@ float4 main(VertexToPixel input) : SV_TARGET
|
||||
{
|
||||
float3 attenuation = shadow_2D(light, shadow_pos, shadow_uv.xy, cascade);
|
||||
|
||||
if (GetFrame().options & OPTION_BIT_VOLUMETRICCLOUDS_SHADOWS)
|
||||
{
|
||||
attenuation *= shadow_2D_volumetricclouds(P);
|
||||
}
|
||||
|
||||
// Evaluate sample height for height fog calculation, given 0 for V:
|
||||
attenuation *= GetFogAmount(cameraDistance - marchedDistance, P, float3(0.0, 0.0, 0.0));
|
||||
attenuation *= scattering;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace wi
|
||||
{
|
||||
|
||||
// this should always be only INCREMENTED and only if a new serialization is implemeted somewhere!
|
||||
static constexpr uint64_t __archiveVersion = 85;
|
||||
static constexpr uint64_t __archiveVersion = 86;
|
||||
// this is the version number of which below the archive is not compatible with the current version
|
||||
static constexpr uint64_t __archiveVersionBarrier = 22;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace wi::enums
|
||||
{
|
||||
TEXTYPE_3D_VOXELRADIANCE,
|
||||
TEXTYPE_3D_VOXELRADIANCE_HELPER,
|
||||
TEXTYPE_2D_VOLUMETRICCLOUDS_SHADOW,
|
||||
TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT,
|
||||
TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT,
|
||||
TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT,
|
||||
@@ -316,8 +317,11 @@ namespace wi::enums
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_CURLNOISE,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_WEATHERMAP,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_RENDER,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_RENDER_CAPTURE,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_RENDER_CAPTURE_MSAA,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_REPROJECT,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_TEMPORAL,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_SHADOW_RENDER,
|
||||
CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_SHADOW_FILTER,
|
||||
CSTYPE_POSTPROCESS_FXAA,
|
||||
CSTYPE_POSTPROCESS_TEMPORALAA,
|
||||
CSTYPE_POSTPROCESS_SHARPEN,
|
||||
|
||||
@@ -631,7 +631,8 @@ namespace wi::graphics
|
||||
{
|
||||
RENDERTARGET,
|
||||
DEPTH_STENCIL,
|
||||
RESOLVE,
|
||||
RESOLVE, // resolve render target (color)
|
||||
RESOLVE_DEPTH,
|
||||
SHADING_RATE_SOURCE
|
||||
} type = Type::RENDERTARGET;
|
||||
enum class LoadOp
|
||||
@@ -650,6 +651,11 @@ namespace wi::graphics
|
||||
ResourceState initial_layout = ResourceState::UNDEFINED; // layout before the render pass
|
||||
ResourceState subpass_layout = ResourceState::UNDEFINED; // layout within the render pass
|
||||
ResourceState final_layout = ResourceState::UNDEFINED; // layout after the render pass
|
||||
enum class DepthResolveMode
|
||||
{
|
||||
Min,
|
||||
Max,
|
||||
} depth_resolve_mode = DepthResolveMode::Min;
|
||||
|
||||
static RenderPassAttachment RenderTarget(
|
||||
const Texture* resource = nullptr,
|
||||
@@ -711,6 +717,24 @@ namespace wi::graphics
|
||||
return attachment;
|
||||
}
|
||||
|
||||
static RenderPassAttachment ResolveDepth(
|
||||
const Texture* resource = nullptr,
|
||||
DepthResolveMode depth_resolve_mode = DepthResolveMode::Min,
|
||||
ResourceState initial_layout = ResourceState::SHADER_RESOURCE,
|
||||
ResourceState final_layout = ResourceState::SHADER_RESOURCE,
|
||||
int subresource_SRV = -1
|
||||
)
|
||||
{
|
||||
RenderPassAttachment attachment;
|
||||
attachment.type = Type::RESOLVE_DEPTH;
|
||||
attachment.texture = resource;
|
||||
attachment.initial_layout = initial_layout;
|
||||
attachment.final_layout = final_layout;
|
||||
attachment.subresource = subresource_SRV;
|
||||
attachment.depth_resolve_mode = depth_resolve_mode;
|
||||
return attachment;
|
||||
}
|
||||
|
||||
static RenderPassAttachment ShadingRateSource(
|
||||
const Texture* resource = nullptr,
|
||||
ResourceState initial_layout = ResourceState::SHADING_RATE_SOURCE,
|
||||
|
||||
@@ -1486,6 +1486,7 @@ namespace dx12_internal
|
||||
|
||||
// Due to a API bug, this resolve_subresources array must be kept alive between BeginRenderpass() and EndRenderpass()!
|
||||
wi::vector<D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS> resolve_subresources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
|
||||
wi::vector<D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS> resolve_subresources_dsv = {};
|
||||
};
|
||||
struct SwapChain_DX12
|
||||
{
|
||||
@@ -2024,6 +2025,7 @@ using namespace dx12_internal;
|
||||
for (auto& attachment : commandlist.active_renderpass->desc.attachments)
|
||||
{
|
||||
if (attachment.type == RenderPassAttachment::Type::RESOLVE ||
|
||||
attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH ||
|
||||
attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE ||
|
||||
attachment.texture == nullptr)
|
||||
continue;
|
||||
@@ -3835,11 +3837,10 @@ using namespace dx12_internal;
|
||||
const SingleDescriptor& src_descriptor = src_subresource < 0 ? src_internal->rtv : src_internal->subresources_rtv[src_subresource];
|
||||
|
||||
D3D12_RENDER_PASS_RENDER_TARGET_DESC& src_RTV = internal_state->RTVs[resolve_src_counter];
|
||||
src_RTV.EndingAccess.Resolve.PreserveResolveSource = src_RTV.EndingAccess.Type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE;
|
||||
src_RTV.EndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
|
||||
src_RTV.EndingAccess.Resolve.Format = clear_value.Format;
|
||||
src_RTV.EndingAccess.Resolve.PreserveResolveSource = src.storeop == RenderPassAttachment::StoreOp::STORE ? TRUE : FALSE;
|
||||
src_RTV.EndingAccess.Resolve.Format = src_descriptor.rtv.Format;
|
||||
src_RTV.EndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_AVERAGE;
|
||||
src_RTV.EndingAccess.Resolve.PreserveResolveSource = src_RTV.EndingAccess.Type == D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD ? FALSE : TRUE;
|
||||
src_RTV.EndingAccess.Resolve.pDstResource = texture_internal->resource.Get();
|
||||
src_RTV.EndingAccess.Resolve.pSrcResource = src_internal->resource.Get();
|
||||
|
||||
@@ -3867,6 +3868,63 @@ using namespace dx12_internal;
|
||||
}
|
||||
resolve_dst_counter++;
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
if (texture != nullptr)
|
||||
{
|
||||
for (auto& src : renderpass->desc.attachments)
|
||||
{
|
||||
if (src.type == RenderPassAttachment::Type::DEPTH_STENCIL && src.texture != nullptr)
|
||||
{
|
||||
auto src_internal = to_internal(src.texture);
|
||||
int src_subresource = src.subresource;
|
||||
const SingleDescriptor& src_descriptor = src_subresource < 0 ? src_internal->dsv : src_internal->subresources_dsv[src_subresource];
|
||||
|
||||
D3D12_RENDER_PASS_DEPTH_STENCIL_DESC& src_DSV = internal_state->DSV;
|
||||
src_DSV.DepthEndingAccess.Type = D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_RESOLVE;
|
||||
src_DSV.DepthEndingAccess.Resolve.PreserveResolveSource = src.storeop == RenderPassAttachment::StoreOp::STORE ? TRUE : FALSE;
|
||||
src_DSV.DepthEndingAccess.Resolve.Format = src_descriptor.dsv.Format;
|
||||
|
||||
switch (attachment.depth_resolve_mode)
|
||||
{
|
||||
default:
|
||||
case RenderPassAttachment::DepthResolveMode::Min:
|
||||
src_DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MIN;
|
||||
break;
|
||||
case RenderPassAttachment::DepthResolveMode::Max:
|
||||
src_DSV.DepthEndingAccess.Resolve.ResolveMode = D3D12_RESOLVE_MODE_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
src_DSV.DepthEndingAccess.Resolve.pDstResource = texture_internal->resource.Get();
|
||||
src_DSV.DepthEndingAccess.Resolve.pSrcResource = src_internal->resource.Get();
|
||||
|
||||
const SingleDescriptor& dst_descriptor = subresource < 0 ? texture_internal->srv : texture_internal->subresources_srv[subresource];
|
||||
for (uint32_t mip = 0; mip < std::min(attachment.texture->desc.mip_levels, dst_descriptor.mipCount); ++mip)
|
||||
{
|
||||
for (uint32_t slice = 0; slice < std::min(attachment.texture->desc.array_size, dst_descriptor.sliceCount); ++slice)
|
||||
{
|
||||
D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_SUBRESOURCE_PARAMETERS& params = internal_state->resolve_subresources_dsv.emplace_back();
|
||||
params.SrcSubresource = D3D12CalcSubresource(src_descriptor.firstMip + mip, src_descriptor.firstSlice + slice, 0, src.texture->desc.mip_levels, src.texture->desc.array_size);
|
||||
params.DstSubresource = D3D12CalcSubresource(dst_descriptor.firstMip + mip, dst_descriptor.firstSlice + slice, 0, texture->desc.mip_levels, texture->desc.array_size);
|
||||
params.SrcRect.left = 0;
|
||||
params.SrcRect.top = 0;
|
||||
params.SrcRect.right = (LONG)texture->desc.width;
|
||||
params.SrcRect.bottom = (LONG)texture->desc.height;
|
||||
}
|
||||
}
|
||||
src_DSV.DepthEndingAccess.Resolve.SubresourceCount = (UINT)internal_state->resolve_subresources_dsv.size();
|
||||
src_DSV.DepthEndingAccess.Resolve.pSubresourceParameters = internal_state->resolve_subresources_dsv.data();
|
||||
if (IsFormatStencilSupport(attachment.texture->desc.format))
|
||||
{
|
||||
src_DSV.StencilBeginningAccess = src_DSV.DepthBeginningAccess;
|
||||
src_DSV.StencilEndingAccess = src_DSV.DepthEndingAccess;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE)
|
||||
{
|
||||
internal_state->shading_rate_image = texture;
|
||||
@@ -3881,7 +3939,11 @@ using namespace dx12_internal;
|
||||
continue;
|
||||
|
||||
D3D12_RESOURCE_STATES before = _ParseResourceState(attachment.initial_layout);
|
||||
D3D12_RESOURCE_STATES after = attachment.type == RenderPassAttachment::Type::RESOLVE ? D3D12_RESOURCE_STATE_RESOLVE_DEST : _ParseResourceState(attachment.subpass_layout);
|
||||
D3D12_RESOURCE_STATES after = _ParseResourceState(attachment.subpass_layout);
|
||||
if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
after = D3D12_RESOURCE_STATE_RESOLVE_DEST;
|
||||
}
|
||||
if (before == after)
|
||||
continue;
|
||||
|
||||
@@ -3906,7 +3968,7 @@ using namespace dx12_internal;
|
||||
{
|
||||
descriptor = &texture_internal->subresources_dsv[attachment.subresource];
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE)
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
// Single barrier for whole resource:
|
||||
// From debug layer it looks like the resolve operation requires entire resource to be in RESOLVE_DEST
|
||||
@@ -3943,8 +4005,12 @@ using namespace dx12_internal;
|
||||
if (attachment.texture == nullptr)
|
||||
continue;
|
||||
|
||||
D3D12_RESOURCE_STATES before = attachment.type == RenderPassAttachment::Type::RESOLVE ? D3D12_RESOURCE_STATE_RESOLVE_DEST : _ParseResourceState(attachment.subpass_layout);
|
||||
D3D12_RESOURCE_STATES before = _ParseResourceState(attachment.subpass_layout);
|
||||
D3D12_RESOURCE_STATES after = _ParseResourceState(attachment.final_layout);
|
||||
if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
before = D3D12_RESOURCE_STATE_RESOLVE_DEST;
|
||||
}
|
||||
if (before == after)
|
||||
continue;
|
||||
|
||||
@@ -3969,7 +4035,7 @@ using namespace dx12_internal;
|
||||
{
|
||||
descriptor = &texture_internal->subresources_dsv[attachment.subresource];
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE)
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE || attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
// Single barrier for whole resource:
|
||||
// From debug layer it looks like the resolve operation requires entire resource to be in RESOLVE_DEST
|
||||
|
||||
@@ -2477,6 +2477,10 @@ using namespace vulkan_internal;
|
||||
*properties_chain = &sampler_minmax_properties;
|
||||
properties_chain = &sampler_minmax_properties.pNext;
|
||||
|
||||
depth_stencil_resolve_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
|
||||
*properties_chain = &depth_stencil_resolve_properties;
|
||||
properties_chain = &depth_stencil_resolve_properties.pNext;
|
||||
|
||||
enabled_deviceExtensions = required_deviceExtensions;
|
||||
|
||||
if (checkExtensionSupport(VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, available_deviceExtensions))
|
||||
@@ -2577,6 +2581,8 @@ using namespace vulkan_internal;
|
||||
}
|
||||
|
||||
assert(properties2.properties.limits.timestampComputeAndGraphics == VK_TRUE);
|
||||
assert(depth_stencil_resolve_properties.supportedDepthResolveModes& VK_RESOLVE_MODE_MIN_BIT);
|
||||
assert(depth_stencil_resolve_properties.supportedDepthResolveModes& VK_RESOLVE_MODE_MAX_BIT);
|
||||
|
||||
vkGetPhysicalDeviceFeatures2(physicalDevice, &features2);
|
||||
|
||||
@@ -5097,6 +5103,8 @@ using namespace vulkan_internal;
|
||||
VkAttachmentReference2 resolveAttachmentRefs[8] = {};
|
||||
VkAttachmentReference2 shadingRateAttachmentRef = {};
|
||||
VkAttachmentReference2 depthAttachmentRef = {};
|
||||
VkSubpassDescriptionDepthStencilResolve depthResolve = {};
|
||||
VkAttachmentReference2 depthResolveAttachmentRef = {};
|
||||
|
||||
VkFragmentShadingRateAttachmentInfoKHR shading_rate_attachment = {};
|
||||
shading_rate_attachment.sType = VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR;
|
||||
@@ -5109,6 +5117,7 @@ using namespace vulkan_internal;
|
||||
VkSubpassDescription2 subpass = {};
|
||||
subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
|
||||
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
const void** subpass_chain = &subpass.pNext;
|
||||
|
||||
uint32_t validAttachmentCount = 0;
|
||||
for (auto& attachment : renderpass->desc.attachments)
|
||||
@@ -5258,6 +5267,58 @@ using namespace vulkan_internal;
|
||||
resolvecount++;
|
||||
subpass.pResolveAttachments = resolveAttachmentRefs;
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::RESOLVE_DEPTH)
|
||||
{
|
||||
|
||||
if (attachment.texture == nullptr)
|
||||
{
|
||||
resolveAttachmentRefs[resolvecount].attachment = VK_ATTACHMENT_UNUSED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (subresource < 0 || texture_internal_state->subresources_srv.empty())
|
||||
{
|
||||
attachments[validAttachmentCount] = texture_internal_state->srv.image_view;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(texture_internal_state->subresources_srv.size() > size_t(subresource) && "Invalid SRV subresource!");
|
||||
attachments[validAttachmentCount] = texture_internal_state->subresources_srv[subresource].image_view;
|
||||
}
|
||||
if (attachments[validAttachmentCount] == VK_NULL_HANDLE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
depthResolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
|
||||
|
||||
switch (attachment.depth_resolve_mode)
|
||||
{
|
||||
default:
|
||||
case RenderPassAttachment::DepthResolveMode::Min:
|
||||
depthResolve.depthResolveMode = VK_RESOLVE_MODE_MIN_BIT;
|
||||
depthResolve.stencilResolveMode = VK_RESOLVE_MODE_MIN_BIT;
|
||||
break;
|
||||
case RenderPassAttachment::DepthResolveMode::Max:
|
||||
depthResolve.depthResolveMode = VK_RESOLVE_MODE_MAX_BIT;
|
||||
depthResolve.stencilResolveMode = VK_RESOLVE_MODE_MAX_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
depthResolveAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
|
||||
depthResolveAttachmentRef.attachment = validAttachmentCount;
|
||||
depthResolveAttachmentRef.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
if (IsFormatStencilSupport(attachment.texture->desc.format))
|
||||
{
|
||||
depthResolveAttachmentRef.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
}
|
||||
depthResolveAttachmentRef.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
depthResolve.pDepthStencilResolveAttachment = &depthResolveAttachmentRef;
|
||||
|
||||
*subpass_chain = &depthResolve;
|
||||
subpass_chain = &depthResolve.pNext;
|
||||
}
|
||||
else if (attachment.type == RenderPassAttachment::Type::SHADING_RATE_SOURCE && CheckCapability(GraphicsDeviceCapability::VARIABLE_RATE_SHADING_TIER2))
|
||||
{
|
||||
shadingRateAttachmentRef.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
|
||||
@@ -5286,7 +5347,8 @@ using namespace vulkan_internal;
|
||||
shadingRateAttachmentRef.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
subpass.pNext = &shading_rate_attachment;
|
||||
*subpass_chain = &shading_rate_attachment;
|
||||
subpass_chain = &shading_rate_attachment.pNext;
|
||||
}
|
||||
|
||||
validAttachmentCount++;
|
||||
|
||||
@@ -55,6 +55,7 @@ namespace wi::graphics
|
||||
VkPhysicalDeviceFragmentShadingRatePropertiesKHR fragment_shading_rate_properties = {};
|
||||
VkPhysicalDeviceMeshShaderPropertiesNV mesh_shader_properties = {};
|
||||
VkPhysicalDeviceMemoryProperties2 memory_properties_2 = {};
|
||||
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve_properties = {};
|
||||
|
||||
VkPhysicalDeviceFeatures2 features2 = {};
|
||||
VkPhysicalDeviceVulkan11Features features_1_1 = {};
|
||||
|
||||
@@ -220,7 +220,7 @@ void RenderPath3D::ResizeBuffers()
|
||||
|
||||
desc.sample_count = getMSAASampleCount();
|
||||
desc.layout = ResourceState::DEPTHSTENCIL_READONLY;
|
||||
desc.format = Format::R32G8X24_TYPELESS;
|
||||
desc.format = Format::D32_FLOAT_S8X24_UINT;
|
||||
desc.bind_flags = BindFlag::DEPTH_STENCIL;
|
||||
device->CreateTexture(&desc, nullptr, &depthBuffer_Main);
|
||||
device->SetName(&depthBuffer_Main, "depthBuffer_Main");
|
||||
@@ -918,7 +918,8 @@ void RenderPath3D::Render() const
|
||||
{
|
||||
wi::renderer::Postprocess_VolumetricClouds(
|
||||
volumetriccloudResources,
|
||||
cmd
|
||||
cmd,
|
||||
scene->weather.volumetricCloudsWeatherMap.IsValid() ? &scene->weather.volumetricCloudsWeatherMap.GetTexture() : nullptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1017,7 +1018,8 @@ void RenderPath3D::Render() const
|
||||
{
|
||||
wi::renderer::Postprocess_VolumetricClouds(
|
||||
volumetriccloudResources_reflection,
|
||||
cmd
|
||||
cmd,
|
||||
scene->weather.volumetricCloudsWeatherMap.IsValid() ? &scene->weather.volumetricCloudsWeatherMap.GetTexture() : nullptr
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1066,7 +1068,7 @@ void RenderPath3D::Render() const
|
||||
wi::image::Params fx;
|
||||
fx.enableFullScreen();
|
||||
fx.blendFlag = BLENDMODE_PREMULTIPLIED;
|
||||
wi::image::Draw(&volumetriccloudResources_reflection.texture_temporal[device->GetFrameCount() % 2], fx, cmd);
|
||||
wi::image::Draw(&volumetriccloudResources_reflection.texture_reproject[device->GetFrameCount() % 2], fx, cmd);
|
||||
device->EventEnd(cmd);
|
||||
}
|
||||
|
||||
@@ -1175,7 +1177,7 @@ void RenderPath3D::Render() const
|
||||
{
|
||||
device->EventBegin("Volumetric Clouds Upsample + Blend", cmd);
|
||||
wi::renderer::Postprocess_Upsample_Bilateral(
|
||||
volumetriccloudResources.texture_temporal[device->GetFrameCount() % 2],
|
||||
volumetriccloudResources.texture_reproject[device->GetFrameCount() % 2],
|
||||
rtLinearDepth,
|
||||
rtMain_render, // only desc is taken if pixel shader upsampling is used
|
||||
cmd,
|
||||
|
||||
+316
-72
File diff suppressed because it is too large
Load Diff
@@ -206,8 +206,13 @@ namespace wi::renderer
|
||||
// Render mip levels for textures that reqested it:
|
||||
void ProcessDeferredMipGenRequests(wi::graphics::CommandList cmd);
|
||||
|
||||
// Compute volumetric cloud shadow data
|
||||
void ComputeVolumetricCloudShadows(
|
||||
wi::graphics::CommandList cmd,
|
||||
const wi::graphics::Texture* weatherMap = nullptr
|
||||
);
|
||||
// Compute essential atmospheric scattering textures for skybox, fog and clouds
|
||||
void RenderAtmosphericScatteringTextures(wi::graphics::CommandList cmd);
|
||||
void ComputeAtmosphericScatteringTextures(wi::graphics::CommandList cmd);
|
||||
// Update atmospheric scattering primarily for environment probes.
|
||||
void RefreshAtmosphericScatteringTextures(wi::graphics::CommandList cmd);
|
||||
// Draw skydome centered to camera.
|
||||
@@ -621,13 +626,14 @@ namespace wi::renderer
|
||||
wi::graphics::Texture texture_cloudDepth;
|
||||
wi::graphics::Texture texture_reproject[2];
|
||||
wi::graphics::Texture texture_reproject_depth[2];
|
||||
wi::graphics::Texture texture_temporal[2];
|
||||
wi::graphics::Texture texture_reproject_additional[2];
|
||||
wi::graphics::Texture texture_cloudMask;
|
||||
};
|
||||
void CreateVolumetricCloudResources(VolumetricCloudResources& res, XMUINT2 resolution);
|
||||
void Postprocess_VolumetricClouds(
|
||||
const VolumetricCloudResources& res,
|
||||
wi::graphics::CommandList cmd
|
||||
wi::graphics::CommandList cmd,
|
||||
const wi::graphics::Texture* weatherMap = nullptr
|
||||
);
|
||||
void Postprocess_FXAA(
|
||||
const wi::graphics::Texture& input,
|
||||
|
||||
+22
-21
@@ -2060,17 +2060,10 @@ namespace wi::scene
|
||||
shaderscene.weather.sun_direction = weather.sunDirection;
|
||||
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;
|
||||
shaderscene.weather.cloud_speed = weather.cloudSpeed;
|
||||
shaderscene.weather.cloud_shadow_amount = weather.cloud_shadow_amount;
|
||||
shaderscene.weather.cloud_shadow_scale = weather.cloud_shadow_scale;
|
||||
shaderscene.weather.cloud_shadow_speed = weather.cloud_shadow_speed;
|
||||
shaderscene.weather.fog.start = weather.fogStart;
|
||||
shaderscene.weather.fog.end = weather.fogEnd;
|
||||
shaderscene.weather.fog.height_start = weather.fogHeightStart;
|
||||
shaderscene.weather.fog.height_end = weather.fogHeightEnd;
|
||||
shaderscene.weather.fog.height_sky = weather.fogHeightSky;
|
||||
shaderscene.weather.horizon = weather.horizon;
|
||||
shaderscene.weather.zenith = weather.zenith;
|
||||
shaderscene.weather.sky_exposure = weather.skyExposure;
|
||||
@@ -2315,9 +2308,6 @@ namespace wi::scene
|
||||
transform.UpdateTransform();
|
||||
|
||||
ForceFieldComponent& force = forces.Create(entity);
|
||||
force.gravity = 0;
|
||||
force.range = 0;
|
||||
force.type = ENTITY_TYPE_FORCEFIELD_POINT;
|
||||
|
||||
return entity;
|
||||
}
|
||||
@@ -4835,12 +4825,9 @@ namespace wi::scene
|
||||
desc.mip_levels = 1;
|
||||
desc.usage = Usage::DEFAULT;
|
||||
|
||||
desc.bind_flags = BindFlag::DEPTH_STENCIL;
|
||||
desc.format = Format::D16_UNORM;
|
||||
desc.layout = ResourceState::DEPTHSTENCIL;
|
||||
desc.misc_flags = ResourceMiscFlag::TRANSIENT_ATTACHMENT;
|
||||
device->CreateTexture(&desc, nullptr, &envrenderingDepthBuffer);
|
||||
device->SetName(&envrenderingDepthBuffer, "envrenderingDepthBuffer");
|
||||
desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE;
|
||||
desc.format = Format::R16_TYPELESS;
|
||||
desc.layout = ResourceState::SHADER_RESOURCE;
|
||||
desc.sample_count = envmapMSAASampleCount;
|
||||
device->CreateTexture(&desc, nullptr, &envrenderingDepthBuffer_MSAA);
|
||||
device->SetName(&envrenderingDepthBuffer_MSAA, "envrenderingDepthBuffer_MSAA");
|
||||
@@ -4862,17 +4849,25 @@ namespace wi::scene
|
||||
desc.misc_flags = ResourceMiscFlag::TEXTURECUBE;
|
||||
desc.usage = Usage::DEFAULT;
|
||||
desc.layout = ResourceState::SHADER_RESOURCE;
|
||||
|
||||
device->CreateTexture(&desc, nullptr, &envmapArray);
|
||||
device->SetName(&envmapArray, "envmapArray");
|
||||
|
||||
desc.array_size = 6;
|
||||
desc.mip_levels = 1;
|
||||
desc.format = Format::R16_TYPELESS;
|
||||
desc.bind_flags = BindFlag::DEPTH_STENCIL | BindFlag::SHADER_RESOURCE;
|
||||
desc.layout = ResourceState::SHADER_RESOURCE;
|
||||
device->CreateTexture(&desc, nullptr, &envrenderingDepthBuffer);
|
||||
device->SetName(&envrenderingDepthBuffer, "envrenderingDepthBuffer");
|
||||
|
||||
|
||||
// Cube arrays per mip level:
|
||||
for (uint32_t i = 0; i < envmapArray.desc.mip_levels; ++i)
|
||||
{
|
||||
int subresource_index;
|
||||
subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::SRV, 0, desc.array_size, i, 1);
|
||||
subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::SRV, 0, envmapArray.desc.array_size, i, 1);
|
||||
assert(subresource_index == i);
|
||||
subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::UAV, 0, desc.array_size, i, 1);
|
||||
subresource_index = device->CreateSubresource(&envmapArray, SubresourceType::UAV, 0, envmapArray.desc.array_size, i, 1);
|
||||
assert(subresource_index == i);
|
||||
}
|
||||
|
||||
@@ -4907,7 +4902,10 @@ namespace wi::scene
|
||||
RenderPassAttachment::DepthStencil(
|
||||
&envrenderingDepthBuffer,
|
||||
RenderPassAttachment::LoadOp::CLEAR,
|
||||
RenderPassAttachment::StoreOp::DONTCARE
|
||||
RenderPassAttachment::StoreOp::STORE,
|
||||
ResourceState::SHADER_RESOURCE,
|
||||
ResourceState::DEPTHSTENCIL,
|
||||
ResourceState::SHADER_RESOURCE
|
||||
)
|
||||
);
|
||||
renderpassdesc.attachments.push_back(
|
||||
@@ -4931,7 +4929,10 @@ namespace wi::scene
|
||||
RenderPassAttachment::DepthStencil(
|
||||
&envrenderingDepthBuffer_MSAA,
|
||||
RenderPassAttachment::LoadOp::CLEAR,
|
||||
RenderPassAttachment::StoreOp::DONTCARE
|
||||
RenderPassAttachment::StoreOp::STORE,
|
||||
ResourceState::SHADER_RESOURCE,
|
||||
ResourceState::DEPTHSTENCIL,
|
||||
ResourceState::SHADER_RESOURCE
|
||||
)
|
||||
);
|
||||
renderpassdesc.attachments.push_back(
|
||||
|
||||
+18
-14
@@ -849,6 +849,7 @@ namespace wi::scene
|
||||
VOLUMETRICS = 1 << 1,
|
||||
VISUALIZER = 1 << 2,
|
||||
LIGHTMAPONLY_STATIC = 1 << 3,
|
||||
VOLUMETRICCLOUDS = 1 << 4,
|
||||
};
|
||||
uint32_t _flags = EMPTY;
|
||||
|
||||
@@ -892,11 +893,13 @@ namespace wi::scene
|
||||
inline void SetVolumetricsEnabled(bool value) { if (value) { _flags |= VOLUMETRICS; } else { _flags &= ~VOLUMETRICS; } }
|
||||
inline void SetVisualizerEnabled(bool value) { if (value) { _flags |= VISUALIZER; } else { _flags &= ~VISUALIZER; } }
|
||||
inline void SetStatic(bool value) { if (value) { _flags |= LIGHTMAPONLY_STATIC; } else { _flags &= ~LIGHTMAPONLY_STATIC; } }
|
||||
inline void SetVolumetricCloudsEnabled(bool value) { if (value) { _flags |= VOLUMETRICCLOUDS; } else { _flags &= ~VOLUMETRICCLOUDS; } }
|
||||
|
||||
inline bool IsCastingShadow() const { return _flags & CAST_SHADOW; }
|
||||
inline bool IsVolumetricsEnabled() const { return _flags & VOLUMETRICS; }
|
||||
inline bool IsVisualizerEnabled() const { return _flags & VISUALIZER; }
|
||||
inline bool IsStatic() const { return _flags & LIGHTMAPONLY_STATIC; }
|
||||
inline bool IsVolumetricCloudsEnabled() const { return _flags & VOLUMETRICCLOUDS; }
|
||||
|
||||
inline float GetRange() const
|
||||
{
|
||||
@@ -1038,9 +1041,14 @@ namespace wi::scene
|
||||
};
|
||||
uint32_t _flags = EMPTY;
|
||||
|
||||
int type = ENTITY_TYPE_FORCEFIELD_POINT;
|
||||
float gravity = 0.0f; // negative = deflector, positive = attractor
|
||||
float range = 0.0f; // affection range
|
||||
enum class Type
|
||||
{
|
||||
Point,
|
||||
Plane,
|
||||
} type = Type::Point;
|
||||
|
||||
float gravity = 0; // negative = deflector, positive = attractor
|
||||
float range = 0; // affection range
|
||||
|
||||
// Non-serialized attributes:
|
||||
XMFLOAT3 position;
|
||||
@@ -1227,24 +1235,25 @@ namespace wi::scene
|
||||
{
|
||||
EMPTY = 0,
|
||||
OCEAN_ENABLED = 1 << 0,
|
||||
SIMPLE_SKY = 1 << 1,
|
||||
_DEPRECATED_SIMPLE_SKY = 1 << 1,
|
||||
REALISTIC_SKY = 1 << 2,
|
||||
VOLUMETRIC_CLOUDS = 1 << 3,
|
||||
HEIGHT_FOG = 1 << 4,
|
||||
VOLUMETRIC_CLOUDS_SHADOWS = 1 << 5,
|
||||
};
|
||||
uint32_t _flags = EMPTY;
|
||||
|
||||
inline bool IsOceanEnabled() const { return _flags & OCEAN_ENABLED; }
|
||||
inline bool IsSimpleSky() const { return _flags & SIMPLE_SKY; }
|
||||
inline bool IsRealisticSky() const { return _flags & REALISTIC_SKY; }
|
||||
inline bool IsVolumetricClouds() const { return _flags & VOLUMETRIC_CLOUDS; }
|
||||
inline bool IsHeightFog() const { return _flags & HEIGHT_FOG; }
|
||||
inline bool IsVolumetricCloudsShadows() const { return _flags & VOLUMETRIC_CLOUDS_SHADOWS; }
|
||||
|
||||
inline void SetOceanEnabled(bool value = true) { if (value) { _flags |= OCEAN_ENABLED; } else { _flags &= ~OCEAN_ENABLED; } }
|
||||
inline void SetSimpleSky(bool value = true) { if (value) { _flags |= SIMPLE_SKY; } else { _flags &= ~SIMPLE_SKY; } }
|
||||
inline void SetRealisticSky(bool value = true) { if (value) { _flags |= REALISTIC_SKY; } else { _flags &= ~REALISTIC_SKY; } }
|
||||
inline void SetVolumetricClouds(bool value = true) { if (value) { _flags |= VOLUMETRIC_CLOUDS; } else { _flags &= ~VOLUMETRIC_CLOUDS; } }
|
||||
inline void SetHeightFog(bool value = true) { if (value) { _flags |= HEIGHT_FOG; } else { _flags &= ~HEIGHT_FOG; } }
|
||||
inline void SetVolumetricCloudsShadows(bool value = true) { if (value) { _flags |= VOLUMETRIC_CLOUDS_SHADOWS; } else { _flags &= ~VOLUMETRIC_CLOUDS_SHADOWS; } }
|
||||
|
||||
XMFLOAT3 sunColor = XMFLOAT3(0, 0, 0);
|
||||
XMFLOAT3 sunDirection = XMFLOAT3(0, 1, 0);
|
||||
@@ -1256,13 +1265,6 @@ namespace wi::scene
|
||||
float fogEnd = 1000;
|
||||
float fogHeightStart = 1;
|
||||
float fogHeightEnd = 3;
|
||||
float fogHeightSky = 0;
|
||||
float cloudiness = 0.0f;
|
||||
float cloudScale = 0.0003f;
|
||||
float cloudSpeed = 0.1f;
|
||||
float cloud_shadow_amount = 0;
|
||||
float cloud_shadow_scale = 0.002f;
|
||||
float cloud_shadow_speed = 0.2f;
|
||||
XMFLOAT3 windDirection = XMFLOAT3(0, 0, 0);
|
||||
float windRandomness = 5;
|
||||
float windWaveSize = 1;
|
||||
@@ -1275,11 +1277,13 @@ namespace wi::scene
|
||||
|
||||
std::string skyMapName;
|
||||
std::string colorGradingMapName;
|
||||
std::string volumetricCloudsWeatherMapName;
|
||||
|
||||
// Non-serialized attributes:
|
||||
uint32_t most_important_light_index = ~0u;
|
||||
wi::Resource skyMap;
|
||||
wi::Resource colorGradingMap;
|
||||
wi::Resource volumetricCloudsWeatherMap;
|
||||
XMFLOAT4 stars_rotation_quaternion = XMFLOAT4(0, 0, 0, 1);
|
||||
|
||||
void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri);
|
||||
@@ -1554,7 +1558,7 @@ namespace wi::scene
|
||||
wi::ecs::ComponentManager<CameraComponent>& cameras = componentLibrary.Register<CameraComponent>("wi::scene::Scene::cameras");
|
||||
wi::ecs::ComponentManager<EnvironmentProbeComponent>& probes = componentLibrary.Register<EnvironmentProbeComponent>("wi::scene::Scene::probes");
|
||||
wi::ecs::ComponentManager<wi::primitive::AABB>& aabb_probes = componentLibrary.Register<wi::primitive::AABB>("wi::scene::Scene::aabb_probes");
|
||||
wi::ecs::ComponentManager<ForceFieldComponent>& forces = componentLibrary.Register<ForceFieldComponent>("wi::scene::Scene::forces");
|
||||
wi::ecs::ComponentManager<ForceFieldComponent>& forces = componentLibrary.Register<ForceFieldComponent>("wi::scene::Scene::forces", 1); // version = 1
|
||||
wi::ecs::ComponentManager<DecalComponent>& decals = componentLibrary.Register<DecalComponent>("wi::scene::Scene::decals");
|
||||
wi::ecs::ComponentManager<wi::primitive::AABB>& aabb_decals = componentLibrary.Register<wi::primitive::AABB>("wi::scene::Scene::aabb_decals");
|
||||
wi::ecs::ComponentManager<AnimationComponent>& animations = componentLibrary.Register<AnimationComponent>("wi::scene::Scene::animations");
|
||||
|
||||
@@ -3872,13 +3872,9 @@ Luna<Weather_VolumetricCloudParams_BindLua>::PropertyType Weather_VolumetricClou
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,DetailScale),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,WeatherScale),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,CurlScale),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,ShapeNoiseHeightGradientAmount),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,ShapeNoiseMultiplier),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,ShapeNoiseMinMax),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,ShapeNoisePower),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,DetailNoiseModifier),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,TypeAmount),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,TypeOverall),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,TypeMinimum),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,AnvilAmount),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,AnvilOverhangHeight),
|
||||
lunaproperty(Weather_VolumetricCloudParams_BindLua,AnimationMultiplier),
|
||||
@@ -4011,7 +4007,7 @@ int WeatherComponent_BindLua::SetOceanEnabled(lua_State* L)
|
||||
}
|
||||
int WeatherComponent_BindLua::IsSimpleSky(lua_State* L)
|
||||
{
|
||||
wi::lua::SSetBool(L, component->IsSimpleSky());
|
||||
wi::lua::SSetBool(L, !component->IsRealisticSky());
|
||||
return 1;
|
||||
}
|
||||
int WeatherComponent_BindLua::SetSimpleSky(lua_State* L)
|
||||
@@ -4020,7 +4016,7 @@ int WeatherComponent_BindLua::SetSimpleSky(lua_State* L)
|
||||
if (argc > 0)
|
||||
{
|
||||
bool value = wi::lua::SGetBool(L, 1);
|
||||
component->SetSimpleSky(value);
|
||||
component->SetRealisticSky(!value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -849,15 +849,10 @@ namespace wi::lua::scene
|
||||
|
||||
WeatherScale = FloatProperty(¶meter->WeatherScale);
|
||||
CurlScale = FloatProperty(¶meter->CurlScale);
|
||||
ShapeNoiseHeightGradientAmount = FloatProperty(¶meter->ShapeNoiseHeightGradientAmount);
|
||||
ShapeNoiseMultiplier = FloatProperty(¶meter->ShapeNoiseMultiplier);
|
||||
|
||||
ShapeNoiseMinMax = VectorProperty(¶meter->ShapeNoiseMinMax);
|
||||
ShapeNoisePower = FloatProperty(¶meter->ShapeNoisePower);
|
||||
DetailNoiseModifier = FloatProperty(¶meter->DetailNoiseModifier);
|
||||
|
||||
TypeAmount = FloatProperty(¶meter->TypeAmount);
|
||||
TypeOverall = FloatProperty(¶meter->TypeOverall);
|
||||
TypeMinimum = FloatProperty(¶meter->TypeMinimum);
|
||||
AnvilAmount = FloatProperty(¶meter->AnvilAmount);
|
||||
AnvilOverhangHeight = FloatProperty(¶meter->AnvilOverhangHeight);
|
||||
|
||||
@@ -895,15 +890,10 @@ namespace wi::lua::scene
|
||||
|
||||
FloatProperty WeatherScale;
|
||||
FloatProperty CurlScale;
|
||||
FloatProperty ShapeNoiseHeightGradientAmount;
|
||||
FloatProperty ShapeNoiseMultiplier;
|
||||
|
||||
VectorProperty ShapeNoiseMinMax;
|
||||
FloatProperty ShapeNoisePower;
|
||||
FloatProperty DetailNoiseModifier;
|
||||
|
||||
FloatProperty TypeAmount;
|
||||
FloatProperty TypeOverall;
|
||||
FloatProperty TypeMinimum;
|
||||
FloatProperty AnvilAmount;
|
||||
FloatProperty AnvilOverhangHeight;
|
||||
|
||||
@@ -935,15 +925,10 @@ namespace wi::lua::scene
|
||||
|
||||
PropertyFunction(WeatherScale)
|
||||
PropertyFunction(CurlScale)
|
||||
PropertyFunction(ShapeNoiseHeightGradientAmount)
|
||||
PropertyFunction(ShapeNoiseMultiplier)
|
||||
|
||||
PropertyFunction(ShapeNoiseMinMax)
|
||||
PropertyFunction(ShapeNoisePower)
|
||||
PropertyFunction(DetailNoiseModifier)
|
||||
|
||||
PropertyFunction(TypeAmount)
|
||||
PropertyFunction(TypeOverall)
|
||||
PropertyFunction(TypeMinimum)
|
||||
PropertyFunction(AnvilAmount)
|
||||
PropertyFunction(AnvilOverhangHeight)
|
||||
|
||||
@@ -992,13 +977,6 @@ namespace wi::lua::scene
|
||||
fogEnd = FloatProperty(&component->fogEnd);
|
||||
fogHeightStart = FloatProperty(&component->fogHeightStart);
|
||||
fogHeightEnd = FloatProperty(&component->fogHeightEnd);
|
||||
fogHeightSky = FloatProperty(&component->fogHeightSky);
|
||||
cloudiness = FloatProperty(&component->cloudiness);
|
||||
cloudScale = FloatProperty(&component->cloudScale);
|
||||
cloudSpeed = FloatProperty(&component->cloudSpeed);
|
||||
cloud_shadow_amount = FloatProperty(&component->cloud_shadow_amount);
|
||||
cloud_shadow_scale = FloatProperty(&component->cloud_shadow_scale);
|
||||
cloud_shadow_speed = FloatProperty(&component->cloud_shadow_speed);
|
||||
windDirection = VectorProperty(&component->windDirection);
|
||||
windRandomness = FloatProperty(&component->windRandomness);
|
||||
windWaveSize = FloatProperty(&component->windWaveSize);
|
||||
|
||||
@@ -900,14 +900,23 @@ namespace wi::scene
|
||||
if (archive.IsReadMode())
|
||||
{
|
||||
archive >> _flags;
|
||||
archive >> type;
|
||||
uint32_t value;
|
||||
archive >> value;
|
||||
if (seri.GetVersion() < 1)
|
||||
{
|
||||
if (value == 200)
|
||||
value = 0;
|
||||
if (value == 201)
|
||||
value = 1;
|
||||
}
|
||||
type = (Type)value;
|
||||
archive >> gravity;
|
||||
archive >> range;
|
||||
}
|
||||
else
|
||||
{
|
||||
archive << _flags;
|
||||
archive << type;
|
||||
archive << (uint32_t)type;
|
||||
archive << gravity;
|
||||
archive << range;
|
||||
}
|
||||
@@ -1034,10 +1043,17 @@ namespace wi::scene
|
||||
archive >> ambient;
|
||||
archive >> fogStart;
|
||||
archive >> fogEnd;
|
||||
archive >> fogHeightSky;
|
||||
archive >> cloudiness;
|
||||
archive >> cloudScale;
|
||||
archive >> cloudSpeed;
|
||||
if (archive.GetVersion() < 86)
|
||||
{
|
||||
float fogHeightSky;
|
||||
float cloudiness;
|
||||
float cloudScale;
|
||||
float cloudSpeed;
|
||||
archive >> fogHeightSky;
|
||||
archive >> cloudiness;
|
||||
archive >> cloudScale;
|
||||
archive >> cloudSpeed;
|
||||
}
|
||||
archive >> windDirection;
|
||||
archive >> windRandomness;
|
||||
archive >> windWaveSize;
|
||||
@@ -1135,17 +1151,24 @@ namespace wi::scene
|
||||
archive >> volumetricCloudParameters.DetailScale;
|
||||
archive >> volumetricCloudParameters.WeatherScale;
|
||||
archive >> volumetricCloudParameters.CurlScale;
|
||||
archive >> volumetricCloudParameters.ShapeNoiseHeightGradientAmount;
|
||||
archive >> volumetricCloudParameters.ShapeNoiseMultiplier;
|
||||
archive >> volumetricCloudParameters.ShapeNoiseMinMax;
|
||||
archive >> volumetricCloudParameters.ShapeNoisePower;
|
||||
if (archive.GetVersion() < 86)
|
||||
{
|
||||
float ShapeNoiseHeightGradientAmount;
|
||||
float ShapeNoiseMultiplier;
|
||||
XMFLOAT2 ShapeNoiseMinMax;
|
||||
float ShapeNoisePower;
|
||||
archive >> ShapeNoiseHeightGradientAmount;
|
||||
archive >> ShapeNoiseMultiplier;
|
||||
archive >> ShapeNoiseMinMax;
|
||||
archive >> ShapeNoisePower;
|
||||
}
|
||||
archive >> volumetricCloudParameters.DetailNoiseModifier;
|
||||
archive >> volumetricCloudParameters.DetailNoiseHeightFraction;
|
||||
archive >> volumetricCloudParameters.CurlNoiseModifier;
|
||||
archive >> volumetricCloudParameters.CoverageAmount;
|
||||
archive >> volumetricCloudParameters.CoverageMinimum;
|
||||
archive >> volumetricCloudParameters.TypeAmount;
|
||||
archive >> volumetricCloudParameters.TypeOverall;
|
||||
archive >> volumetricCloudParameters.TypeMinimum;
|
||||
archive >> volumetricCloudParameters.AnvilAmount;
|
||||
archive >> volumetricCloudParameters.AnvilOverhangHeight;
|
||||
archive >> volumetricCloudParameters.AnimationMultiplier;
|
||||
@@ -1167,6 +1190,15 @@ namespace wi::scene
|
||||
archive >> volumetricCloudParameters.TransmittanceThreshold;
|
||||
archive >> volumetricCloudParameters.ShadowSampleCount;
|
||||
archive >> volumetricCloudParameters.GroundContributionSampleCount;
|
||||
|
||||
if (archive.GetVersion() < 86)
|
||||
{
|
||||
volumetricCloudParameters.HorizonBlendAmount *= 0.00001f;
|
||||
volumetricCloudParameters.TotalNoiseScale *= 0.0004f;
|
||||
volumetricCloudParameters.WeatherScale *= 0.0004f;
|
||||
volumetricCloudParameters.CoverageAmount /= 2.0f;
|
||||
volumetricCloudParameters.CoverageMinimum = std::max(0.0f, volumetricCloudParameters.CoverageMinimum - 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 71)
|
||||
@@ -1175,8 +1207,11 @@ namespace wi::scene
|
||||
archive >> fogHeightEnd;
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 77)
|
||||
if (archive.GetVersion() >= 77 && archive.GetVersion() < 86)
|
||||
{
|
||||
float cloud_shadow_amount;
|
||||
float cloud_shadow_scale;
|
||||
float cloud_shadow_speed;
|
||||
archive >> cloud_shadow_amount;
|
||||
archive >> cloud_shadow_scale;
|
||||
archive >> cloud_shadow_speed;
|
||||
@@ -1186,6 +1221,16 @@ namespace wi::scene
|
||||
{
|
||||
archive >> stars;
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 86)
|
||||
{
|
||||
archive >> volumetricCloudsWeatherMapName;
|
||||
if (!volumetricCloudsWeatherMapName.empty())
|
||||
{
|
||||
volumetricCloudsWeatherMapName = dir + volumetricCloudsWeatherMapName;
|
||||
volumetricCloudsWeatherMap = wi::resourcemanager::Load(volumetricCloudsWeatherMapName, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1197,10 +1242,6 @@ namespace wi::scene
|
||||
archive << ambient;
|
||||
archive << fogStart;
|
||||
archive << fogEnd;
|
||||
archive << fogHeightSky;
|
||||
archive << cloudiness;
|
||||
archive << cloudScale;
|
||||
archive << cloudSpeed;
|
||||
archive << windDirection;
|
||||
archive << windRandomness;
|
||||
archive << windWaveSize;
|
||||
@@ -1220,6 +1261,7 @@ namespace wi::scene
|
||||
|
||||
wi::helper::MakePathRelative(dir, skyMapName);
|
||||
wi::helper::MakePathRelative(dir, colorGradingMapName);
|
||||
wi::helper::MakePathRelative(dir, volumetricCloudsWeatherMapName);
|
||||
|
||||
if (archive.GetVersion() >= 32)
|
||||
{
|
||||
@@ -1280,17 +1322,24 @@ namespace wi::scene
|
||||
archive << volumetricCloudParameters.DetailScale;
|
||||
archive << volumetricCloudParameters.WeatherScale;
|
||||
archive << volumetricCloudParameters.CurlScale;
|
||||
archive << volumetricCloudParameters.ShapeNoiseHeightGradientAmount;
|
||||
archive << volumetricCloudParameters.ShapeNoiseMultiplier;
|
||||
archive << volumetricCloudParameters.ShapeNoiseMinMax;
|
||||
archive << volumetricCloudParameters.ShapeNoisePower;
|
||||
if (archive.GetVersion() < 86)
|
||||
{
|
||||
float ShapeNoiseHeightGradientAmount = 0;
|
||||
float ShapeNoiseMultiplier = 0;
|
||||
XMFLOAT2 ShapeNoiseMinMax = XMFLOAT2(0, 0);
|
||||
float ShapeNoisePower = 0;
|
||||
archive << ShapeNoiseHeightGradientAmount;
|
||||
archive << ShapeNoiseMultiplier;
|
||||
archive << ShapeNoiseMinMax;
|
||||
archive << ShapeNoisePower;
|
||||
}
|
||||
archive << volumetricCloudParameters.DetailNoiseModifier;
|
||||
archive << volumetricCloudParameters.DetailNoiseHeightFraction;
|
||||
archive << volumetricCloudParameters.CurlNoiseModifier;
|
||||
archive << volumetricCloudParameters.CoverageAmount;
|
||||
archive << volumetricCloudParameters.CoverageMinimum;
|
||||
archive << volumetricCloudParameters.TypeAmount;
|
||||
archive << volumetricCloudParameters.TypeOverall;
|
||||
archive << volumetricCloudParameters.TypeMinimum;
|
||||
archive << volumetricCloudParameters.AnvilAmount;
|
||||
archive << volumetricCloudParameters.AnvilOverhangHeight;
|
||||
archive << volumetricCloudParameters.AnimationMultiplier;
|
||||
@@ -1320,17 +1369,15 @@ namespace wi::scene
|
||||
archive << fogHeightEnd;
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 77)
|
||||
{
|
||||
archive << cloud_shadow_amount;
|
||||
archive << cloud_shadow_scale;
|
||||
archive << cloud_shadow_speed;
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 78)
|
||||
{
|
||||
archive << stars;
|
||||
}
|
||||
|
||||
if (archive.GetVersion() >= 86)
|
||||
{
|
||||
archive << volumetricCloudsWeatherMapName;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SoundComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
|
||||
|
||||
@@ -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 = 29;
|
||||
const int revision = 30;
|
||||
|
||||
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user