Merge remote-tracking branch 'origin/master' into sdl_platform
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Cooker / Cook (Mac) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled

# Conflicts:
#	Source/Editor/Windows/SceneTreeWindow.cs
This commit is contained in:
2025-07-03 22:05:29 +03:00
23 changed files with 233 additions and 83 deletions

View File

@@ -143,9 +143,9 @@ void PS_Forward(
#endif
#if USE_FOG
#if USE_FOG && MATERIAL_SHADING_MODEL != SHADING_MODEL_UNLIT
// Calculate exponential height fog
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0);
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, materialInput.WorldPosition, ViewPos, 0, gBuffer.ViewPos.z);
// Apply fog to the output color
#if MATERIAL_BLEND == MATERIAL_BLEND_OPAQUE

Binary file not shown.

BIN
Content/Shaders/Fog.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -267,6 +267,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=comperand/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=coord/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=cubemap/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=DDGI/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Deformer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=deformers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=defragmentation/@EntryIndexedValue">True</s:Boolean>

View File

@@ -604,6 +604,9 @@ namespace FlaxEditor.CustomEditors.Editors
root.SortChildrenRecursive();
root.Expand(true);
if (Input.GetKey(KeyboardKeys.Shift))
root.ExpandAll(true);
return menu;
}
}

View File

@@ -227,9 +227,8 @@ namespace FlaxEditor.GUI
{
int order = -1 * SortScore.CompareTo(otherItem.SortScore);
if (order == 0)
{
order = string.Compare(Name, otherItem.Name, StringComparison.Ordinal);
}
return order;
}
return base.Compare(other);
@@ -509,7 +508,7 @@ namespace FlaxEditor.GUI
OnSearchFilterChanged();
}
private List<Item> GetVisibleItems()
private List<Item> GetVisibleItems(bool ignoreFoldedCategories)
{
var result = new List<Item>();
var items = ItemsPanel.Children;
@@ -523,7 +522,7 @@ namespace FlaxEditor.GUI
for (int i = 0; i < _categoryPanels.Count; i++)
{
var category = _categoryPanels[i];
if (!category.Visible)
if (!category.Visible || (ignoreFoldedCategories && category is DropPanel panel && panel.IsClosed))
continue;
for (int j = 0; j < category.Children.Count; j++)
{
@@ -535,6 +534,12 @@ namespace FlaxEditor.GUI
return result;
}
private void ExpandToItem(Item item)
{
if (item.Parent is DropPanel dropPanel)
dropPanel.Open(false);
}
/// <inheritdoc />
protected override void OnShow()
{
@@ -564,7 +569,7 @@ namespace FlaxEditor.GUI
Hide();
return true;
case KeyboardKeys.Backspace:
// Alow the user to quickly focus the searchbar
// Allow the user to quickly focus the searchbar
if (_searchBox != null && !_searchBox.IsFocused)
{
_searchBox.Focus();
@@ -582,14 +587,25 @@ namespace FlaxEditor.GUI
}
// Get the next item
var items = GetVisibleItems();
bool controlDown = Root.GetKey(KeyboardKeys.Control);
var items = GetVisibleItems(!controlDown);
var focusedIndex = items.IndexOf(focusedItem);
// If the user hasn't selected anything yet and is holding control, focus first folded item
if (focusedIndex == -1 && controlDown)
focusedIndex = GetVisibleItems(true).Count - 1;
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, items.Count - 1);
var nextItem = items[nextIndex];
// Focus the next item
nextItem.Focus();
// Allow the user to expand groups while scrolling
if (controlDown)
ExpandToItem(nextItem);
_scrollPanel.ScrollViewTo(nextItem);
return true;
case KeyboardKeys.Return:
@@ -601,7 +617,7 @@ namespace FlaxEditor.GUI
else
{
// Select first item if no item is focused (most likely to be the best result), saves the user from pressing arrow down first
var visibleItems = GetVisibleItems();
var visibleItems = GetVisibleItems(true);
if (visibleItems.Count > 0)
{
OnClickItem(visibleItems[0]);

View File

@@ -19,6 +19,7 @@ namespace FlaxEditor.States
private readonly List<Guid> _scenesToLoad = new List<Guid>();
private readonly List<Scene> _scenesToUnload = new List<Scene>();
private Guid _lastSceneFromRequest;
private bool _sameSceneReload = false;
internal ChangingScenesState(Editor editor)
: base(editor)
@@ -164,10 +165,22 @@ namespace FlaxEditor.States
{
Assert.AreEqual(Guid.Empty, _lastSceneFromRequest, "Invalid state.");
// Bind events
Level.SceneLoaded += OnSceneEvent;
Level.SceneLoadError += OnSceneEvent;
Level.SceneUnloaded += OnSceneEvent;
// Bind events, only bind loading event and error if re-loading the same scene to avoid issues.
if (_scenesToUnload.Count == 1 && _scenesToLoad.Count == 1)
{
if (_scenesToLoad[0] == _scenesToUnload[0].ID)
{
Level.SceneLoaded += OnSceneEvent;
Level.SceneLoadError += OnSceneEvent;
_sameSceneReload = true;
}
}
if (!_sameSceneReload)
{
Level.SceneLoaded += OnSceneEvent;
Level.SceneLoadError += OnSceneEvent;
Level.SceneUnloaded += OnSceneEvent;
}
// Push scenes changing requests
for (int i = 0; i < _scenesToUnload.Count; i++)
@@ -210,9 +223,18 @@ namespace FlaxEditor.States
}
// Unbind events
Level.SceneLoaded -= OnSceneEvent;
Level.SceneLoadError -= OnSceneEvent;
Level.SceneUnloaded -= OnSceneEvent;
if (_sameSceneReload)
{
Level.SceneLoaded -= OnSceneEvent;
Level.SceneLoadError -= OnSceneEvent;
_sameSceneReload = false;
}
else
{
Level.SceneLoaded -= OnSceneEvent;
Level.SceneLoadError -= OnSceneEvent;
Level.SceneUnloaded -= OnSceneEvent;
}
}
private void OnSceneEvent(Scene scene, Guid sceneId)

View File

@@ -40,6 +40,11 @@ namespace FlaxEditor.Surface
[HideInEditor]
public class SurfaceNode : SurfaceControl
{
/// <summary>
/// The box to draw a highlight around. Drawing will be skipped if null.
/// </summary>
internal Box highlightBox;
/// <summary>
/// Flag used to discard node values setting during event sending for node UI flushing.
/// </summary>
@@ -1102,6 +1107,9 @@ namespace FlaxEditor.Surface
Render2D.DrawSprite(icon, new Rectangle(-7, -7, 16, 16), new Color(0.9f, 0.9f, 0.9f));
Render2D.DrawSprite(icon, new Rectangle(-6, -6, 14, 14), new Color(0.894117647f, 0.0784313725f, 0.0f));
}
if (highlightBox != null)
Render2D.DrawRectangle(highlightBox.Bounds, style.BorderHighlighted, 2f);
}
/// <inheritdoc />

View File

@@ -427,7 +427,7 @@ namespace FlaxEditor.Surface
_cmDistributeNodesHorizontallyButton = _cmFormatNodesMenu.ContextMenu.AddButton("Distribute horizontally", Editor.Instance.Options.Options.Input.NodesDistributeHorizontal, () => { DistributeNodes(SelectedNodes, false); });
_cmDistributeNodesVerticallyButton = _cmFormatNodesMenu.ContextMenu.AddButton("Distribute vertically", Editor.Instance.Options.Options.Input.NodesDistributeVertical, () => { DistributeNodes(SelectedNodes, true); });
_cmRemoveNodeConnectionsButton = menu.AddButton("Remove all connections to that node(s)", () =>
_cmRemoveNodeConnectionsButton = menu.AddButton("Remove all connections", () =>
{
var nodes = ((List<SurfaceNode>)menu.Tag);
@@ -453,8 +453,10 @@ namespace FlaxEditor.Surface
MarkAsEdited();
});
_cmRemoveNodeConnectionsButton.Enabled = CanEdit;
_cmRemoveBoxConnectionsButton = menu.AddButton("Remove all connections to that box", () =>
bool anyConnection = SelectedNodes.Any(n => n.GetBoxes().Any(b => b.HasAnyConnection));
_cmRemoveNodeConnectionsButton.Enabled = CanEdit && anyConnection;
_cmRemoveBoxConnectionsButton = menu.AddButton("Remove all socket connections", () =>
{
var boxUnderMouse = (Box)_cmRemoveBoxConnectionsButton.Tag;
if (Undo != null)
@@ -475,6 +477,16 @@ namespace FlaxEditor.Surface
var boxUnderMouse = GetChildAtRecursive(location) as Box;
_cmRemoveBoxConnectionsButton.Enabled = boxUnderMouse != null && boxUnderMouse.HasAnyConnection;
_cmRemoveBoxConnectionsButton.Tag = boxUnderMouse;
if (boxUnderMouse != null)
{
boxUnderMouse.ParentNode.highlightBox = boxUnderMouse;
menu.VisibleChanged += (c) =>
{
if (!c.Visible)
boxUnderMouse.ParentNode.highlightBox = null;
};
}
}
controlUnderMouse?.OnShowSecondaryContextMenu(menu, controlUnderMouse.PointFromParent(location));

View File

@@ -225,6 +225,10 @@ namespace FlaxEditor.Surface
_rootControl.DrawComments();
// Reset input flags here because this is the closest to Update we have
WasBoxSelecting = IsBoxSelecting;
WasMovingSelection = IsMovingSelection;
if (IsBoxSelecting)
{
DrawSelection();

View File

@@ -590,9 +590,6 @@ namespace FlaxEditor.Surface
// Cache flags and state
if (_leftMouseDown && button == MouseButton.Left)
{
WasBoxSelecting = IsBoxSelecting;
WasMovingSelection = _isMovingSelection;
_leftMouseDown = false;
EndMouseCapture();
Cursor = CursorType.Default;

View File

@@ -447,6 +447,10 @@ namespace FlaxEditor.Windows
/// </summary>
public void Clear()
{
lock (_locker)
{
_pendingEntries.Clear();
}
if (_entriesPanel == null)
return;
RemoveEntries();
@@ -735,10 +739,10 @@ namespace FlaxEditor.Windows
}
/// <inheritdoc />
public override void OnPlayBegin()
public override void OnPlayBeginning()
{
// Clear on Play
if (_clearOnPlayButton.Checked)
if (Editor.Options.Options.Interface.DebugLogClearOnPlay)
{
Clear();
}

View File

@@ -26,6 +26,7 @@ namespace FlaxEditor.Windows
private Tree _tree;
private Panel _sceneTreePanel;
private bool _isUpdatingSelection;
private bool _blockSceneTreeScroll = false;
private DragAssets _dragAssets;
private DragActorType _dragActorType;
@@ -110,6 +111,34 @@ namespace FlaxEditor.Windows
InputActions.Add(options => options.LockFocusSelection, () => Editor.Windows.EditWin.Viewport.LockFocusSelection());
InputActions.Add(options => options.Rename, RenameSelection);
}
/// <inheritdoc />
public override void OnPlayBeginning()
{
base.OnPlayBeginning();
_blockSceneTreeScroll = true;
}
/// <inheritdoc />
public override void OnPlayBegin()
{
base.OnPlayBegin();
_blockSceneTreeScroll = false;
}
/// <inheritdoc />
public override void OnPlayEnding()
{
base.OnPlayEnding();
_blockSceneTreeScroll = true;
}
/// <inheritdoc />
public override void OnPlayEnd()
{
base.OnPlayEnd();
_blockSceneTreeScroll = true;
}
/// <summary>
/// Enables or disables vertical and horizontal scrolling on the scene tree panel.
@@ -269,7 +298,7 @@ namespace FlaxEditor.Windows
_tree.Select(nodes);
// For single node selected scroll view so user can see it
if (nodes.Count == 1)
if (nodes.Count == 1 && !_blockSceneTreeScroll)
{
nodes[0].ExpandAllParents(true);
_sceneTreePanel.ScrollViewTo(nodes[0]);
@@ -279,6 +308,12 @@ namespace FlaxEditor.Windows
_isUpdatingSelection = false;
}
/// <inheritdoc />
public override void OnEditorStateChanged()
{
_blockSceneTreeScroll = Editor.StateMachine.ReloadingScriptsState.IsActive;
}
private bool ValidateDragAsset(AssetItem assetItem)
{
if (assetItem.IsOfType<SceneAsset>())

View File

@@ -20,6 +20,11 @@ namespace FlaxEditor.Windows.Search
/// </summary>
protected Image _icon;
/// <summary>
/// The color of the accent strip.
/// </summary>
protected Color _accentColor;
/// <summary>
/// The item name.
/// </summary>
@@ -56,7 +61,7 @@ namespace FlaxEditor.Windows.Search
var icon = new Image
{
Size = new Float2(logoSize),
Location = new Float2(5, (height - logoSize) / 2)
Location = new Float2(7, (height - logoSize) / 2)
};
_icon = icon;
@@ -74,6 +79,20 @@ namespace FlaxEditor.Windows.Search
typeLabel.TextColor = Style.Current.ForegroundGrey;
}
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
// Select and focus the item on right click to prevent the search from being cleared
if (button == MouseButton.Right)
{
_finder.SelectedItem = this;
_finder.Hand = true;
Focus();
return true;
}
return base.OnMouseUp(location, button);
}
/// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button)
{
@@ -86,6 +105,15 @@ namespace FlaxEditor.Windows.Search
return base.OnMouseUp(location, button);
}
/// <inheritdoc />
public override void Draw()
{
if (IsMouseOver)
Render2D.FillRectangle(new Rectangle(Float2.Zero, Size), Style.Current.BackgroundHighlighted);
base.Draw();
}
/// <inheritdoc />
public override void OnMouseEnter(Float2 location)
{
@@ -93,12 +121,7 @@ namespace FlaxEditor.Windows.Search
var root = RootWindow;
if (root != null)
{
root.Cursor = CursorType.Hand;
}
_finder.SelectedItem = this;
_finder.Hand = true;
}
/// <inheritdoc />
@@ -128,6 +151,7 @@ namespace FlaxEditor.Windows.Search
{
_asset = item;
_asset.AddReference(this);
_accentColor = Editor.Instance.ContentDatabase.GetProxy(item).AccentColor;
}
/// <inheritdoc />
@@ -176,9 +200,7 @@ namespace FlaxEditor.Windows.Search
{
string importLocation = System.IO.Path.GetDirectoryName(importPath);
if (!string.IsNullOrEmpty(importLocation) && System.IO.Directory.Exists(importLocation))
{
cm.AddButton("Show import location", () => FileSystem.ShowFileExplorer(importLocation));
}
}
}
cm.AddSeparator();
@@ -212,6 +234,10 @@ namespace FlaxEditor.Windows.Search
// Draw icon
var iconRect = _icon.Bounds;
_asset.DrawThumbnail(ref iconRect);
// Draw color strip
var rect = iconRect with { Width = 2, Height = Height, Location = new Float2(2, 0) };
Render2D.FillRectangle(rect, _accentColor);
}
/// <inheritdoc />

View File

@@ -84,7 +84,7 @@ public:
bool EnableGlobalSDF = false;
/// <summary>
/// Draw distance of the Global SDF. Actual value can be large when using DDGI.
/// Draw distance of the Global SDF. Actual value can be larger when using DDGI.
/// </summary>
API_FIELD(Attributes="EditorOrder(2001), EditorDisplay(\"Global SDF\"), Limit(1000), ValueCategory(Utils.ValueCategory.Distance)")
float GlobalSDFDistance = 15000.0f;

View File

@@ -993,6 +993,12 @@ void Foliage::RemoveAllInstances()
RebuildClusters();
}
void Foliage::RemoveLightmap()
{
for (auto& e : Instances)
e.RemoveLightmap();
}
static float GlobalDensityScale = 1.0f;
float Foliage::GetGlobalDensityScale()

View File

@@ -139,6 +139,11 @@ public:
/// </summary>
API_FUNCTION() void RemoveAllInstances();
/// <summary>
/// Removes the lightmap data from the foliage instances.
/// </summary>
API_FUNCTION() void RemoveLightmap();
public:
/// <summary>
/// Gets the global density scale for all foliage instances. The default value is 1. Use values from range 0-1. Lower values decrease amount of foliage instances in-game. Use it to tweak game performance for slower devices.

View File

@@ -41,11 +41,10 @@ void ExponentialHeightFog::Draw(RenderContext& renderContext)
&& _shader->IsLoaded()
&& renderContext.View.IsPerspectiveProjection())
{
// Prepare
if (_psFog.States[0] == nullptr)
{
// Create pipeline states
_psFog.CreatePipelineStates();
if (!_psFog.States[0]->IsValid())
{
GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
psDesc.DepthWriteEnable = false;
psDesc.BlendMode.BlendEnable = true;
@@ -59,6 +58,7 @@ void ExponentialHeightFog::Draw(RenderContext& renderContext)
if (_psFog.Create(psDesc, _shader->GetShader(), "PS_Fog"))
{
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
return;
}
}
@@ -160,7 +160,7 @@ void ExponentialHeightFog::GetExponentialHeightFogData(const RenderView& view, S
result.FogAtViewPosition = density * Math::Pow(2.0f, Math::Clamp(-heightFalloff * (viewHeight - height), -125.f, 126.f));
result.StartDistance = StartDistance;
result.FogMinOpacity = 1.0f - FogMaxOpacity;
result.FogCutoffDistance = FogCutoffDistance;
result.FogCutoffDistance = FogCutoffDistance >= 0 ? FogCutoffDistance : view.Far + FogCutoffDistance;
if (useDirectionalLightInscattering)
{
result.InscatteringLightDirection = -DirectionalInscatteringLight->GetDirection();

View File

@@ -55,9 +55,9 @@ public:
float StartDistance = 0.0f;
/// <summary>
/// Scene elements past this distance will not have fog applied. This is useful for excluding skyboxes which already have fog baked in. Setting this value to 0 disables it.
/// Scene elements past this distance will not have fog applied. This is useful for excluding skyboxes which already have fog baked in. Setting this value to 0 disables it. Negative value sets the cutoff distance relative to the far plane of the camera.
/// </summary>
API_FIELD(Attributes="EditorOrder(60), DefaultValue(0.0f), Limit(0), EditorDisplay(\"Exponential Height Fog\")")
API_FIELD(Attributes="EditorOrder(60), DefaultValue(0.0f), EditorDisplay(\"Exponential Height Fog\")")
float FogCutoffDistance = 0.0f;
public:

View File

@@ -7,6 +7,7 @@
#include "Engine/Content/Content.h"
#include "Engine/Content/Deprecated.h"
#include "Engine/Content/Factories/JsonAssetFactory.h"
#include "Engine/Foliage/Foliage.h"
#include "Engine/Physics/Colliders/MeshCollider.h"
#include "Engine/Level/Actors/StaticModel.h"
#include "Engine/Level/ActorsCache.h"
@@ -15,6 +16,7 @@
#include "Engine/Navigation/NavMesh.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Serialization/Serialization.h"
#include "Engine/Terrain/Terrain.h"
#if USE_EDITOR
#include "Engine/Engine/Globals.h"
#endif
@@ -98,6 +100,19 @@ void Scene::SetLightmapSettings(const LightmapSettings& value)
void Scene::ClearLightmaps()
{
LightmapsData.ClearLightmaps();
// Unlink any actors from lightmap
Function<bool(Actor*)> function = [this](Actor* actor)
{
if (auto* staticModel = Cast<StaticModel>(actor))
staticModel->RemoveLightmap();
else if (auto* terrain = Cast<Terrain>(actor))
terrain->RemoveLightmap();
else if (auto* foliage = Cast<Foliage>(actor))
foliage->RemoveLightmap();
return true;
};
TreeExecute(function);
}
void Scene::BuildCSG(float timeoutMs)

View File

@@ -692,8 +692,12 @@ int Triangulate(OpenFbxImporterData& data, const ofbx::GeometryData& geom, const
triangulatedIndices[i] = polygon.from_vertex + (earIndices[i] % polygon.vertex_count);
// Ensure that we've written enough ears
ASSERT(earIndices.Count() == 3 * (polygon.vertex_count - 2));
return earIndices.Count();
const int32 indexCount = 3 * (polygon.vertex_count - 2);
if (indexCount != earIndices.Count())
{
LOG(Error, "Invalid amount of vertices after triangulation. Expected {} but got {}. Use proper mesh triangulation when exporting source asset to the engine.", earIndices.Count(), indexCount);
}
return indexCount;
}
bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh* aMesh, MeshData& mesh, String& errorMsg, int partitionIndex)
@@ -729,7 +733,7 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
mesh.Positions.Get()[j] = ToFloat3(positions.get(triangulatedIndices[j]));
numIndicesTotal += numIndices;
}
ASSERT(numIndicesTotal == vertexCount);
ASSERT_LOW_LAYER(numIndicesTotal == vertexCount);
}
// Indices (dummy index buffer)

View File

@@ -29,7 +29,7 @@ struct ExponentialHeightFogData
float StartDistance;
};
float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance)
float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance, float sceneDistance)
{
float3 cameraToPos = posWS - camWS;
float cameraToPosSqr = dot(cameraToPos, cameraToPos);
@@ -78,7 +78,7 @@ float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, fl
// Disable fog after a certain distance
FLATTEN
if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToPosLen > exponentialHeightFog.FogCutoffDistance)
if (exponentialHeightFog.FogCutoffDistance > 0 && sceneDistance > exponentialHeightFog.FogCutoffDistance)
{
expFogFactor = 1;
directionalInscattering = 0;
@@ -87,4 +87,9 @@ float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, fl
return float4(inscatteringColor * (1.0f - expFogFactor) + directionalInscattering, expFogFactor);
}
float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance)
{
return GetExponentialHeightFog(exponentialHeightFog, posWS, camWS, skipDistance, distance(posWS, camWS));
}
#endif

View File

@@ -24,41 +24,17 @@ Texture2D Depth : register(t0);
Texture3D IntegratedLightScattering : register(t1);
#endif
// Get world space position at given pixel coordinate
float3 GetWorldPos(float2 uv)
{
float depth = SAMPLE_RT(Depth, uv).r;
GBufferData gBufferData = GetGBufferData();
float3 viewPos = GetViewPos(gBufferData, uv, depth);
return mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz;
}
float4 CalculateCombinedFog(float3 posWS, float sceneDepth, float3 volumeUV)
{
float skipDistance = 0;
#if VOLUMETRIC_FOG
skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
#endif
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, posWS, GBuffer.ViewPos, skipDistance);
#if VOLUMETRIC_FOG
float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0);
fog = float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a);
#endif
return fog;
}
META_PS(true, FEATURE_LEVEL_ES2)
META_PERMUTATION_1(VOLUMETRIC_FOG=0)
META_PERMUTATION_1(VOLUMETRIC_FOG=1)
float4 PS_Fog(Quad_VS2PS input) : SV_Target0
{
// Calculate pixel world space position
float3 posWS = GetWorldPos(input.TexCoord);
float3 viewVector = posWS - GBuffer.ViewPos;
// Get world space position at given pixel coordinate
float rawDepth = SAMPLE_RT(Depth, input.TexCoord).r;
GBufferData gBufferData = GetGBufferData();
float3 viewPos = GetViewPos(gBufferData, input.TexCoord, rawDepth);
float3 worldPos = mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz;
float3 viewVector = worldPos - GBuffer.ViewPos;
float sceneDepth = length(viewVector);
// Calculate volumetric fog coordinates
@@ -67,17 +43,28 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0
// Debug code
#if VOLUMETRIC_FOG && 0
volumeUV = posWS / 1000;
volumeUV = worldPos / 1000;
if (!all(volumeUV >= 0 && volumeUV <= 1))
return 0;
return float4(IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0).rgb, 1);
//return float4(volumeUV, 1);
//return float4(posWS / 100, 1);
//return float4(worldPos / 100, 1);
#endif
// Calculate fog color
float4 fog = CalculateCombinedFog(posWS, sceneDepth, volumeUV);
float skipDistance = 0;
#if VOLUMETRIC_FOG
skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
#endif
// Calculate exponential fog color
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, worldPos, GBuffer.ViewPos, skipDistance, viewPos.z);
#if VOLUMETRIC_FOG
// Sample volumetric fog and mix it in
float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0);
fog = float4(volumetricFog.rgb + fog.rgb * volumetricFog.a, volumetricFog.a * fog.a);
#endif
return fog;
}