Merge remote-tracking branch 'origin/master' into dotnet7

This commit is contained in:
Wojtek Figat
2023-02-06 10:02:13 +01:00
158 changed files with 1077 additions and 905 deletions

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/DefaultFontMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@@ -40,7 +40,7 @@ void PS_GBuffer(
#if MATERIAL_MASKED
clip(material.Mask - MATERIAL_MASK_THRESHOLD);
#endif
#if USE_LIGHTMAP
float3 diffuseColor = GetDiffuseColor(material.Color, material.Metalness);
float3 specularColor = GetSpecularColor(material.Color, material.Specular, material.Metalness);

View File

@@ -33,9 +33,12 @@ DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
// Pixel Shader function for Forward Pass
META_PS(USE_FORWARD, FEATURE_LEVEL_ES2)
float4 PS_Forward(PixelInput input) : SV_Target0
void PS_Forward(
in PixelInput input
,out float4 output : SV_Target0
)
{
float4 output = 0;
output = 0;
#if USE_DITHERED_LOD_TRANSITION
// LOD masking
@@ -148,6 +151,4 @@ float4 PS_Forward(PixelInput input) : SV_Target0
#endif
#endif
return output;
}

View File

@@ -4,8 +4,6 @@
#define MATERIAL 1
#define USE_PER_VIEW_CONSTANTS 1
@3
// Ribbons don't use sorted indices so overlap the segment distances buffer on the slot
#define HAS_SORTED_INDICES (!defined(_VS_Ribbon))
#include "./Flax/Common.hlsl"
#include "./Flax/MaterialCommon.hlsl"
@@ -18,6 +16,14 @@ struct SpriteInput
float2 TexCoord : TEXCOORD;
};
struct RibbonInput
{
uint Order : TEXCOORD0;
uint ParticleIndex : TEXCOORD1;
uint PrevParticleIndex : TEXCOORD2;
float Distance : TEXCOORD3;
};
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
@@ -45,13 +51,8 @@ float4x4 WorldMatrixInverseTransposed;
// Particles attributes buffer
ByteAddressBuffer ParticlesData : register(t0);
#if HAS_SORTED_INDICES
// Sorted particles indices
Buffer<uint> SortedIndices : register(t1);
#else
// Ribbon particles segments distances buffer
Buffer<float> SegmentDistances : register(t1);
#endif
// Shader resources
@2
@@ -320,13 +321,11 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
{
VertexOutput output;
#if HAS_SORTED_INDICES
// Sorted particles mapping
if (SortedIndicesOffset != 0xFFFFFFFF)
{
particleIndex = SortedIndices[SortedIndicesOffset + particleIndex];
}
#endif
// Read particle data
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
@@ -457,13 +456,11 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
{
VertexOutput output;
#if HAS_SORTED_INDICES
// Sorted particles mapping
if (SortedIndicesOffset != 0xFFFFFFFF)
{
particleIndex = SortedIndices[SortedIndicesOffset + particleIndex];
}
#endif
// Read particle data
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
@@ -566,12 +563,16 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
// Vertex Shader function for Ribbon Rendering
META_VS(true, FEATURE_LEVEL_ES2)
VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID)
META_VS_IN_ELEMENT(TEXCOORD, 0, R32_UINT, 0, 0, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 1, R32_UINT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 2, R32_UINT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 3, R32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
{
VertexOutput output;
// Get particle data
uint particleIndex = vertexIndex / 2;
uint particleIndex = input.ParticleIndex;
int vertexSign = (((int)vertexIndex & 0x1) * 2) - 1;
float3 position = GetParticlePosition(particleIndex);
float ribbonWidth = RibbonWidthOffset != -1 ? GetParticleFloat(particleIndex, RibbonWidthOffset) : 20.0f;
@@ -579,15 +580,13 @@ VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID)
// Calculate ribbon direction
float3 direction;
if (particleIndex == 0)
if (input.Order == 0)
{
float3 nextParticlePos = GetParticlePosition(particleIndex + 1);
direction = nextParticlePos - position;
direction = GetParticlePosition(input.PrevParticleIndex) - position;
}
else
{
float3 previousParticlePos = GetParticlePosition(particleIndex - 1);
direction = position - previousParticlePos;
direction = position - GetParticlePosition(input.PrevParticleIndex);
}
// Calculate particle orientation (tangent vectors)
@@ -604,19 +603,16 @@ VertexOutput VS_Ribbon(uint vertexIndex : SV_VertexID)
}
// Calculate texture coordinates
float texCoordU;
#ifdef _VS_Ribbon
if (RibbonUVTilingDistance != 0.0f)
{
texCoordU = SegmentDistances[particleIndex] / RibbonUVTilingDistance;
output.TexCoord.x = input.Distance / RibbonUVTilingDistance;
}
else
#endif
{
texCoordU = (float)particleIndex / RibbonSegmentCount;
output.TexCoord.x = (float)input.Order / (float)RibbonSegmentCount;
}
float texCoordV = (vertexIndex + 1) & 0x1;
output.TexCoord = float2(texCoordU, texCoordV) * RibbonUVScale + RibbonUVOffset;
output.TexCoord.y = (vertexIndex + 1) & 0x1;
output.TexCoord = output.TexCoord * RibbonUVScale + RibbonUVOffset;
// Compute world space vertex position
output.WorldPosition = position + tangentRight * vertexSign * (ribbonWidth.xxx * 0.5f);

View File

@@ -594,7 +594,7 @@ void PS_Depth(PixelInput input)
ClipLODTransition(input);
#endif
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
#if MATERIAL_MASKED || MATERIAL_BLEND != MATERIAL_BLEND_OPAQUE
// Get material parameters
MaterialInput materialInput = GetMaterialInput(input);
Material material = GetMaterialPS(materialInput);

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/SpriteMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/TexturePreviewMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@@ -354,7 +354,7 @@ bool CookAssetsStep::Process(CookingData& data, CacheData& cache, Asset* asset)
if (asset->WaitForLoaded())
{
LOG(Error, "Failed to load asset \'{0}\'", asset->ToString());
return false;
return true;
}
// Switch based on an asset type
@@ -1132,7 +1132,10 @@ bool CookAssetsStep::Perform(CookingData& data)
// Cook asset
if (Process(data, cache, assetRef.Get()))
{
cache.Save();
return true;
}
data.Stats.CookedAssets++;
// Auto save build cache after every few cooked assets (reduces next build time if cooking fails later)

View File

@@ -322,7 +322,7 @@ namespace FlaxEditor.CustomEditors.Editors
internal static ContextMenuBase CreatePicker(Tag value, Tag[] values, PickerData pickerData)
{
// Initialize search popup
var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 40.0f);
var menu = Utilities.Utils.CreateSearchPopup(out var searchBox, out var tree, 42.0f);
// Add tag drop panel
var addTagDropPanel = new DropPanel
@@ -333,6 +333,7 @@ namespace FlaxEditor.CustomEditors.Editors
ArrowImageClosed = new SpriteBrush(FlaxEngine.GUI.Style.Current.ArrowRight),
Parent = menu,
HeaderTextMargin = new Margin(2.0f),
HeaderHeight = 18.0f,
AnchorPreset = AnchorPresets.TopLeft,
Bounds = new Rectangle(2, 2, menu.Width - 4, 30),
IsClosed = true,
@@ -408,7 +409,7 @@ namespace FlaxEditor.CustomEditors.Editors
var buttonAddTag = new Button
{
Parent = addButtonPanel,
Size = new Float2(100, 20),
Size = new Float2(100, 18),
Text = "Add Tag",
AnchorPreset = AnchorPresets.MiddleCenter,
};

View File

@@ -275,12 +275,16 @@ namespace FlaxEditor.CustomEditors
// Workaround for DefaultValueAttribute that doesn't support certain value types storage
if (Type.Type == typeof(sbyte))
_defaultValue = Convert.ToSByte(_defaultValue);
else if (Type.Type == typeof(short))
_defaultValue = Convert.ToInt16(_defaultValue);
else if (Type.Type == typeof(ushort))
_defaultValue = Convert.ToUInt16(_defaultValue);
else if (Type.Type == typeof(uint))
_defaultValue = Convert.ToUInt32(_defaultValue);
else if (Type.Type == typeof(ulong))
_defaultValue = Convert.ToUInt64(_defaultValue);
else if (Type.Type == typeof(long))
_defaultValue = Convert.ToInt64(_defaultValue);
}
}
}

View File

@@ -50,7 +50,8 @@ namespace FlaxEditor
private bool _isAfterInit, _areModulesInited, _areModulesAfterInitEnd, _isHeadlessMode;
private string _projectToOpen;
private float _lastAutoSaveTimer;
private AutoSavePopup _autoSavePopup;
private Button _saveNowButton;
private Button _cancelSaveButton;
private bool _autoSaveNow;
private Guid _startupSceneCmdLine;
@@ -498,28 +499,6 @@ namespace FlaxEditor
{
var timeSinceLastSave = Time.UnscaledGameTime - _lastAutoSaveTimer;
var timeToNextSave = options.AutoSaveFrequency * 60.0f - timeSinceLastSave;
var countDownDuration = 4.0f;
// Show auto save popup
if (timeToNextSave <= options.AutoSaveReminderTime && timeToNextSave >= 0)
{
if (_autoSavePopup == null)
{
_autoSavePopup = AutoSavePopup.Show(Instance.Windows.MainWindow.GUI, timeToNextSave);
_autoSavePopup.SaveNowButton.Clicked += () => _autoSaveNow = true;
_autoSavePopup.CancelSaveButton.Clicked += () =>
{
Log("Auto save canceled");
_autoSavePopup.HidePopup();
_lastAutoSaveTimer = Time.UnscaledGameTime; // Reset timer
};
}
else if (!_autoSavePopup.Visible && !_autoSavePopup.UserClosed)
_autoSavePopup.ShowPopup();
if (_autoSavePopup.Visible)
_autoSavePopup.UpdateTime(timeToNextSave);
}
if (timeToNextSave <= 0.0f || _autoSaveNow)
{
@@ -530,14 +509,76 @@ namespace FlaxEditor
if (options.AutoSaveContent)
SaveContent();
// Hide auto save popup and reset user closed
_autoSavePopup.HidePopup();
_autoSavePopup.UserClosed = false;
_autoSaveNow = false;
// Hide save now and cancel save buttons
if (_saveNowButton != null && _cancelSaveButton != null)
{
_saveNowButton.Visible = false;
_cancelSaveButton.Visible = false;
}
}
else if (timeToNextSave < countDownDuration)
else if (timeToNextSave <= options.AutoSaveReminderTime)
{
msg = string.Format("Auto save in {0}s...", Mathf.CeilToInt(timeToNextSave));
// Create save now and cancel save buttons if needed
if (_saveNowButton == null)
{
_saveNowButton = new Button
{
Parent = UI.StatusBar,
Height = 14,
Width = 60,
AnchorPreset = AnchorPresets.MiddleLeft,
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BackgroundColorHighlighted = Color.Transparent,
BackgroundColorSelected = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
Text = "Save Now",
TooltipText = "Saves now and restarts the auto save timer."
};
_saveNowButton.LocalX += 120;
_saveNowButton.Clicked += () => _autoSaveNow = true;
_saveNowButton.HoverBegin += () => _saveNowButton.TextColor = Style.Current.BackgroundHighlighted;
_saveNowButton.HoverEnd += () => _saveNowButton.TextColor = UI.StatusBar.TextColor;
}
if (_cancelSaveButton == null)
{
_cancelSaveButton = new Button
{
Parent = UI.StatusBar,
Height = 14,
Width = 70,
AnchorPreset = AnchorPresets.MiddleLeft,
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BackgroundColorHighlighted = Color.Transparent,
BackgroundColorSelected = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
Text = "Cancel",
TooltipText = "Cancels this auto save."
};
_cancelSaveButton.LocalX += 180;
_cancelSaveButton.Clicked += () =>
{
Log("Auto save canceled");
_saveNowButton.Visible = false;
_cancelSaveButton.Visible = false;
_lastAutoSaveTimer = Time.UnscaledGameTime; // Reset timer
};
_cancelSaveButton.HoverBegin += () => _cancelSaveButton.TextColor = Style.Current.BackgroundHighlighted;
_cancelSaveButton.HoverEnd += () => _cancelSaveButton.TextColor = UI.StatusBar.TextColor;
}
// Show save now and cancel save buttons
if (!_saveNowButton.Visible || !_cancelSaveButton.Visible)
{
_saveNowButton.Visible = true;
_cancelSaveButton.Visible = true;
}
}
}
if (StateMachine.EditingSceneState.AutoSaveStatus != msg)
@@ -545,6 +586,14 @@ namespace FlaxEditor
StateMachine.EditingSceneState.AutoSaveStatus = msg;
UI.UpdateStatusBar();
}
if (UI?.StatusBar?.Text != null && !UI.StatusBar.Text.Contains("Auto") &&
_saveNowButton != null && _cancelSaveButton != null &&
(_saveNowButton.Visible || _cancelSaveButton.Visible))
{
_saveNowButton.Visible = false;
_cancelSaveButton.Visible = false;
}
}
private void InitProject()

View File

@@ -1,169 +0,0 @@
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.GUI
{
/// <summary>
/// Popup menu for reminding of an upcoming auto save.
/// </summary>
public class AutoSavePopup : ContainerControl
{
/// <summary>
/// Gets or sets the value for if the user has manually closed this popup.
/// </summary>
public bool UserClosed { get; set; }
/// <summary>
/// The save now button. Used to skip the last remaining auto save time.
/// </summary>
public Button SaveNowButton => _saveNowButton;
/// <summary>
/// Button that should be used to cancel the auto save.
/// </summary>
public Button CancelSaveButton => _cancelSaveButton;
private int _timeRemaining;
private Panel _backgroundPanel;
private Label _timeLabel;
private Button _saveNowButton;
private Button _cancelSaveButton;
private Color _defaultTextColor;
private bool _isMoved = false;
/// <summary>
/// Initialize the AutoSavePopup.
/// </summary>
/// <param name="initialTime">The initial time to set the time label to.</param>
public AutoSavePopup(float initialTime)
{
UpdateTime(initialTime);
_backgroundPanel = new Panel(ScrollBars.None)
{
Parent = this,
AnchorPreset = AnchorPresets.StretchAll,
BackgroundColor = Color.Transparent,
};
_timeLabel = new Label(0, 0, 25, 10)
{
Parent = _backgroundPanel,
Text = _timeRemaining.ToString(),
HorizontalAlignment = TextAlignment.Near,
VerticalAlignment = TextAlignment.Near,
AutoWidth = true,
Height = 14,
AnchorPreset = AnchorPresets.MiddleLeft,
};
_saveNowButton = new Button
{
Parent = _backgroundPanel,
Height = 14,
Width = 60,
AnchorPreset = AnchorPresets.MiddleRight,
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BackgroundColorHighlighted = Color.Transparent,
BackgroundColorSelected = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
Text = "Save Now",
TooltipText = "Saves now and restarts the auto save timer."
};
_saveNowButton.LocalX -= 85;
_cancelSaveButton = new Button
{
Parent = _backgroundPanel,
Height = 14,
Width = 70,
AnchorPreset = AnchorPresets.MiddleRight,
BackgroundColor = Color.Transparent,
BorderColor = Color.Transparent,
BackgroundColorHighlighted = Color.Transparent,
BackgroundColorSelected = Color.Transparent,
BorderColorHighlighted = Color.Transparent,
Text = "Cancel Save",
TooltipText = "Cancels this auto save."
};
_cancelSaveButton.LocalX -= 5;
_defaultTextColor = _saveNowButton.TextColor;
}
/// <summary>
/// Updates the time label
/// </summary>
/// <param name="time">The time to change the label to.</param>
public void UpdateTime(float time)
{
_timeRemaining = Mathf.CeilToInt(time);
if (_timeLabel != null)
_timeLabel.Text = "Auto Save in: " + _timeRemaining;
}
/// <inheritdoc />
public override void Update(float deltaTime)
{
if (IsMouseOver)
{
_saveNowButton.TextColor = _saveNowButton.IsMouseOver ? Style.Current.BackgroundHighlighted : _defaultTextColor;
_cancelSaveButton.TextColor = _cancelSaveButton.IsMouseOver ? Style.Current.BackgroundHighlighted : _defaultTextColor;
}
// Move if the progress bar is visible
if (Editor.Instance.UI.ProgressVisible && !_isMoved)
{
_isMoved = true;
LocalX -= 280;
}
else if (!Editor.Instance.UI.ProgressVisible && _isMoved)
{
LocalX += 280;
_isMoved = false;
}
base.Update(deltaTime);
}
/// <summary>
/// Creates and shows the AutoSavePopup
/// </summary>
/// <param name="parentControl">The parent control.</param>
/// <param name="initialTime">The time to start at.</param>
/// <returns></returns>
public static AutoSavePopup Show(ContainerControl parentControl, float initialTime)
{
var popup = new AutoSavePopup(initialTime)
{
Parent = parentControl,
Height = Editor.Instance.UI.StatusBar.Height,
Width = 250,
AnchorPreset = AnchorPresets.BottomRight,
};
popup.ShowPopup();
return popup;
}
/// <summary>
/// Shows the popup by changing its visibility
/// </summary>
public void ShowPopup()
{
Visible = true;
UserClosed = false;
_saveNowButton.TextColor = _defaultTextColor;
_cancelSaveButton.TextColor = _defaultTextColor;
}
/// <summary>
/// Hides the popup by changing its visibility
/// </summary>
public void HidePopup()
{
Visible = false;
if (_containsFocus)
Defocus();
}
}
}

View File

@@ -78,6 +78,7 @@ void ViewportIconsRenderer::DrawIcons(RenderContext& renderContext, Actor* actor
draw.PerInstanceRandom = 0;
draw.LODBias = 0;
draw.ForcedLOD = -1;
draw.SortOrder = 0;
draw.VertexColors = nullptr;
if (const auto scene = SceneObject::Cast<Scene>(actor))

View File

@@ -1521,6 +1521,7 @@ namespace FlaxEditor.Viewport
new ViewFlagOptions(ViewFlags.PointLights, "Point Lights"),
new ViewFlagOptions(ViewFlags.SpotLights, "Spot Lights"),
new ViewFlagOptions(ViewFlags.SkyLights, "Sky Lights"),
new ViewFlagOptions(ViewFlags.Sky, "Sky"),
new ViewFlagOptions(ViewFlags.Fog, "Fog"),
new ViewFlagOptions(ViewFlags.SpecularLight, "Specular Light"),
new ViewFlagOptions(ViewFlags.Decals, "Decals"),

View File

@@ -428,8 +428,12 @@ namespace FlaxEditor.Viewport.Previews
case KeyboardKeys.F:
// Pay respect..
ViewportCamera.SetArcBallView(_previewModel.Box);
break;
return true;
case KeyboardKeys.Spacebar:
PlayAnimation = !PlayAnimation;
return true;
}
return base.OnKeyDown(key);
}

View File

@@ -2,8 +2,10 @@
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.Viewport.Cameras;
using FlaxEditor.Viewport.Widgets;
using FlaxEngine;
using FlaxEngine.GUI;
using System;
using Object = FlaxEngine.Object;
namespace FlaxEditor.Viewport.Previews
@@ -14,10 +16,12 @@ namespace FlaxEditor.Viewport.Previews
/// <seealso cref="AssetPreview" />
public class ParticleSystemPreview : AssetPreview
{
private bool _playSimulation = false;
private ParticleEffect _previewEffect;
private ContextMenuButton _showBoundsButton;
private ContextMenuButton _showOriginButton;
private ContextMenuButton _showParticleCounterButton;
private ViewportWidgetButton _playPauseButton;
private StaticModel _boundsModel;
private StaticModel _originModel;
private bool _showParticlesCounter;
@@ -39,7 +43,25 @@ namespace FlaxEditor.Viewport.Previews
/// <summary>
/// Gets or sets a value indicating whether to play the particles simulation in editor.
/// </summary>
public bool PlaySimulation { get; set; } = false;
public bool PlaySimulation
{
get => _playSimulation;
set
{
if (_playSimulation == value)
return;
_playSimulation = value;
PlaySimulationChanged?.Invoke();
if (_playPauseButton != null)
_playPauseButton.Icon = value ? Editor.Instance.Icons.Pause64 : Editor.Instance.Icons.Play64;
}
}
/// <summary>
/// Occurs when particles simulation playback state gets changed.
/// </summary>
public event Action PlaySimulationChanged;
/// <summary>
/// Gets or sets a value indicating whether to show particle effect bounding box.
@@ -161,11 +183,22 @@ namespace FlaxEditor.Viewport.Previews
// Link actors for rendering
Task.AddCustomActor(_previewEffect);
if (useWidgets)
if (!useWidgets)
return;
_showBoundsButton = ViewWidgetShowMenu.AddButton("Bounds", () => ShowBounds = !ShowBounds);
_showOriginButton = ViewWidgetShowMenu.AddButton("Origin", () => ShowOrigin = !ShowOrigin);
_showParticleCounterButton = ViewWidgetShowMenu.AddButton("Particles Counter", () => ShowParticlesCounter = !ShowParticlesCounter);
// Play/Pause widget
{
_showBoundsButton = ViewWidgetShowMenu.AddButton("Bounds", () => ShowBounds = !ShowBounds);
_showOriginButton = ViewWidgetShowMenu.AddButton("Origin", () => ShowOrigin = !ShowOrigin);
_showParticleCounterButton = ViewWidgetShowMenu.AddButton("Particles Counter", () => ShowParticlesCounter = !ShowParticlesCounter);
var playPauseWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
_playPauseButton = new ViewportWidgetButton(null, Editor.Instance.Icons.Pause64)
{
TooltipText = "Simulation playback play (F5) or pause (F6)",
Parent = playPauseWidget,
};
_playPauseButton.Clicked += button => PlaySimulation = !PlaySimulation;
playPauseWidget.Parent = this;
}
}
@@ -200,7 +233,7 @@ namespace FlaxEditor.Viewport.Previews
// Manually update simulation
if (PlaySimulation)
{
_previewEffect.UpdateSimulation();
_previewEffect.UpdateSimulation(true);
}
// Keep bounds matching the model
@@ -228,6 +261,34 @@ namespace FlaxEditor.Viewport.Previews
}
}
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
switch (key)
{
case KeyboardKeys.F:
ViewportCamera.SetArcBallView(_previewEffect.Box);
return true;
case KeyboardKeys.Spacebar:
PlaySimulation = !PlaySimulation;
return true;
}
var inputOptions = Editor.Instance.Options.Options.Input;
if (inputOptions.Play.Process(this, key))
{
PlaySimulation = true;
return true;
}
if (inputOptions.Pause.Process(this, key))
{
PlaySimulation = false;
return true;
}
return base.OnKeyDown(key);
}
/// <inheritdoc />
public override void OnDestroy()
{
@@ -239,6 +300,7 @@ namespace FlaxEditor.Viewport.Previews
_showBoundsButton = null;
_showOriginButton = null;
_showParticleCounterButton = null;
_playPauseButton = null;
base.OnDestroy();
}

View File

@@ -430,7 +430,7 @@ namespace FlaxEditor.Windows
writer.WriteAttributeString("MovementSpeed", Viewport.MovementSpeed.ToString());
writer.WriteAttributeString("OrthographicScale", Viewport.OrthographicScale.ToString());
writer.WriteAttributeString("UseOrthographicProjection", Viewport.UseOrthographicProjection.ToString());
writer.WriteAttributeString("ViewFlags", ((long)Viewport.Task.View.Flags).ToString());
writer.WriteAttributeString("ViewFlags", ((ulong)Viewport.Task.View.Flags).ToString());
}
/// <inheritdoc />
@@ -463,7 +463,7 @@ namespace FlaxEditor.Windows
if (bool.TryParse(node.GetAttribute("UseOrthographicProjection"), out value1))
Viewport.UseOrthographicProjection = value1;
if (long.TryParse(node.GetAttribute("ViewFlags"), out long value3))
if (ulong.TryParse(node.GetAttribute("ViewFlags"), out ulong value3))
Viewport.Task.ViewFlags = (ViewFlags)value3;
// Reset view flags if opening with different engine version (ViewFlags enum could be modified)

View File

@@ -91,6 +91,10 @@ namespace
void AudioSettings::Apply()
{
::MuteOnFocusLoss = MuteOnFocusLoss;
if (AudioBackend::Instance != nullptr)
{
Audio::SetDopplerFactor(DopplerFactor);
}
}
AudioDevice* Audio::GetActiveDevice()

View File

@@ -187,7 +187,7 @@ BoundingBox Model::GetBox(int32 lodIndex) const
return LODs[lodIndex].GetBox();
}
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals) const
void Model::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, int16 sortOrder) const
{
if (!CanBeRendered())
return;
@@ -203,7 +203,7 @@ void Model::Draw(const RenderContext& renderContext, MaterialBase* material, con
lodIndex = ClampLODIndex(lodIndex);
// Draw
LODs[lodIndex].Draw(renderContext, material, world, flags, receiveDecals);
LODs[lodIndex].Draw(renderContext, material, world, flags, receiveDecals, DrawPass::Default, 0, sortOrder);
}
template<typename ContextType>

View File

@@ -181,7 +181,8 @@ public:
/// <param name="world">The world transformation of the model.</param>
/// <param name="flags">The object static flags.</param>
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true) const;
/// <param name="sortOrder">Object sorting key.</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, int16 sortOrder = 0) const;
/// <summary>
/// Draws the model.

View File

@@ -267,6 +267,19 @@ namespace FlaxEngine
/// <remarks>This method may be preferred to <see cref="Float2.Length" /> when only a relative length is needed and speed is of the essence.</remarks>
public float LengthSquared => X * X + Y * Y;
/// <summary>
/// Gets the normalized vector. Returned vector has length equal 1.
/// </summary>
public Float2 Normalized
{
get
{
Float2 result = this;
result.Normalize();
return result;
}
}
/// <summary>
/// Converts the vector into a unit vector.
/// </summary>

View File

@@ -301,6 +301,19 @@ namespace FlaxEngine
}
}
/// <summary>
/// Gets the normalized vector. Returned vector has length equal 1.
/// </summary>
public Vector2 Normalized
{
get
{
Vector2 result = this;
result.Normalize();
return result;
}
}
/// <summary>
/// Creates an array containing the elements of the vector.
/// </summary>

View File

@@ -223,6 +223,15 @@ public:
return Vector2Base(-X, -Y);
}
/// <summary>
/// Calculates a normalized vector that has length equal to 1.
/// </summary>
Vector2Base GetNormalized() const
{
const T rcp = 1.0f / Length();
return Vector2Base(X * rcp, Y * rcp);
}
public:
/// <summary>
/// Performs vector normalization (scales vector up to unit length).

View File

@@ -161,6 +161,11 @@ namespace FlaxEngine
}
}
/// <summary>
/// Gets the aspect ratio used by the viewport.
/// </summary>
public float AspectRatio => !Mathf.IsZero(Height) ? Width / Height : 0f;
/// <summary>
/// Determines whether the specified <see cref="Viewport"/> is equal to this instance.
/// </summary>
@@ -326,21 +331,5 @@ namespace FlaxEngine
vector /= w;
}
}
/// <summary>
/// Gets the aspect ratio used by the viewport.
/// </summary>
/// <value>The aspect ratio.</value>
public float AspectRatio
{
get
{
if (!Mathf.IsZero(Height))
{
return Width / Height;
}
return 0f;
}
}
}
}

View File

@@ -164,5 +164,12 @@ constexpr bool EnumHasAllFlags(T value, T flags)
return ((__underlying_type(T))value & (__underlying_type(T))flags) == (__underlying_type(T))flags;
}
// Returns true if given enum value has none of enum flags set
template<typename T>
constexpr bool EnumHasNoneFlags(T value, T flags)
{
return ((__underlying_type(T))value & (__underlying_type(T))flags) == 0;
}
// Returns byte offset from the object pointer in vtable to the begin of the given inherited type implementation
#define VTABLE_OFFSET(type, baseType) (((intptr)static_cast<baseType*>((type*)1))-1)

View File

@@ -140,13 +140,13 @@ struct PsData
bool Create(GPUPipelineState::Description& desc)
{
desc.DepthTestEnable = true;
desc.DepthEnable = true;
desc.DepthWriteEnable = false;
Depth = GPUDevice::Instance->CreatePipelineState();
if (Depth->Init(desc))
return true;
desc.DepthTestEnable = false;
desc.DepthEnable = false;
NoDepthTest = GPUDevice::Instance->CreatePipelineState();
if (NoDepthTest->Init(desc))
return false;
@@ -156,7 +156,7 @@ struct PsData
NoDepthTestDepthWrite = GPUDevice::Instance->CreatePipelineState();
if (NoDepthTestDepthWrite->Init(desc))
return false;
desc.DepthTestEnable = true;
desc.DepthEnable = true;
DepthWrite = GPUDevice::Instance->CreatePipelineState();
return DepthWrite->Init(desc);
}

View File

@@ -1173,6 +1173,7 @@ void Foliage::Draw(RenderContext& renderContext)
draw.Flags = GetStaticFlags();
draw.LODBias = 0;
draw.ForcedLOD = -1;
draw.SortOrder = 0;
draw.VertexColors = nullptr;
draw.Lightmap = _scene->LightmapsData.GetReadyLightmap(instance.Lightmap.TextureIndex);
draw.LightmapUVs = &instance.Lightmap.UVsArea;

View File

@@ -514,7 +514,7 @@ public:
API_FIELD(ReadOnly) static BlendingMode Additive;
/// <summary>
/// Gets the alpha blending.
/// Gets the alpha blending. Source alpha controls the output color (0 - use destination color, 1 - use source color).
/// </summary>
API_FIELD(ReadOnly) static BlendingMode AlphaBlend;
@@ -591,22 +591,22 @@ API_ENUM() enum class Quality : byte
API_ENUM() enum class MaterialPostFxLocation : byte
{
/// <summary>
/// The after post processing pass using LDR input frame.
/// The 'after' post processing pass using LDR input frame.
/// </summary>
AfterPostProcessingPass = 0,
/// <summary>
/// The before post processing pass using HDR input frame.
/// The 'before' post processing pass using HDR input frame.
/// </summary>
BeforePostProcessingPass = 1,
/// <summary>
/// The before forward pass but after GBuffer with HDR input frame.
/// The 'before' forward pass but after GBuffer with HDR input frame.
/// </summary>
BeforeForwardPass = 2,
/// <summary>
/// The after custom post effects.
/// The 'after' custom post effects.
/// </summary>
AfterCustomPostEffects = 3,
@@ -620,6 +620,11 @@ API_ENUM() enum class MaterialPostFxLocation : byte
/// </summary>
AfterAntiAliasingPass = 5,
/// <summary>
/// The 'after' forward pass but before any post processing.
/// </summary>
AfterForwardPass = 6,
API_ENUM(Attributes="HideInEditor")
MAX,
};
@@ -635,7 +640,7 @@ API_ENUM() enum class PostProcessEffectLocation
Default = 0,
/// <summary>
///The 'before' in-build PostFx pass (bloom, color grading, etc.). After Forward Pass (transparency) and fog effects.
/// The 'before' in-build PostFx pass (bloom, color grading, etc.). After Forward Pass (transparency) and fog effects.
/// </summary>
BeforePostProcessingPass = 1,
@@ -659,6 +664,16 @@ API_ENUM() enum class PostProcessEffectLocation
/// </summary>
CustomUpscale = 5,
/// <summary>
/// The 'after' GBuffer rendering pass. Can be used to render custom geometry into GBuffer. Output is light buffer, single-target only (no output).
/// </summary>
AfterGBufferPass = 6,
/// <summary>
/// The 'after' forward pass but before any post processing.
/// </summary>
AfterForwardPass = 7,
API_ENUM(Attributes="HideInEditor")
MAX,
};
@@ -874,7 +889,7 @@ API_ENUM() enum class ViewMode
/// <summary>
/// Frame rendering flags used to switch between graphics features.
/// </summary>
API_ENUM(Attributes="Flags") enum class ViewFlags : int64
API_ENUM(Attributes="Flags") enum class ViewFlags : uint64
{
/// <summary>
/// Nothing.
@@ -1011,20 +1026,25 @@ API_ENUM(Attributes="Flags") enum class ViewFlags : int64
/// </summary>
GlobalSDF = 1 << 25,
/// <summary>
/// Shows/hides the Sky/Skybox rendering.
/// </summary>
Sky = 1 << 26,
/// <summary>
/// Default flags for Game.
/// </summary>
DefaultGame = Reflections | DepthOfField | Fog | Decals | MotionBlur | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | GlobalSDF,
DefaultGame = Reflections | DepthOfField | Fog | Decals | MotionBlur | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | GlobalSDF | Sky,
/// <summary>
/// Default flags for Editor.
/// </summary>
DefaultEditor = Reflections | Fog | Decals | DebugDraw | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | EditorSprites | ContactShadows | GlobalSDF,
DefaultEditor = Reflections | Fog | Decals | DebugDraw | SSR | AO | GI | DirectionalLights | PointLights | SpotLights | SkyLights | Shadows | SpecularLight | AntiAliasing | CustomPostProcess | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | EditorSprites | ContactShadows | GlobalSDF | Sky,
/// <summary>
/// Default flags for materials/models previews generating.
/// </summary>
DefaultAssetPreview = Reflections | Decals | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows,
DefaultAssetPreview = Reflections | Decals | DirectionalLights | PointLights | SpotLights | SkyLights | SpecularLight | AntiAliasing | Bloom | ToneMapping | EyeAdaptation | CameraArtifacts | LensFlares | ContactShadows | Sky,
};
DECLARE_ENUM_OPERATORS(ViewFlags);

View File

@@ -315,6 +315,12 @@ public:
/// <param name="rts">The array with render targets to bind.</param>
API_FUNCTION() virtual void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) = 0;
/// <summary>
/// Sets the blend factor that modulate values for a pixel shader, render target, or both.
/// </summary>
/// <param name="value">Blend factors, one for each RGBA component.</param>
API_FUNCTION() virtual void SetBlendFactor(const Float4& value) = 0;
public:
/// <summary>
/// Unbinds all shader resource slots and flushes the change with the driver (used to prevent driver detection of resource hazards, eg. when down-scaling the texture).

View File

@@ -76,7 +76,7 @@ bool GPUPipelineState::Init(const Description& desc)
Complexity += tessCost;
if (desc.DepthWriteEnable)
Complexity += 5;
if (desc.DepthTestEnable)
if (desc.DepthEnable)
Complexity += 5;
if (desc.BlendMode.BlendEnable)
Complexity += 20;

View File

@@ -134,7 +134,7 @@ public:
/// <summary>
/// Quad rendering shader
/// </summary>
GPUShader* QuadShader;
API_FIELD(ReadOnly) GPUShader* QuadShader;
/// <summary>
/// The current task being executed.

View File

@@ -24,16 +24,16 @@ public:
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Description);
/// <summary>
/// Enable/disable depth (DepthFunc and DepthWriteEnable)
/// </summary>
API_FIELD() bool DepthEnable;
/// <summary>
/// Enable/disable depth write
/// </summary>
API_FIELD() bool DepthWriteEnable;
/// <summary>
/// Enable/disable depth test
/// </summary>
API_FIELD() bool DepthTestEnable;
/// <summary>
/// Enable/disable depth clipping
/// </summary>

View File

@@ -137,8 +137,13 @@ void DeferredMaterialShader::Unload()
bool DeferredMaterialShader::Load()
{
auto psDesc = GPUPipelineState::Description::Default;
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
if (EnumHasAnyFlags(_info.FeaturesFlags, MaterialFeaturesFlags::DisableDepthTest))
{
psDesc.DepthFunc = ComparisonFunc::Always;
if (!psDesc.DepthWriteEnable)
psDesc.DepthEnable = false;
}
// Check if use tessellation (both material and runtime supports it)
const bool useTess = _info.TessellationMode != TessellationMethod::None && GPUDevice::Instance->Limits.HasTessellation;
@@ -183,7 +188,7 @@ bool DeferredMaterialShader::Load()
// Motion Vectors pass
psDesc.DepthWriteEnable = false;
psDesc.DepthTestEnable = true;
psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::LessEqual;
psDesc.VS = _shader->GetVS("VS");
psDesc.PS = _shader->GetPS("PS_MotionVectors");
@@ -201,7 +206,7 @@ bool DeferredMaterialShader::Load()
psDesc.CullMode = CullMode::TwoSided;
psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true;
psDesc.DepthTestEnable = true;
psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less;
psDesc.HS = nullptr;
psDesc.DS = nullptr;

View File

@@ -112,7 +112,7 @@ bool DeformableMaterialShader::Load()
{
_drawModes = DrawPass::Depth | DrawPass::QuadOverdraw;
auto psDesc = GPUPipelineState::Description::Default;
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
@@ -170,7 +170,7 @@ bool DeformableMaterialShader::Load()
psDesc.CullMode = CullMode::TwoSided;
psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true;
psDesc.DepthTestEnable = true;
psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less;
psDesc.HS = nullptr;
psDesc.DS = nullptr;

View File

@@ -130,7 +130,7 @@ bool ForwardMaterialShader::Load()
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
auto psDesc = GPUPipelineState::Description::Default;
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
@@ -200,7 +200,7 @@ bool ForwardMaterialShader::Load()
psDesc.CullMode = CullMode::TwoSided;
psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true;
psDesc.DepthTestEnable = true;
psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less;
psDesc.HS = nullptr;
psDesc.DS = nullptr;

View File

@@ -89,13 +89,13 @@ bool GUIMaterialShader::Load()
psDesc0.PS = _shader->GetPS("PS_GUI");
psDesc0.BlendMode = BlendingMode::AlphaBlend;
psDesc0.DepthTestEnable = psDesc0.DepthWriteEnable = true;
psDesc0.DepthEnable = psDesc0.DepthWriteEnable = true;
_cache.Depth = GPUDevice::Instance->CreatePipelineState();
_cache.NoDepth = GPUDevice::Instance->CreatePipelineState();
bool failed = _cache.Depth->Init(psDesc0);
psDesc0.DepthTestEnable = psDesc0.DepthWriteEnable = false;
psDesc0.DepthEnable = psDesc0.DepthWriteEnable = false;
failed |= _cache.NoDepth->Init(psDesc0);
if (failed)

View File

@@ -10,7 +10,7 @@
/// <summary>
/// Current materials shader version.
/// </summary>
#define MATERIAL_GRAPH_VERSION 159
#define MATERIAL_GRAPH_VERSION 161
class Material;
class GPUShader;

View File

@@ -154,9 +154,6 @@ void ParticleMaterialShader::Bind(BindParameters& params)
materialData->RibbonUVOffset.Y = drawCall.Particle.Ribbon.UVOffsetY;
materialData->RibbonSegmentCount = drawCall.Particle.Ribbon.SegmentCount;
if (drawCall.Particle.Ribbon.SegmentDistances)
context->BindSR(1, drawCall.Particle.Ribbon.SegmentDistances->View());
break;
}
}
@@ -189,7 +186,7 @@ bool ParticleMaterialShader::Load()
{
_drawModes = DrawPass::Depth | DrawPass::Forward | DrawPass::QuadOverdraw;
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
auto vsSprite = _shader->GetVS("VS_Sprite");

View File

@@ -133,7 +133,7 @@ void TerrainMaterialShader::Unload()
bool TerrainMaterialShader::Load()
{
GPUPipelineState::Description psDesc = GPUPipelineState::Description::Default;
psDesc.DepthTestEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthTest) == MaterialFeaturesFlags::None;
psDesc.DepthWriteEnable = (_info.FeaturesFlags & MaterialFeaturesFlags::DisableDepthWrite) == MaterialFeaturesFlags::None;
// Check if use tessellation (both material and runtime supports it)
@@ -182,7 +182,7 @@ bool TerrainMaterialShader::Load()
psDesc.BlendMode = BlendingMode::Opaque;
psDesc.DepthClipEnable = false;
psDesc.DepthWriteEnable = true;
psDesc.DepthTestEnable = true;
psDesc.DepthEnable = true;
psDesc.DepthFunc = ComparisonFunc::Less;
psDesc.HS = nullptr;
psDesc.DS = nullptr;

View File

@@ -408,7 +408,7 @@ void Mesh::Render(GPUContext* context) const
context->DrawIndexedInstanced(_triangles * 3, 1, 0, 0, 0);
}
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom) const
void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, const Matrix& world, StaticFlags flags, bool receiveDecals, DrawPass drawModes, float perInstanceRandom, int16 sortOrder) const
{
if (!material || !material->IsSurface() || !IsInitialized())
return;
@@ -446,7 +446,7 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons
#endif
// Push draw call to the render list
renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, receiveDecals);
renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, receiveDecals, sortOrder);
}
void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float lodDitherFactor) const
@@ -512,7 +512,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
#endif
// Push draw call to the render list
renderContext.List->AddDrawCall(renderContext, drawModes, info.Flags, drawCall, entry.ReceiveDecals);
renderContext.List->AddDrawCall(renderContext, drawModes, info.Flags, drawCall, entry.ReceiveDecals, info.SortOrder);
}
void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& info, float lodDitherFactor) const
@@ -575,7 +575,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in
const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
const auto drawModes = info.DrawModes & material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, info.Flags, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals);
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, info.Flags, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals, info.SortOrder);
}
bool Mesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const

View File

@@ -6,14 +6,11 @@
#include "ModelInstanceEntry.h"
#include "Config.h"
#include "Types.h"
#include "Engine/Level/Types.h"
#if USE_PRECISE_MESH_INTERSECTS
#include "CollisionProxy.h"
#endif
struct GeometryDrawStateData;
class Lightmap;
class GPUBuffer;
/// <summary>
/// Represents part of the model that is made of vertices and can be rendered using custom material and transformation.
@@ -275,72 +272,6 @@ public:
/// <param name="drawCall">The draw call.</param>
void GetDrawCallGeometry(DrawCall& drawCall) const;
/// <summary>
/// Model instance drawing packed data.
/// </summary>
struct DrawInfo
{
/// <summary>
/// The instance buffer to use during model rendering.
/// </summary>
ModelInstanceEntries* Buffer;
/// <summary>
/// The world transformation of the model.
/// </summary>
Matrix* World;
/// <summary>
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
/// </summary>
GeometryDrawStateData* DrawState;
/// <summary>
/// The lightmap.
/// </summary>
const Lightmap* Lightmap;
/// <summary>
/// The lightmap UVs.
/// </summary>
const Rectangle* LightmapUVs;
/// <summary>
/// The model instance vertex colors buffers (per-lod all meshes packed in a single allocation, array length equal to model lods count).
/// </summary>
GPUBuffer** VertexColors;
/// <summary>
/// The object static flags.
/// </summary>
StaticFlags Flags;
/// <summary>
/// The object draw modes.
/// </summary>
DrawPass DrawModes;
/// <summary>
/// The bounds of the model (used to select a proper LOD during rendering).
/// </summary>
BoundingSphere Bounds;
/// <summary>
/// The per-instance random value.
/// </summary>
float PerInstanceRandom;
/// <summary>
/// The LOD bias value.
/// </summary>
char LODBias;
/// <summary>
/// The forced LOD to use. Value -1 disables this feature.
/// </summary>
char ForcedLOD;
};
/// <summary>
/// Draws the mesh. Binds vertex and index buffers and invokes the draw call.
/// </summary>
@@ -357,7 +288,8 @@ public:
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f) const;
/// <param name="sortOrder">Object sorting key.</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int16 sortOrder = 0) const;
/// <summary>
/// Draws the mesh.

View File

@@ -5,12 +5,20 @@
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Graphics/Enums.h"
#include "Engine/Graphics/Models/Types.h"
#include "Engine/Level/Types.h"
#include "Engine/Scripting/ScriptingObject.h"
struct GeometryDrawStateData;
struct RenderContext;
struct RenderContextBatch;
class Task;
class ModelBase;
struct RenderContextBatch;
class Lightmap;
class GPUBuffer;
class SkinnedMeshDrawData;
class BlendShapesInstance;
/// <summary>
/// Base class for model resources meshes.
@@ -143,4 +151,95 @@ public:
/// <param name="count">The amount of items inside the result buffer.</param>
/// <returns>True if failed, otherwise false</returns>
virtual bool DownloadDataCPU(MeshBufferType type, BytesContainer& result, int32& count) const = 0;
public:
/// <summary>
/// Model instance drawing packed data.
/// </summary>
struct DrawInfo
{
/// <summary>
/// The instance buffer to use during model rendering
/// </summary>
ModelInstanceEntries* Buffer;
/// <summary>
/// The world transformation of the model.
/// </summary>
Matrix* World;
/// <summary>
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
/// </summary>
GeometryDrawStateData* DrawState;
union
{
struct
{
/// <summary>
/// The skinning.
/// </summary>
SkinnedMeshDrawData* Skinning;
/// <summary>
/// The blend shapes.
/// </summary>
BlendShapesInstance* BlendShapes;
};
struct
{
/// <summary>
/// The lightmap.
/// </summary>
const Lightmap* Lightmap;
/// <summary>
/// The lightmap UVs.
/// </summary>
const Rectangle* LightmapUVs;
};
};
/// <summary>
/// The model instance vertex colors buffers (per-lod all meshes packed in a single allocation, array length equal to model lods count).
/// </summary>
GPUBuffer** VertexColors;
/// <summary>
/// The object static flags.
/// </summary>
StaticFlags Flags;
/// <summary>
/// The object draw modes.
/// </summary>
DrawPass DrawModes;
/// <summary>
/// The bounds of the model (used to select a proper LOD during rendering).
/// </summary>
BoundingSphere Bounds;
/// <summary>
/// The per-instance random value.
/// </summary>
float PerInstanceRandom;
/// <summary>
/// The LOD bias value.
/// </summary>
char LODBias;
/// <summary>
/// The forced LOD to use. Value -1 disables this feature.
/// </summary>
char ForcedLOD;
/// <summary>
/// The object sorting key.
/// </summary>
int16 SortOrder;
};
};

View File

@@ -124,9 +124,7 @@ public:
FORCE_INLINE void Render(GPUContext* context)
{
for (int32 i = 0; i < Meshes.Count(); i++)
{
Meshes.Get()[i].Render(context);
}
}
/// <summary>
@@ -139,12 +137,11 @@ public:
/// <param name="receiveDecals">True if rendered geometry can receive decals, otherwise false.</param>
/// <param name="drawModes">The draw passes to use for rendering this object.</param>
/// <param name="perInstanceRandom">The random per-instance value (normalized to range 0-1).</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f) const
/// <param name="sortOrder">Object sorting key.</param>
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, API_PARAM(Ref) const Matrix& world, StaticFlags flags = StaticFlags::None, bool receiveDecals = true, DrawPass drawModes = DrawPass::Default, float perInstanceRandom = 0.0f, int16 sortOrder = 0) const
{
for (int32 i = 0; i < Meshes.Count(); i++)
{
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom);
}
Meshes.Get()[i].Draw(renderContext, material, world, flags, receiveDecals, drawModes, perInstanceRandom, sortOrder);
}
/// <summary>
@@ -156,9 +153,7 @@ public:
FORCE_INLINE void Draw(const RenderContext& renderContext, const Mesh::DrawInfo& info, float lodDitherFactor) const
{
for (int32 i = 0; i < Meshes.Count(); i++)
{
Meshes.Get()[i].Draw(renderContext, info, lodDitherFactor);
}
}
/// <summary>
@@ -170,8 +165,6 @@ public:
FORCE_INLINE void Draw(const RenderContextBatch& renderContextBatch, const Mesh::DrawInfo& info, float lodDitherFactor) const
{
for (int32 i = 0; i < Meshes.Count(); i++)
{
Meshes.Get()[i].Draw(renderContextBatch, info, lodDitherFactor);
}
}
};

View File

@@ -119,28 +119,22 @@ bool SkinnedMesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0Skinne
bool SkinnedMesh::Intersects(const Ray& ray, const Matrix& world, Real& distance, Vector3& normal) const
{
// Transform points
Vector3 min, max;
Vector3::Transform(_box.Minimum, world, min);
Vector3::Transform(_box.Maximum, world, max);
BoundingBox transformedBox;
Vector3::Transform(_box.Minimum, world, transformedBox.Minimum);
Vector3::Transform(_box.Maximum, world, transformedBox.Maximum);
// Get transformed box
BoundingBox transformedBox(min, max);
// Test ray on a box
// Test ray on a transformed box
return transformedBox.Intersects(ray, distance, normal);
}
bool SkinnedMesh::Intersects(const Ray& ray, const Transform& transform, Real& distance, Vector3& normal) const
{
// Transform points
Vector3 min, max;
transform.LocalToWorld(_box.Minimum, min);
transform.LocalToWorld(_box.Maximum, max);
BoundingBox transformedBox;
transform.LocalToWorld(_box.Minimum, transformedBox.Minimum);
transform.LocalToWorld(_box.Maximum, transformedBox.Maximum);
// Get transformed box
BoundingBox transformedBox(min, max);
// Test ray on a box
// Test ray on a transformed box
return transformedBox.Intersects(ray, distance, normal);
}
@@ -216,7 +210,7 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info,
drawCall.PerInstanceRandom = info.PerInstanceRandom;
// Push draw call to the render list
renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals);
renderContext.List->AddDrawCall(renderContext, drawModes, StaticFlags::None, drawCall, entry.ReceiveDecals, info.SortOrder);
}
void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& info, float lodDitherFactor) const
@@ -279,7 +273,7 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI
const auto shadowsMode = entry.ShadowsMode & slot.ShadowsMode;
const auto drawModes = info.DrawModes & material->GetDrawModes();
if (drawModes != DrawPass::None)
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals);
renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals, info.SortOrder);
}
bool SkinnedMesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const

View File

@@ -6,11 +6,6 @@
#include "Types.h"
#include "BlendShape.h"
struct GeometryDrawStateData;
struct RenderContext;
class GPUBuffer;
class SkinnedMeshDrawData;
/// <summary>
/// Represents part of the skinned model that is made of vertices and can be rendered using custom material, transformation and skeleton bones hierarchy.
/// </summary>
@@ -170,62 +165,6 @@ public:
}
public:
/// <summary>
/// Model instance drawing packed data.
/// </summary>
struct DrawInfo
{
/// <summary>
/// The instance buffer to use during model rendering
/// </summary>
ModelInstanceEntries* Buffer;
/// <summary>
/// The skinning.
/// </summary>
SkinnedMeshDrawData* Skinning;
/// <summary>
/// The blend shapes.
/// </summary>
BlendShapesInstance* BlendShapes;
/// <summary>
/// The world transformation of the model.
/// </summary>
Matrix* World;
/// <summary>
/// The instance drawing state data container. Used for LOD transition handling and previous world transformation matrix updating.
/// </summary>
GeometryDrawStateData* DrawState;
/// <summary>
/// The object draw modes.
/// </summary>
DrawPass DrawModes;
/// <summary>
/// The bounds of the model (used to select a proper LOD during rendering).
/// </summary>
BoundingSphere Bounds;
/// <summary>
/// The per-instance random value.
/// </summary>
float PerInstanceRandom;
/// <summary>
/// The LOD bias value.
/// </summary>
char LODBias;
/// <summary>
/// The forced LOD to use. Value -1 disables this feature.
/// </summary>
char ForcedLOD;
};
/// <summary>
/// Draws the mesh. Binds vertex and index buffers and invokes the draw call.
/// </summary>

View File

@@ -128,6 +128,8 @@ void RenderBuffers::SetUseAlpha(bool value)
const RenderBuffers::CustomBuffer* RenderBuffers::FindCustomBuffer(const StringView& name) const
{
if (LinkedCustomBuffers)
return LinkedCustomBuffers->FindCustomBuffer(name);
for (const CustomBuffer* e : CustomBuffers)
{
if (e->Name == name)
@@ -196,6 +198,7 @@ bool RenderBuffers::Init(int32 width, int32 height)
void RenderBuffers::Release()
{
LastEyeAdaptationTime = 0;
LinkedCustomBuffers = nullptr;
for (int32 i = 0; i < _resources.Count(); i++)
_resources[i]->ReleaseGPU();

View File

@@ -45,10 +45,14 @@ public:
{
struct
{
GPUTexture* GBuffer0;
GPUTexture* GBuffer1;
GPUTexture* GBuffer2;
GPUTexture* GBuffer3;
/// <summary>Gets the GBuffer texture 0. RGB: Color, A: AO</summary>
API_FIELD(ReadOnly) GPUTexture* GBuffer0;
/// <summary>Gets the GBuffer texture 1. RGB: Normal, A: ShadingModel</summary>
API_FIELD(ReadOnly) GPUTexture* GBuffer1;
/// <summary>Gets the GBuffer texture 2. R: Roughness, G: Metalness, B:Specular</summary>
API_FIELD(ReadOnly) GPUTexture* GBuffer2;
/// <summary>Gets the GBuffer texture 3. RGBA: Custom Data</summary>
API_FIELD(ReadOnly) GPUTexture* GBuffer3;
};
GPUTexture* GBuffer[4];
@@ -174,6 +178,8 @@ public:
template<class T>
T* GetCustomBuffer(const StringView& name)
{
if (LinkedCustomBuffers)
return LinkedCustomBuffers->GetCustomBuffer<T>(name);
CustomBuffer* result = (CustomBuffer*)FindCustomBuffer(name);
if (!result)
{
@@ -202,6 +208,11 @@ public:
/// </remarks>
API_FIELD(ReadOnly) GPUTexture* MotionVectors;
/// <summary>
/// External Render Buffers used to redirect FindCustomBuffer/GetCustomBuffer calls. Can be linked to other rendering task (eg. main game viewport) to reuse graphics effect state from it (eg. use GI from main game view in in-game camera renderer).
/// </summary>
API_FIELD() RenderBuffers* LinkedCustomBuffers = nullptr;
public:
/// <summary>
/// Allocates the buffers.

View File

@@ -154,7 +154,7 @@ void SceneRenderTask::CameraCut()
void SceneRenderTask::AddCustomActor(Actor* actor)
{
CustomActors.Add(actor);
CustomActors.AddUnique(actor);
}
void SceneRenderTask::RemoveCustomActor(Actor* actor)
@@ -169,7 +169,7 @@ void SceneRenderTask::ClearCustomActors()
void SceneRenderTask::AddCustomPostFx(PostProcessEffect* fx)
{
CustomPostFx.Add(fx);
CustomPostFx.AddUnique(fx);
}
void SceneRenderTask::RemoveCustomPostFx(PostProcessEffect* fx)
@@ -179,7 +179,7 @@ void SceneRenderTask::RemoveCustomPostFx(PostProcessEffect* fx)
void SceneRenderTask::AddGlobalCustomPostFx(PostProcessEffect* fx)
{
GlobalCustomPostFx.Add(fx);
GlobalCustomPostFx.AddUnique(fx);
}
void SceneRenderTask::RemoveGlobalCustomPostFx(PostProcessEffect* fx)

View File

@@ -181,116 +181,75 @@ uint32 GetHash(const BlendingMode& key)
return hash;
}
// @formatter:off
BlendingMode BlendingMode::Opaque =
{
false,
// AlphaToCoverageEnable
false,
// BlendEnable
Blend::One,
// SrcBlend
Blend::Zero,
// DestBlend
Operation::Add,
// BlendOp
Blend::One,
// SrcBlendAlpha
Blend::Zero,
// DestBlendAlpha
Operation::Add,
// BlendOpAlpha
ColorWrite::All,
// RenderTargetWriteMask
false, // AlphaToCoverageEnable
false, // BlendEnable
Blend::One, // SrcBlend
Blend::Zero, // DestBlend
Operation::Add, // BlendOp
Blend::One, // SrcBlendAlpha
Blend::Zero, // DestBlendAlpha
Operation::Add, // BlendOpAlpha
ColorWrite::All, // RenderTargetWriteMask
};
BlendingMode BlendingMode::Additive =
{
false,
// AlphaToCoverageEnable
true,
// BlendEnable
Blend::SrcAlpha,
// SrcBlend
Blend::One,
// DestBlend
Operation::Add,
// BlendOp
Blend::SrcAlpha,
// SrcBlendAlpha
Blend::One,
// DestBlendAlpha
Operation::Add,
// BlendOpAlpha
ColorWrite::All,
// RenderTargetWriteMask
false, // AlphaToCoverageEnable
true, // BlendEnable
Blend::SrcAlpha, // SrcBlend
Blend::One, // DestBlend
Operation::Add, // BlendOp
Blend::SrcAlpha, // SrcBlendAlpha
Blend::One, // DestBlendAlpha
Operation::Add, // BlendOpAlpha
ColorWrite::All, // RenderTargetWriteMask
};
BlendingMode BlendingMode::AlphaBlend =
{
false,
// AlphaToCoverageEnable
true,
// BlendEnable
Blend::SrcAlpha,
// SrcBlend
Blend::InvSrcAlpha,
// DestBlend
Operation::Add,
// BlendOp
Blend::One,
// SrcBlendAlpha
Blend::InvSrcAlpha,
// DestBlendAlpha
Operation::Add,
// BlendOpAlpha
ColorWrite::All,
// RenderTargetWriteMask
false, // AlphaToCoverageEnable
true, // BlendEnable
Blend::SrcAlpha, // SrcBlend
Blend::InvSrcAlpha, // DestBlend
Operation::Add, // BlendOp
Blend::One, // SrcBlendAlpha
Blend::InvSrcAlpha, // DestBlendAlpha
Operation::Add, // BlendOpAlpha
ColorWrite::All, // RenderTargetWriteMask
};
BlendingMode BlendingMode::Add =
{
false,
// AlphaToCoverageEnable
true,
// BlendEnable
Blend::One,
// SrcBlend
Blend::One,
// DestBlend
Operation::Add,
// BlendOp
Blend::One,
// SrcBlendAlpha
Blend::One,
// DestBlendAlpha
Operation::Add,
// BlendOpAlpha
ColorWrite::All,
// RenderTargetWriteMask
false, // AlphaToCoverageEnable
true, // BlendEnable
Blend::One, // SrcBlend
Blend::One, // DestBlend
Operation::Add, // BlendOp
Blend::One, // SrcBlendAlpha
Blend::One, // DestBlendAlpha
Operation::Add, // BlendOpAlpha
ColorWrite::All, // RenderTargetWriteMask
};
BlendingMode BlendingMode::Multiply =
{
false,
// AlphaToCoverageEnable
true,
// BlendEnable
Blend::Zero,
// SrcBlend
Blend::SrcColor,
// DestBlend
Operation::Add,
// BlendOp
Blend::Zero,
// SrcBlendAlpha
Blend::SrcAlpha,
// DestBlendAlpha
Operation::Add,
// BlendOpAlpha
ColorWrite::All,
// RenderTargetWriteMask
false, // AlphaToCoverageEnable
true, // BlendEnable
Blend::Zero, // SrcBlend
Blend::SrcColor, // DestBlend
Operation::Add, // BlendOp
Blend::Zero, // SrcBlendAlpha
Blend::SrcAlpha, // DestBlendAlpha
Operation::Add, // BlendOpAlpha
ColorWrite::All, // RenderTargetWriteMask
};
// @formatter:on
FeatureLevel RenderTools::GetFeatureLevel(ShaderProfile profile)
{
switch (profile)

View File

@@ -84,6 +84,14 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f
MainScreenSize = mainView->ScreenSize;
}
void RenderView::SetUp(const Matrix& viewProjection)
{
// Copy data
Matrix::Invert(viewProjection, IVP);
Frustum.SetMatrix(viewProjection);
CullingFrustum = Frustum;
}
void RenderView::SetUp(const Matrix& view, const Matrix& projection)
{
// Copy data

View File

@@ -255,13 +255,7 @@ public:
public:
// Set up view with custom params
// @param viewProjection View * Projection matrix
void SetUp(const Matrix& viewProjection)
{
// Copy data
Matrix::Invert(viewProjection, IVP);
Frustum.SetMatrix(viewProjection);
CullingFrustum = Frustum;
}
void SetUp(const Matrix& viewProjection);
// Set up view with custom params
// @param view View matrix

View File

@@ -103,6 +103,7 @@ void GPUContextDX11::FrameBegin()
CurrentPS = nullptr;
CurrentCS = nullptr;
CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
CurrentBlendFactor = Float4::One;
// Bind static samplers
ID3D11SamplerState* samplers[] =
@@ -267,6 +268,13 @@ void GPUContextDX11::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPU
}
}
void GPUContextDX11::SetBlendFactor(const Float4& value)
{
CurrentBlendFactor = value;
if (CurrentBlendState)
_context->OMSetBlendState(CurrentBlendState, CurrentBlendFactor.Raw, D3D11_DEFAULT_SAMPLE_MASK);
}
void GPUContextDX11::ResetSR()
{
_srDirtyFlag = false;
@@ -420,6 +428,7 @@ void GPUContextDX11::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCoun
void GPUContextDX11::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
ASSERT(bufferForArgs && EnumHasAnyFlags(bufferForArgs->GetFlags(), GPUBufferFlags::Argument));
CurrentCS = (GPUShaderProgramCSDX11*)shader;
auto bufferForArgsDX11 = (GPUBufferDX11*)bufferForArgs;
@@ -560,8 +569,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state)
if (CurrentBlendState != blendState)
{
CurrentBlendState = blendState;
FLOAT blendFactor[4] = { 1, 1, 1, 1 };
_context->OMSetBlendState(blendState, blendFactor, D3D11_DEFAULT_SAMPLE_MASK);
_context->OMSetBlendState(blendState, CurrentBlendFactor.Raw, D3D11_DEFAULT_SAMPLE_MASK);
}
if (CurrentVS != vs)
{

View File

@@ -61,6 +61,7 @@ private:
GPUShaderProgramPSDX11* CurrentPS;
GPUShaderProgramCSDX11* CurrentCS;
D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology;
Float4 CurrentBlendFactor;
public:
@@ -115,6 +116,7 @@ public:
void SetRenderTarget(GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;

View File

@@ -48,7 +48,7 @@ bool GPUPipelineStateDX11::Init(const Description& desc)
PrimitiveTopology = (D3D11_PRIMITIVE_TOPOLOGY)((int32)D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (HS->GetControlPointsCount() - 1));
// States
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthTestEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
DepthStencilStateIndex = static_cast<int32>(desc.DepthFunc) + (desc.DepthEnable ? 0 : 9) + (desc.DepthWriteEnable ? 0 : 18);
RasterizerStateIndex = static_cast<int32>(desc.CullMode) + (desc.Wireframe ? 0 : 3) + (desc.DepthClipEnable ? 0 : 6);
BlendState = _device->GetBlendState(desc.BlendMode);

View File

@@ -111,7 +111,7 @@ bool GPUBufferDX12::OnInit()
if (useUAV)
resourceDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
#if PLATFORM_XBOX_SCARLETT || PLATFORM_XBOX_ONE
if (_desc.Flags & GPUBufferFlags::Argument)
if (EnumHasAnyFlags(_desc.Flags, GPUBufferFlags::Argument))
resourceDesc.Flags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER;
#endif

View File

@@ -845,6 +845,11 @@ void GPUContextDX12::SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPU
}
}
void GPUContextDX12::SetBlendFactor(const Float4& value)
{
_commandList->OMSetBlendFactor(value.Raw);
}
void GPUContextDX12::ResetSR()
{
for (int32 slot = 0; slot < GPU_MAX_SR_BINDED; slot++)

View File

@@ -166,6 +166,7 @@ public:
void SetRenderTarget(GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;

View File

@@ -172,7 +172,7 @@ bool GPUPipelineStateDX12::Init(const Description& desc)
}
// Depth State
psDesc.DepthStencilState.DepthEnable = !!desc.DepthTestEnable;
psDesc.DepthStencilState.DepthEnable = !!desc.DepthEnable;
psDesc.DepthStencilState.DepthWriteMask = desc.DepthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
psDesc.DepthStencilState.DepthFunc = static_cast<D3D12_COMPARISON_FUNC>(desc.DepthFunc);
psDesc.DepthStencilState.StencilEnable = FALSE;

View File

@@ -84,6 +84,10 @@ public:
{
}
void SetBlendFactor(const Float4& value) override
{
}
void ResetSR() override
{
}

View File

@@ -966,6 +966,12 @@ void GPUContextVulkan::SetRenderTarget(GPUTextureView* depthBuffer, const Span<G
}
}
void GPUContextVulkan::SetBlendFactor(const Float4& value)
{
const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer();
vkCmdSetBlendConstants(cmdBuffer->GetHandle(), value.Raw);
}
void GPUContextVulkan::ResetSR()
{
Platform::MemoryClear(_srHandles, sizeof(_srHandles));

View File

@@ -184,6 +184,7 @@ public:
void SetRenderTarget(GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override;
void SetRenderTarget(GPUTextureView* depthBuffer, const Span<GPUTextureView*>& rts) override;
void SetBlendFactor(const Float4& value) override;
void ResetSR() override;
void ResetUA() override;
void ResetCB() override;

View File

@@ -286,7 +286,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc)
// Depth Stencil
RenderToolsVulkan::ZeroStruct(_descDepthStencil, VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO);
_descDepthStencil.depthTestEnable = desc.DepthTestEnable;
_descDepthStencil.depthTestEnable = desc.DepthEnable;
_descDepthStencil.depthWriteEnable = desc.DepthWriteEnable;
_descDepthStencil.depthCompareOp = RenderToolsVulkan::ToVulkanCompareOp(desc.DepthFunc);
_desc.pDepthStencilState = &_descDepthStencil;

View File

@@ -31,6 +31,15 @@ void Gamepad::ResetState()
_mappedPrevState.Clear();
}
bool Gamepad::IsAnyButtonDown() const
{
// TODO: optimize with SIMD
bool result = false;
for (auto e : _state.Buttons)
result |= e;
return result;
}
bool Gamepad::Update(EventQueue& queue)
{
// Copy state

View File

@@ -164,6 +164,11 @@ public:
return _mappedState.Buttons[static_cast<int32>(button)] && !_mappedPrevState.Buttons[static_cast<int32>(button)];
}
/// <summary>
/// Checks if any gamepad button is currently pressed.
/// </summary>
API_PROPERTY() bool IsAnyButtonDown() const;
/// <summary>
/// Gets the gamepad button up state (true if was released during the current frame).
/// </summary>

View File

@@ -183,6 +183,15 @@ void Mouse::OnMouseDown(const Float2& position, const MouseButton button, Window
e.MouseData.Position = position;
}
bool Mouse::IsAnyButtonDown() const
{
// TODO: optimize with SIMD
bool result = false;
for (auto e : Mouse::_state.MouseButtons)
result |= e;
return result;
}
void Mouse::OnMouseUp(const Float2& position, const MouseButton button, Window* target)
{
Event& e = _queue.AddOne();

View File

@@ -64,6 +64,11 @@ public:
return _state.MousePosition;
}
/// <summary>
/// Checks if any mouse button is currently pressed.
/// </summary>
API_PROPERTY() bool IsAnyButtonDown() const;
/// <summary>
/// Gets the delta position of the mouse in the screen-space coordinates.
/// </summary>

View File

@@ -737,6 +737,7 @@ void AnimatedModel::Draw(RenderContext& renderContext)
draw.PerInstanceRandom = GetPerInstanceRandom();
draw.LODBias = LODBias;
draw.ForcedLOD = ForcedLOD;
draw.SortOrder = SortOrder;
SkinnedModel->Draw(renderContext, draw);
}
@@ -777,6 +778,7 @@ void AnimatedModel::Draw(RenderContextBatch& renderContextBatch)
draw.PerInstanceRandom = GetPerInstanceRandom();
draw.LODBias = LODBias;
draw.ForcedLOD = ForcedLOD;
draw.SortOrder = SortOrder;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if (ShadowsMode != ShadowsCastingMode::All)
@@ -851,6 +853,7 @@ void AnimatedModel::Serialize(SerializeStream& stream, const void* otherObj)
SERIALIZE(CustomBounds);
SERIALIZE(LODBias);
SERIALIZE(ForcedLOD);
SERIALIZE(SortOrder);
SERIALIZE(DrawModes);
PRAGMA_DISABLE_DEPRECATION_WARNINGS
SERIALIZE(ShadowsMode);
@@ -877,6 +880,7 @@ void AnimatedModel::Deserialize(DeserializeStream& stream, ISerializeModifier* m
DESERIALIZE(CustomBounds);
DESERIALIZE(LODBias);
DESERIALIZE(ForcedLOD);
DESERIALIZE(SortOrder);
DESERIALIZE(DrawModes);
PRAGMA_DISABLE_DEPRECATION_WARNINGS
DESERIALIZE(ShadowsMode);

Some files were not shown because too many files have changed in this diff Show More