Merge remote-tracking branch 'origin/master' into 1.11
# Conflicts: # Source/Engine/Level/Actors/Sky.cpp
This commit is contained in:
14
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
14
.github/ISSUE_TEMPLATE/1-bug.yaml
vendored
@@ -5,19 +5,19 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Please attach any minimal repoduction projects!
|
||||
Thanks for taking the time to fill out this bug report! Please attach any minimal reproduction projects!
|
||||
- type: textarea
|
||||
id: description-area
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide a description and what you expected to happen.
|
||||
description: Please provide a description of the bug and what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps-area
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Please provide an repoduction steps.
|
||||
description: Please provide reproduction steps if possible.
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -26,10 +26,10 @@ body:
|
||||
label: Version
|
||||
description: What version of Flax are you running?
|
||||
options:
|
||||
- 1.8
|
||||
- 1.9
|
||||
- 1.10
|
||||
- 1.11
|
||||
- '1.8'
|
||||
- '1.9'
|
||||
- '1.10'
|
||||
- '1.11'
|
||||
- master branch
|
||||
default: 2
|
||||
validations:
|
||||
|
||||
@@ -14,9 +14,9 @@ body:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: benifits-area
|
||||
id: benefits-area
|
||||
attributes:
|
||||
label: Benifits
|
||||
description: Please provide what benifits this feature would provide to the engine!
|
||||
label: Benefits
|
||||
description: Please provide what benefits this feature would provide to the engine!
|
||||
validations:
|
||||
required: true
|
||||
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
BIN
Content/Shaders/Sky.flax
(Stored with Git LFS)
Binary file not shown.
@@ -32,7 +32,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
private void OnImageClicked(Image image, MouseButton button)
|
||||
{
|
||||
var texture = Values[0] as GPUTexture;
|
||||
if (!texture)
|
||||
if (!texture || button != MouseButton.Right)
|
||||
return;
|
||||
var menu = new ContextMenu();
|
||||
menu.AddButton("Save...", () => Screenshot.Capture(Values[0] as GPUTexture));
|
||||
|
||||
@@ -673,6 +673,7 @@ namespace FlaxEditor.Modules
|
||||
pasteAction.Do(out _, out var nodeParents);
|
||||
|
||||
// Select spawned objects (parents only)
|
||||
newSelection.Clear();
|
||||
newSelection.AddRange(nodeParents);
|
||||
var selectAction = new SelectionChangeAction(Selection.ToArray(), newSelection.ToArray(), OnSelectionUndo);
|
||||
selectAction.Do();
|
||||
|
||||
@@ -151,6 +151,8 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
protected virtual Color FooterColor => GroupArchetype.Color;
|
||||
|
||||
private Float2 mouseDownMousePosition;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the size of the node including header, footer, and margins.
|
||||
/// </summary>
|
||||
@@ -1121,7 +1123,7 @@ namespace FlaxEditor.Surface
|
||||
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location))
|
||||
return true;
|
||||
if (button == MouseButton.Right)
|
||||
return true;
|
||||
mouseDownMousePosition = Input.Mouse.Position;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1143,6 +1145,10 @@ namespace FlaxEditor.Surface
|
||||
// Secondary Context Menu
|
||||
if (button == MouseButton.Right)
|
||||
{
|
||||
float distance = Float2.Distance(mouseDownMousePosition, Input.Mouse.Position);
|
||||
if (distance > 2.5f)
|
||||
return true;
|
||||
|
||||
if (!IsSelected)
|
||||
Surface.Select(this);
|
||||
var tmp = PointToParent(ref location);
|
||||
|
||||
@@ -149,13 +149,13 @@ bool GetTextureDataForSampling(Texture* texture, TextureDataResult& data, bool h
|
||||
|
||||
bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches, Texture* heightmap, float heightmapScale, Texture* splatmap1, Texture* splatmap2)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Terrain.GenerateTerrain");
|
||||
CHECK_RETURN(terrain && terrain->GetChunkSize() != 0, true);
|
||||
if (numberOfPatches.X < 1 || numberOfPatches.Y < 1)
|
||||
{
|
||||
LOG(Warning, "Cannot setup terain with no patches.");
|
||||
LOG(Warning, "Cannot setup terrain with no patches.");
|
||||
return false;
|
||||
}
|
||||
PROFILE_CPU_NAMED("Terrain.GenerateTerrain");
|
||||
|
||||
// Wait for assets to be loaded
|
||||
if (heightmap && heightmap->WaitForLoaded())
|
||||
@@ -178,7 +178,9 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches
|
||||
terrain->AddPatches(numberOfPatches);
|
||||
|
||||
// Prepare data
|
||||
const auto heightmapSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1;
|
||||
const int32 heightmapSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1;
|
||||
const float heightmapSizeInv = 1.0f / (float)(heightmapSize - 1);
|
||||
const Float2 uvPerPatch = Float2::One / Float2(numberOfPatches);
|
||||
Array<float> heightmapData;
|
||||
heightmapData.Resize(heightmapSize * heightmapSize);
|
||||
|
||||
@@ -192,19 +194,17 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches
|
||||
const auto sampler = PixelFormatSampler::Get(dataHeightmap.Format);
|
||||
|
||||
// Initialize with sub-range of the input heightmap
|
||||
const Vector2 uvPerPatch = Vector2::One / Vector2(numberOfPatches);
|
||||
const float heightmapSizeInv = 1.0f / (heightmapSize - 1);
|
||||
for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++)
|
||||
{
|
||||
auto patch = terrain->GetPatch(patchIndex);
|
||||
const Vector2 uvStart = Vector2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch;
|
||||
const Float2 uvStart = Float2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch;
|
||||
|
||||
// Sample heightmap pixels with interpolation to get actual heightmap vertices locations
|
||||
for (int32 z = 0; z < heightmapSize; z++)
|
||||
{
|
||||
for (int32 x = 0; x < heightmapSize; x++)
|
||||
{
|
||||
const Vector2 uv = uvStart + Vector2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch;
|
||||
const Float2 uv = uvStart + Float2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch;
|
||||
const Color color = sampler->SampleLinear(dataHeightmap.Mip0DataPtr->Get(), uv, dataHeightmap.Mip0Size, dataHeightmap.RowPitch);
|
||||
heightmapData[z * heightmapSize + x] = color.R * heightmapScale;
|
||||
}
|
||||
@@ -230,37 +230,30 @@ bool TerrainTools::GenerateTerrain(Terrain* terrain, const Int2& numberOfPatches
|
||||
Texture* splatmaps[2] = { splatmap1, splatmap2 };
|
||||
Array<Color32> splatmapData;
|
||||
TextureDataResult data1;
|
||||
const Vector2 uvPerPatch = Vector2::One / Vector2(numberOfPatches);
|
||||
const float heightmapSizeInv = 1.0f / (heightmapSize - 1);
|
||||
for (int32 index = 0; index < ARRAY_COUNT(splatmaps); index++)
|
||||
{
|
||||
const auto splatmap = splatmaps[index];
|
||||
if (!splatmap)
|
||||
continue;
|
||||
|
||||
// Prepare data
|
||||
if (splatmapData.IsEmpty())
|
||||
splatmapData.Resize(heightmapSize * heightmapSize);
|
||||
|
||||
// Get splatmap data
|
||||
if (GetTextureDataForSampling(splatmap, data1))
|
||||
return true;
|
||||
const auto sampler = PixelFormatSampler::Get(data1.Format);
|
||||
|
||||
// Modify heightmap splatmaps with sub-range of the input splatmaps
|
||||
splatmapData.Resize(heightmapSize * heightmapSize);
|
||||
for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++)
|
||||
{
|
||||
auto patch = terrain->GetPatch(patchIndex);
|
||||
|
||||
const Vector2 uvStart = Vector2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch;
|
||||
const Float2 uvStart = Float2((float)patch->GetX(), (float)patch->GetZ()) * uvPerPatch;
|
||||
|
||||
// Sample splatmap pixels with interpolation to get actual splatmap values
|
||||
for (int32 z = 0; z < heightmapSize; z++)
|
||||
{
|
||||
for (int32 x = 0; x < heightmapSize; x++)
|
||||
{
|
||||
const Vector2 uv = uvStart + Vector2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch;
|
||||
|
||||
const Float2 uv = uvStart + Float2(x * heightmapSizeInv, z * heightmapSizeInv) * uvPerPatch;
|
||||
const Color color = sampler->SampleLinear(data1.Mip0DataPtr->Get(), uv, data1.Mip0Size, data1.RowPitch);
|
||||
|
||||
Color32 layers;
|
||||
@@ -374,63 +367,38 @@ Color32* TerrainTools::GetSplatMapData(Terrain* terrain, const Int2& patchCoord,
|
||||
|
||||
bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Terrain.ExportTerrain");
|
||||
CHECK_RETURN(terrain && terrain->GetPatchesCount() != 0, true);
|
||||
const auto firstPatch = terrain->GetPatch(0);
|
||||
|
||||
// Calculate texture size
|
||||
const int32 patchEdgeVertexCount = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1;
|
||||
const int32 patchVertexCount = patchEdgeVertexCount * patchEdgeVertexCount;
|
||||
|
||||
// Find size of heightmap in patches
|
||||
const auto firstPatch = terrain->GetPatch(0);
|
||||
Int2 start(firstPatch->GetX(), firstPatch->GetZ());
|
||||
Int2 end(start);
|
||||
for (int32 i = 0; i < terrain->GetPatchesCount(); i++)
|
||||
for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++)
|
||||
{
|
||||
const int32 x = terrain->GetPatch(i)->GetX();
|
||||
const int32 y = terrain->GetPatch(i)->GetZ();
|
||||
|
||||
if (x < start.X)
|
||||
start.X = x;
|
||||
if (y < start.Y)
|
||||
start.Y = y;
|
||||
if (x > end.X)
|
||||
end.X = x;
|
||||
if (y > end.Y)
|
||||
end.Y = y;
|
||||
const auto patch = terrain->GetPatch(patchIndex);
|
||||
const Int2 pos(patch->GetX(), patch->GetZ());
|
||||
start = Int2::Min(start, pos);
|
||||
end = Int2::Max(end, pos);
|
||||
}
|
||||
const Int2 size = (end + 1) - start;
|
||||
|
||||
// Allocate - with space for non-existent patches
|
||||
// Allocate heightmap for a whole terrain (NumberOfPatches * 4x4 * ChunkSize + 1)
|
||||
const Int2 heightmapSize = size * Terrain::ChunksCountEdge * terrain->GetChunkSize() + 1;
|
||||
Array<float> heightmap;
|
||||
heightmap.Resize(patchVertexCount * size.X * size.Y);
|
||||
|
||||
// Set to any element, where: min < elem < max
|
||||
heightmap.Resize(heightmapSize.X * heightmapSize.Y);
|
||||
heightmap.SetAll(firstPatch->GetHeightmapData()[0]);
|
||||
|
||||
const int32 heightmapWidth = patchEdgeVertexCount * size.X;
|
||||
|
||||
// Fill heightmap with data
|
||||
// Fill heightmap with data from all patches
|
||||
const int32 rowSize = terrain->GetChunkSize() * Terrain::ChunksCountEdge + 1;
|
||||
for (int32 patchIndex = 0; patchIndex < terrain->GetPatchesCount(); patchIndex++)
|
||||
{
|
||||
// Pick a patch
|
||||
const auto patch = terrain->GetPatch(patchIndex);
|
||||
const float* data = patch->GetHeightmapData();
|
||||
|
||||
// Beginning of patch
|
||||
int32 dstIndex = (patch->GetX() - start.X) * patchEdgeVertexCount +
|
||||
(patch->GetZ() - start.Y) * size.Y * patchVertexCount;
|
||||
|
||||
// Iterate over lines in patch
|
||||
for (int32 z = 0; z < patchEdgeVertexCount; z++)
|
||||
{
|
||||
// Iterate over vertices in line
|
||||
for (int32 x = 0; x < patchEdgeVertexCount; x++)
|
||||
{
|
||||
heightmap[dstIndex + x] = data[z * patchEdgeVertexCount + x];
|
||||
}
|
||||
|
||||
dstIndex += heightmapWidth;
|
||||
}
|
||||
const Int2 pos(patch->GetX() - start.X, patch->GetZ() - start.Y);
|
||||
const float* src = patch->GetHeightmapData();
|
||||
float* dst = heightmap.Get() + pos.X * (rowSize - 1) + pos.Y * heightmapSize.X * (rowSize - 1);
|
||||
for (int32 row = 0; row < rowSize; row++)
|
||||
Platform::MemoryCopy(dst + row * heightmapSize.X, src + row * rowSize, rowSize * sizeof(float));
|
||||
}
|
||||
|
||||
// Interpolate to 16-bit int
|
||||
@@ -438,44 +406,42 @@ bool TerrainTools::ExportTerrain(Terrain* terrain, String outputFolder)
|
||||
maxHeight = minHeight = heightmap[0];
|
||||
for (int32 i = 1; i < heightmap.Count(); i++)
|
||||
{
|
||||
float h = heightmap[i];
|
||||
float h = heightmap.Get()[i];
|
||||
if (maxHeight < h)
|
||||
maxHeight = h;
|
||||
else if (minHeight > h)
|
||||
minHeight = h;
|
||||
}
|
||||
|
||||
const float maxValue = 65535.0f;
|
||||
const float alpha = maxValue / (maxHeight - minHeight);
|
||||
const float alpha = MAX_uint16 / (maxHeight - minHeight);
|
||||
|
||||
// Storage for pixel data
|
||||
Array<uint16> byteHeightmap(heightmap.Capacity());
|
||||
|
||||
for (auto& elem : heightmap)
|
||||
Array<uint16> byteHeightmap;
|
||||
byteHeightmap.Resize(heightmap.Count());
|
||||
for (int32 i = 0; i < heightmap.Count(); i++)
|
||||
{
|
||||
byteHeightmap.Add(static_cast<uint16>(alpha * (elem - minHeight)));
|
||||
float height = heightmap.Get()[i];
|
||||
byteHeightmap.Get()[i] = static_cast<uint16>(alpha * (height - minHeight));
|
||||
}
|
||||
|
||||
// Create texture
|
||||
TextureData textureData;
|
||||
textureData.Height = textureData.Width = heightmapWidth;
|
||||
textureData.Width = heightmapSize.X;
|
||||
textureData.Height = heightmapSize.Y;
|
||||
textureData.Depth = 1;
|
||||
textureData.Format = PixelFormat::R16_UNorm;
|
||||
textureData.Items.Resize(1);
|
||||
textureData.Items[0].Mips.Resize(1);
|
||||
|
||||
// Fill mip data
|
||||
TextureMipData* srcMip = textureData.GetData(0, 0);
|
||||
srcMip->Data.Link(byteHeightmap.Get());
|
||||
srcMip->Lines = textureData.Height;
|
||||
srcMip->RowPitch = textureData.Width * 2; // 2 bytes per pixel for format R16
|
||||
srcMip->RowPitch = textureData.Width * sizeof(uint16);
|
||||
srcMip->DepthPitch = srcMip->Lines * srcMip->RowPitch;
|
||||
|
||||
// Find next non-existing file heightmap file
|
||||
FileSystem::NormalizePath(outputFolder);
|
||||
const String baseFileName(TEXT("heightmap"));
|
||||
String outputPath;
|
||||
for (int32 i = 0; i < MAX_int32; i++)
|
||||
for (int32 i = 0; i < 100; i++)
|
||||
{
|
||||
outputPath = outputFolder / baseFileName + StringUtils::ToString(i) + TEXT(".png");
|
||||
if (!FileSystem::FileExists(outputPath))
|
||||
|
||||
@@ -535,7 +535,7 @@ namespace FlaxEditor.Viewport
|
||||
|
||||
// Setup options
|
||||
{
|
||||
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
|
||||
_editor.Options.OptionsChanged += OnEditorOptionsChanged;
|
||||
SetupViewportOptions();
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ namespace FlaxEditor.Viewport
|
||||
|
||||
// Camera Settings Menu
|
||||
var cameraCM = new ContextMenu();
|
||||
_cameraButton = new ViewportWidgetButton(string.Format(MovementSpeedTextFormat, _movementSpeed), Editor.Instance.Icons.Camera64, cameraCM, false, cameraSpeedTextWidth)
|
||||
_cameraButton = new ViewportWidgetButton(string.Format(MovementSpeedTextFormat, _movementSpeed), _editor.Icons.Camera64, cameraCM, false, cameraSpeedTextWidth)
|
||||
{
|
||||
Tag = this,
|
||||
TooltipText = "Camera Settings",
|
||||
@@ -590,7 +590,7 @@ namespace FlaxEditor.Viewport
|
||||
_cameraWidget.Parent = this;
|
||||
|
||||
// Orthographic/Perspective Mode Widget
|
||||
_orthographicModeButton = new ViewportWidgetButton(string.Empty, Editor.Instance.Icons.CamSpeed32, null, true)
|
||||
_orthographicModeButton = new ViewportWidgetButton(string.Empty, _editor.Icons.CamSpeed32, null, true)
|
||||
{
|
||||
Checked = !_isOrtho,
|
||||
TooltipText = "Toggle Orthographic/Perspective Mode",
|
||||
@@ -863,8 +863,8 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
}
|
||||
});
|
||||
viewLayers.AddButton("Reset layers", () => Task.ViewLayersMask = LayersMask.Default).Icon = Editor.Instance.Icons.Rotate32;
|
||||
viewLayers.AddButton("Disable layers", () => Task.ViewLayersMask = new LayersMask(0)).Icon = Editor.Instance.Icons.Rotate32;
|
||||
viewLayers.AddButton("Reset layers", () => Task.ViewLayersMask = LayersMask.Default).Icon = _editor.Icons.Rotate32;
|
||||
viewLayers.AddButton("Disable layers", () => Task.ViewLayersMask = new LayersMask(0));
|
||||
viewLayers.AddSeparator();
|
||||
var layers = LayersAndTagsSettings.GetCurrentLayers();
|
||||
if (layers != null && layers.Length > 0)
|
||||
@@ -904,8 +904,8 @@ namespace FlaxEditor.Viewport
|
||||
{
|
||||
}
|
||||
});
|
||||
viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = Editor.Instance.Icons.Rotate32;
|
||||
viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None).Icon = Editor.Instance.Icons.Rotate32;
|
||||
viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = _editor.Icons.Rotate32;
|
||||
viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None);
|
||||
viewFlags.AddSeparator();
|
||||
for (int i = 0; i < ViewFlagsValues.Length; i++)
|
||||
{
|
||||
@@ -1085,7 +1085,7 @@ namespace FlaxEditor.Viewport
|
||||
/// </summary>
|
||||
private void SetupViewportOptions()
|
||||
{
|
||||
var options = Editor.Instance.Options.Options;
|
||||
var options = _editor.Options.Options;
|
||||
_minMovementSpeed = options.Viewport.MinMovementSpeed;
|
||||
MovementSpeed = options.Viewport.MovementSpeed;
|
||||
_maxMovementSpeed = options.Viewport.MaxMovementSpeed;
|
||||
@@ -1701,7 +1701,7 @@ namespace FlaxEditor.Viewport
|
||||
|
||||
// Check if update mouse
|
||||
var size = Size;
|
||||
var options = Editor.Instance.Options.Options;
|
||||
var options = _editor.Options.Options;
|
||||
if (_isControllingMouse)
|
||||
{
|
||||
var rmbWheel = false;
|
||||
@@ -1926,7 +1926,7 @@ namespace FlaxEditor.Viewport
|
||||
return true;
|
||||
|
||||
// Custom input events
|
||||
return InputActions.Process(Editor.Instance, this, key);
|
||||
return InputActions.Process(_editor, this, key);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -1943,7 +1943,7 @@ namespace FlaxEditor.Viewport
|
||||
base.Draw();
|
||||
|
||||
// Add overlay during debugger breakpoint hang
|
||||
if (Editor.Instance.Simulation.IsDuringBreakpointHang)
|
||||
if (_editor.Simulation.IsDuringBreakpointHang)
|
||||
{
|
||||
var bounds = new Rectangle(Float2.Zero, Size);
|
||||
Render2D.FillRectangle(bounds, new Color(0.0f, 0.0f, 0.0f, 0.2f));
|
||||
@@ -1967,7 +1967,7 @@ namespace FlaxEditor.Viewport
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
Editor.Instance.Options.OptionsChanged -= OnEditorOptionsChanged;
|
||||
_editor.Options.OptionsChanged -= OnEditorOptionsChanged;
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace FlaxEditor.Windows
|
||||
"Jean-Baptiste Perrier",
|
||||
"Chandler Cox",
|
||||
"Ari Vuollet",
|
||||
"Vincent Saarmann",
|
||||
});
|
||||
authors.Sort();
|
||||
var authorsLabel = new Label(4, topParentControl.Bottom + 20, Width - 8, 70)
|
||||
|
||||
@@ -93,6 +93,7 @@ void MultiBlendBucketInit(AnimGraphInstanceData::Bucket& bucket)
|
||||
void BlendPoseBucketInit(AnimGraphInstanceData::Bucket& bucket)
|
||||
{
|
||||
bucket.BlendPose.TransitionPosition = 0.0f;
|
||||
bucket.BlendPose.BlendPoseIndex = -1;
|
||||
bucket.BlendPose.PreviousBlendPoseIndex = -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,8 @@ public:
|
||||
struct BlendPoseBucket
|
||||
{
|
||||
float TransitionPosition;
|
||||
int32 PreviousBlendPoseIndex;
|
||||
int16 BlendPoseIndex;
|
||||
int16 PreviousBlendPoseIndex;
|
||||
};
|
||||
|
||||
struct StateMachineBucket
|
||||
@@ -810,6 +811,7 @@ public:
|
||||
{
|
||||
// Copy the node transformations
|
||||
Platform::MemoryCopy(dstNodes->Nodes.Get(), srcNodes->Nodes.Get(), sizeof(Transform) * _skeletonNodesCount);
|
||||
dstNodes->RootMotion = srcNodes->RootMotion;
|
||||
|
||||
// Copy the animation playback state
|
||||
dstNodes->Position = srcNodes->Position;
|
||||
|
||||
@@ -676,9 +676,12 @@ Variant AnimGraphExecutor::Blend(AnimGraphNode* node, const Value& poseA, const
|
||||
if (!ANIM_GRAPH_IS_VALID_PTR(poseB))
|
||||
nodesB = GetEmptyNodes();
|
||||
|
||||
const Transform* srcA = nodesA->Nodes.Get();
|
||||
const Transform* srcB = nodesB->Nodes.Get();
|
||||
Transform* dst = nodes->Nodes.Get();
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]);
|
||||
Transform::Lerp(srcA[i], srcB[i], alpha, dst[i]);
|
||||
}
|
||||
Transform::Lerp(nodesA->RootMotion, nodesB->RootMotion, alpha, nodes->RootMotion);
|
||||
nodes->Position = Math::Lerp(nodesA->Position, nodesB->Position, alpha);
|
||||
@@ -1263,21 +1266,7 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
{
|
||||
const auto valueA = tryGetValue(node->GetBox(1), Value::Null);
|
||||
const auto valueB = tryGetValue(node->GetBox(2), Value::Null);
|
||||
const auto nodes = node->GetNodes(this);
|
||||
|
||||
auto nodesA = static_cast<AnimGraphImpulse*>(valueA.AsPointer);
|
||||
auto nodesB = static_cast<AnimGraphImpulse*>(valueB.AsPointer);
|
||||
if (!ANIM_GRAPH_IS_VALID_PTR(valueA))
|
||||
nodesA = GetEmptyNodes();
|
||||
if (!ANIM_GRAPH_IS_VALID_PTR(valueB))
|
||||
nodesB = GetEmptyNodes();
|
||||
|
||||
for (int32 i = 0; i < nodes->Nodes.Count(); i++)
|
||||
{
|
||||
Transform::Lerp(nodesA->Nodes[i], nodesB->Nodes[i], alpha, nodes->Nodes[i]);
|
||||
}
|
||||
Transform::Lerp(nodesA->RootMotion, nodesB->RootMotion, alpha, nodes->RootMotion);
|
||||
value = nodes;
|
||||
value = Blend(node, valueA, valueB, alpha, AlphaBlendMode::Linear);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1758,35 +1747,38 @@ void AnimGraphExecutor::ProcessGroupAnimation(Box* boxBase, Node* nodeBase, Valu
|
||||
// [2]: int Pose Count
|
||||
// [3]: AlphaBlendMode Mode
|
||||
|
||||
// Prepare
|
||||
auto& bucket = context.Data->State[node->BucketIndex].BlendPose;
|
||||
const int32 poseIndex = (int32)tryGetValue(node->GetBox(1), node->Values[0]);
|
||||
const int16 poseIndex = (int32)tryGetValue(node->GetBox(1), node->Values[0]);
|
||||
const float blendDuration = (float)tryGetValue(node->GetBox(2), node->Values[1]);
|
||||
const int32 poseCount = Math::Clamp(node->Values[2].AsInt, 0, MaxBlendPoses);
|
||||
const AlphaBlendMode mode = (AlphaBlendMode)node->Values[3].AsInt;
|
||||
|
||||
// Skip if nothing to blend
|
||||
if (poseCount == 0 || poseIndex < 0 || poseIndex >= poseCount)
|
||||
{
|
||||
break;
|
||||
|
||||
// Check if swap transition end points
|
||||
if (bucket.PreviousBlendPoseIndex == poseIndex && bucket.BlendPoseIndex != poseIndex && bucket.TransitionPosition >= ANIM_GRAPH_BLEND_THRESHOLD)
|
||||
{
|
||||
bucket.TransitionPosition = blendDuration - bucket.TransitionPosition;
|
||||
Swap(bucket.BlendPoseIndex, bucket.PreviousBlendPoseIndex);
|
||||
}
|
||||
|
||||
// Check if transition is not active (first update, pose not changing or transition ended)
|
||||
bucket.TransitionPosition += context.DeltaTime;
|
||||
bucket.BlendPoseIndex = poseIndex;
|
||||
if (bucket.PreviousBlendPoseIndex == -1 || bucket.PreviousBlendPoseIndex == poseIndex || bucket.TransitionPosition >= blendDuration || blendDuration <= ANIM_GRAPH_BLEND_THRESHOLD)
|
||||
{
|
||||
bucket.TransitionPosition = 0.0f;
|
||||
bucket.BlendPoseIndex = poseIndex;
|
||||
bucket.PreviousBlendPoseIndex = poseIndex;
|
||||
value = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + poseIndex), Value::Null);
|
||||
value = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.BlendPoseIndex), Value::Null);
|
||||
break;
|
||||
}
|
||||
ASSERT(bucket.PreviousBlendPoseIndex >= 0 && bucket.PreviousBlendPoseIndex < poseCount);
|
||||
|
||||
// Blend two animations
|
||||
{
|
||||
const float alpha = bucket.TransitionPosition / blendDuration;
|
||||
const auto valueA = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.PreviousBlendPoseIndex), Value::Null);
|
||||
const auto valueB = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + poseIndex), Value::Null);
|
||||
const auto valueB = tryGetValue(node->GetBox(FirstBlendPoseBoxIndex + bucket.BlendPoseIndex), Value::Null);
|
||||
value = Blend(node, valueA, valueB, alpha, mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +63,16 @@ void BoundingFrustum::SetMatrix(const Matrix& matrix)
|
||||
|
||||
Plane BoundingFrustum::GetPlane(int32 index) const
|
||||
{
|
||||
if (index > 5)
|
||||
return Plane();
|
||||
return _planes[index];
|
||||
switch (index)
|
||||
{
|
||||
case 0: return _pLeft;
|
||||
case 1: return _pRight;
|
||||
case 2: return _pTop;
|
||||
case 3: return _pBottom;
|
||||
case 4: return _pNear;
|
||||
case 5: return _pFar;
|
||||
default: return Plane();
|
||||
}
|
||||
}
|
||||
|
||||
static Vector3 Get3PlanesInterPoint(const Plane& p1, const Plane& p2, const Plane& p3)
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Returns one of the 6 planes related to this frustum.
|
||||
/// </summary>
|
||||
/// <param name="index">Plane index where 0 fro Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far</param>
|
||||
/// <param name="index">Plane index where 0 for Left, 1 for Right, 2 for Top, 3 for Bottom, 4 for Near, 5 for Far</param>
|
||||
/// <returns>The frustum plane.</returns>
|
||||
public Plane GetPlane(int index)
|
||||
{
|
||||
|
||||
@@ -148,13 +148,13 @@ public:
|
||||
Plane GetPlane(int32 index) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
|
||||
/// Gets the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
|
||||
/// </summary>
|
||||
/// <param name="corners">The corners.</param>
|
||||
void GetCorners(Float3 corners[8]) const;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
|
||||
/// Gets the 8 corners of the frustum: Near1 (near right down corner), Near2 (near right top corner), Near3 (near Left top corner), Near4 (near Left down corner), Far1 (far right down corner), Far2 (far right top corner), Far3 (far left top corner), Far4 (far left down corner).
|
||||
/// </summary>
|
||||
/// <param name="corners">The corners.</param>
|
||||
void GetCorners(Double3 corners[8]) const;
|
||||
|
||||
@@ -265,6 +265,14 @@ public:
|
||||
return Projection.M44 >= 1.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether view Origin has been moved in this frame. Old history buffers/data might be invalid.
|
||||
/// </summary>
|
||||
FORCE_INLINE bool IsOriginTeleport() const
|
||||
{
|
||||
return Origin != PrevOrigin;
|
||||
}
|
||||
|
||||
public:
|
||||
// Ignore deprecation warnings in defaults
|
||||
PRAGMA_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
#endif
|
||||
|
||||
GPU_CB_STRUCT(Data {
|
||||
Matrix WVP;
|
||||
Matrix WorldViewProjection;
|
||||
Matrix InvViewProjection;
|
||||
Float3 ViewOffset;
|
||||
float Padding;
|
||||
ShaderGBufferData GBuffer;
|
||||
@@ -30,8 +31,6 @@ GPU_CB_STRUCT(Data {
|
||||
|
||||
Sky::Sky(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
, _psSky(nullptr)
|
||||
, _psFog(nullptr)
|
||||
{
|
||||
_drawNoCulling = 1;
|
||||
_drawCategory = SceneRendering::PreRender;
|
||||
@@ -51,7 +50,6 @@ Sky::Sky(const SpawnParams& params)
|
||||
Sky::~Sky()
|
||||
{
|
||||
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
||||
SAFE_DELETE_GPU_RESOURCE(_psFog);
|
||||
}
|
||||
|
||||
void Sky::InitConfig(ShaderAtmosphericFogData& config) const
|
||||
@@ -90,7 +88,7 @@ void Sky::Draw(RenderContext& renderContext)
|
||||
if (HasContentLoaded() && EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::Sky))
|
||||
{
|
||||
// Ensure to have pipeline state cache created
|
||||
if (_psSky == nullptr || _psFog == nullptr)
|
||||
if (_psSky == nullptr)
|
||||
{
|
||||
const auto shader = _shader->GetShader();
|
||||
|
||||
@@ -112,21 +110,6 @@ void Sky::Draw(RenderContext& renderContext)
|
||||
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
|
||||
}
|
||||
}
|
||||
if (_psFog == nullptr)
|
||||
{
|
||||
_psFog = GPUDevice::Instance->CreatePipelineState();
|
||||
|
||||
GPUPipelineState::Description psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
||||
psDesc.PS = shader->GetPS("PS_Fog");
|
||||
psDesc.DepthWriteEnable = false;
|
||||
psDesc.DepthClipEnable = false;
|
||||
psDesc.BlendMode = BlendingMode::Additive;
|
||||
|
||||
if (_psFog->Init(psDesc))
|
||||
{
|
||||
LOG(Warning, "Cannot create graphics pipeline state object for '{0}'.", ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register for the sky and fog pass
|
||||
@@ -138,7 +121,6 @@ void Sky::Draw(RenderContext& renderContext)
|
||||
|
||||
void Sky::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
{
|
||||
// Base
|
||||
Actor::Serialize(stream, otherObj);
|
||||
|
||||
SERIALIZE_GET_OTHER_OBJ(Sky);
|
||||
@@ -151,7 +133,6 @@ void Sky::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
|
||||
void Sky::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
// Base
|
||||
Actor::Deserialize(stream, modifier);
|
||||
|
||||
DESERIALIZE_MEMBER(Sun, SunLight);
|
||||
@@ -172,40 +153,7 @@ bool Sky::IntersectsItself(const Ray& ray, Real& distance, Vector3& normal)
|
||||
|
||||
void Sky::DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output)
|
||||
{
|
||||
// Get precomputed cache and bind it to the pipeline
|
||||
AtmosphereCache cache;
|
||||
if (!AtmospherePreCompute::GetCache(&cache))
|
||||
return;
|
||||
PROFILE_GPU_CPU("Sky Fog");
|
||||
context->BindSR(4, cache.Transmittance);
|
||||
context->BindSR(5, cache.Irradiance);
|
||||
context->BindSR(6, cache.Inscatter->ViewVolume());
|
||||
|
||||
// Bind GBuffer inputs
|
||||
context->BindSR(0, renderContext.Buffers->GBuffer0);
|
||||
context->BindSR(1, renderContext.Buffers->GBuffer1);
|
||||
context->BindSR(2, renderContext.Buffers->GBuffer2);
|
||||
context->BindSR(3, renderContext.Buffers->DepthBuffer);
|
||||
|
||||
// Setup constants data
|
||||
Data data;
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
||||
InitConfig(data.Fog);
|
||||
data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
||||
bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
|
||||
if (!useSpecularLight)
|
||||
{
|
||||
data.Fog.AtmosphericFogSunDiscScale = 0;
|
||||
}
|
||||
|
||||
// Bind pipeline
|
||||
auto cb = _shader->GetShader()->GetCB(0);
|
||||
context->UpdateCB(cb, &data);
|
||||
context->BindCB(0, cb);
|
||||
context->SetState(_psFog);
|
||||
context->SetRenderTarget(output);
|
||||
context->DrawFullscreenTriangle();
|
||||
MISSING_CODE("sky fog");
|
||||
}
|
||||
|
||||
bool Sky::IsDynamicSky() const
|
||||
@@ -231,14 +179,14 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
|
||||
// Setup constants data
|
||||
Matrix m;
|
||||
Data data;
|
||||
Matrix::Multiply(world, renderContext.View.Frustum.GetMatrix(), m);
|
||||
Matrix::Transpose(m, data.WVP);
|
||||
Matrix::Multiply(world, renderContext.View.ViewProjection(), m);
|
||||
Matrix::Transpose(m, data.WorldViewProjection);
|
||||
Matrix::Transpose(renderContext.View.IVP, data.InvViewProjection);
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
data.ViewOffset = renderContext.View.Origin + GetPosition();
|
||||
InitConfig(data.Fog);
|
||||
//data.Fog.AtmosphericFogSunPower *= SunLight ? SunLight->Brightness : 1.0f;
|
||||
bool useSpecularLight = EnumHasAnyFlags(renderContext.View.Flags, ViewFlags::SpecularLight);
|
||||
if (!useSpecularLight)
|
||||
if (EnumHasNoneFlags(renderContext.View.Flags, ViewFlags::SpecularLight))
|
||||
{
|
||||
// Hide sun disc if specular light is disabled
|
||||
data.Fog.AtmosphericFogSunDiscScale = 0;
|
||||
@@ -253,11 +201,8 @@ void Sky::ApplySky(GPUContext* context, RenderContext& renderContext, const Matr
|
||||
|
||||
void Sky::EndPlay()
|
||||
{
|
||||
// Cleanup
|
||||
SAFE_DELETE_GPU_RESOURCE(_psSky);
|
||||
SAFE_DELETE_GPU_RESOURCE(_psFog);
|
||||
|
||||
// Base
|
||||
Actor::EndPlay();
|
||||
}
|
||||
|
||||
@@ -268,7 +213,6 @@ void Sky::OnEnable()
|
||||
GetSceneRendering()->AddViewportIcon(this);
|
||||
#endif
|
||||
|
||||
// Base
|
||||
Actor::OnEnable();
|
||||
}
|
||||
|
||||
@@ -279,13 +223,11 @@ void Sky::OnDisable()
|
||||
#endif
|
||||
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
|
||||
|
||||
// Base
|
||||
Actor::OnDisable();
|
||||
}
|
||||
|
||||
void Sky::OnTransformChanged()
|
||||
{
|
||||
// Base
|
||||
Actor::OnTransformChanged();
|
||||
|
||||
_box = BoundingBox(_transform.Translation);
|
||||
|
||||
@@ -20,8 +20,7 @@ class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public
|
||||
DECLARE_SCENE_OBJECT(Sky);
|
||||
private:
|
||||
AssetReference<Shader> _shader;
|
||||
GPUPipelineState* _psSky;
|
||||
GPUPipelineState* _psFog;
|
||||
GPUPipelineState* _psSky = nullptr;
|
||||
int32 _sceneRenderingKey = -1;
|
||||
|
||||
public:
|
||||
@@ -57,7 +56,6 @@ private:
|
||||
void OnShaderReloading(Asset* obj)
|
||||
{
|
||||
_psSky = nullptr;
|
||||
_psFog = nullptr;
|
||||
}
|
||||
#endif
|
||||
void InitConfig(ShaderAtmosphericFogData& config) const;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Assets/Model.h"
|
||||
#include "Engine/Level/Actors/Decal.h"
|
||||
#include "Engine/Level/Actors/Sky.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
|
||||
GPU_CB_STRUCT(GBufferPassData {
|
||||
@@ -416,8 +417,17 @@ void GBufferPass::DrawSky(RenderContext& renderContext, GPUContext* context)
|
||||
|
||||
// Calculate sphere model transform to cover far plane
|
||||
Matrix m1, m2;
|
||||
Matrix::Scaling(renderContext.View.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
|
||||
Matrix::CreateWorld(renderContext.View.Position, Float3::Up, Float3::Backward, m2); // Rotate sphere model
|
||||
float size = renderContext.View.Far;
|
||||
Float3 origin = renderContext.View.Position;
|
||||
if (dynamic_cast<Sky*>(renderContext.List->Sky)) // TODO: refactor sky rendering (eg. let sky draw with custom projection)
|
||||
{
|
||||
BoundingSphere frustumBounds;
|
||||
renderContext.View.CullingFrustum.GetSphere(frustumBounds);
|
||||
origin = frustumBounds.Center;
|
||||
size = frustumBounds.Radius;
|
||||
}
|
||||
Matrix::Scaling(size / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
|
||||
Matrix::CreateWorld(origin, Float3::Up, Float3::Backward, m2); // Rotate sphere model
|
||||
m1 *= m2;
|
||||
|
||||
// Draw sky
|
||||
|
||||
@@ -357,8 +357,6 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode);
|
||||
{
|
||||
PROFILE_CPU_NAMED("Setup");
|
||||
if (renderContext.View.Origin != renderContext.View.PrevOrigin)
|
||||
renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change
|
||||
const int32 screenWidth = renderContext.Buffers->GetWidth();
|
||||
const int32 screenHeight = renderContext.Buffers->GetHeight();
|
||||
setup.UpscaleLocation = renderContext.Task->UpscaleLocation;
|
||||
|
||||
@@ -167,7 +167,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
|
||||
(float)_cache.GridSizeZ);
|
||||
auto& fogData = renderContext.Buffers->VolumetricFogData;
|
||||
fogData.MaxDistance = options.Distance;
|
||||
if (renderContext.Task->IsCameraCut)
|
||||
if (renderContext.Task->IsCameraCut || renderContext.View.IsOriginTeleport())
|
||||
_cache.HistoryWeight = 0.0f;
|
||||
|
||||
// Init data (partial, without directional light or sky light data);
|
||||
@@ -301,7 +301,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
|
||||
PROFILE_GPU_CPU("Volumetric Fog");
|
||||
|
||||
// TODO: test exponential depth distribution (should give better quality near the camera)
|
||||
// TODO: use tiled light culling and render unshadowed lights in single pass
|
||||
// TODO: use tiled light culling and render shadowed/unshadowed lights in single pass
|
||||
|
||||
// Try to get shadows atlas
|
||||
GPUTexture* shadowMap;
|
||||
|
||||
@@ -859,9 +859,7 @@ void Terrain::OnEnable()
|
||||
{
|
||||
auto patch = _patches[i];
|
||||
if (patch->_physicsActor)
|
||||
{
|
||||
PhysicsBackend::AddSceneActor(scene, patch->_physicsActor);
|
||||
}
|
||||
}
|
||||
|
||||
// Base
|
||||
@@ -880,9 +878,7 @@ void Terrain::OnDisable()
|
||||
{
|
||||
auto patch = _patches[i];
|
||||
if (patch->_physicsActor)
|
||||
{
|
||||
PhysicsBackend::RemoveSceneActor(scene, patch->_physicsActor);
|
||||
}
|
||||
}
|
||||
|
||||
// Base
|
||||
|
||||
@@ -2230,7 +2230,8 @@ void TerrainPatch::DestroyCollision()
|
||||
|
||||
void* scene = _terrain->GetPhysicsScene()->GetPhysicsScene();
|
||||
PhysicsBackend::RemoveCollider(_terrain);
|
||||
PhysicsBackend::RemoveSceneActor(scene, _physicsActor);
|
||||
if (_terrain->IsDuringPlay() && _terrain->IsActiveInHierarchy())
|
||||
PhysicsBackend::RemoveSceneActor(scene, _physicsActor);
|
||||
PhysicsBackend::DestroyActor(_physicsActor);
|
||||
PhysicsBackend::DestroyShape(_physicsShape);
|
||||
PhysicsBackend::DestroyObject(_physicsHeightField);
|
||||
|
||||
@@ -181,8 +181,8 @@ namespace FlaxEngine.GUI
|
||||
ImageColor = style.BorderSelected * 1.2f;
|
||||
BorderColor = style.BorderNormal;
|
||||
BorderColorHighlighted = style.BorderSelected;
|
||||
CheckedImage = new SpriteBrush(style.CheckBoxTick);
|
||||
IntermediateImage = new SpriteBrush(style.CheckBoxIntermediate);
|
||||
CheckedImage = style.CheckBoxTick.IsValid ? new SpriteBrush(style.CheckBoxTick) : new SolidColorBrush(style.Foreground);
|
||||
IntermediateImage = style.CheckBoxIntermediate.IsValid ? new SpriteBrush(style.CheckBoxIntermediate) : new SolidColorBrush(style.ForegroundGrey);
|
||||
|
||||
CacheBox();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "Engine/Content/AssetsContainer.h"
|
||||
#include "Engine/Animations/Curve.h"
|
||||
|
||||
#define SHADER_GRAPH_MAX_CALL_STACK 100
|
||||
#define SHADER_GRAPH_MAX_CALL_STACK 50
|
||||
|
||||
enum class MaterialSceneTextures;
|
||||
template<class BoxType>
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
#include "./Flax/AtmosphereFog.hlsl"
|
||||
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WVP;
|
||||
float4x4 WorldViewProjection;
|
||||
float4x4 InvViewProjection;
|
||||
float3 ViewOffset;
|
||||
float Padding;
|
||||
GBufferData GBuffer;
|
||||
@@ -18,7 +19,7 @@ DECLARE_GBUFFERDATA_ACCESS(GBuffer)
|
||||
|
||||
struct MaterialInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float4 Position : SV_Position;
|
||||
float4 ScreenPos : TEXCOORD0;
|
||||
};
|
||||
|
||||
@@ -30,12 +31,9 @@ MaterialInput VS(ModelInput_PosOnly input)
|
||||
MaterialInput output;
|
||||
|
||||
// Compute vertex position
|
||||
output.Position = mul(float4(input.Position.xyz, 1), WVP);
|
||||
output.Position = mul(float4(input.Position.xyz, 1), WorldViewProjection);
|
||||
output.ScreenPos = output.Position;
|
||||
|
||||
// Place pixels on the far plane
|
||||
output.Position = output.Position.xyzz;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -45,15 +43,15 @@ GBufferOutput PS_Sky(MaterialInput input)
|
||||
{
|
||||
GBufferOutput output;
|
||||
|
||||
// Obtain UVs corresponding to the current pixel
|
||||
float2 uv = (input.ScreenPos.xy / input.ScreenPos.w) * float2(0.5, -0.5) + float2(0.5, 0.5);
|
||||
// Calculate view vector (unproject at the far plane)
|
||||
GBufferData gBufferData = GetGBufferData();
|
||||
float4 clipPos = float4(input.ScreenPos.xy / input.ScreenPos.w, 1.0, 1.0);
|
||||
clipPos = mul(clipPos, InvViewProjection);
|
||||
float3 worldPos = clipPos.xyz / clipPos.w;
|
||||
float3 viewVector = normalize(worldPos - gBufferData.ViewPos);
|
||||
|
||||
// Sample atmosphere color
|
||||
GBufferData gBufferData = GetGBufferData();
|
||||
float3 vsPos = GetViewPos(gBufferData, uv, LinearZ2DeviceDepth(gBufferData, 1));
|
||||
float3 wsPos = mul(float4(vsPos, 1), gBufferData.InvViewMatrix).xyz;
|
||||
float3 viewVector = wsPos - gBufferData.ViewPos;
|
||||
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, wsPos + ViewOffset, gBufferData.ViewPos + ViewOffset);
|
||||
float4 color = GetAtmosphericFog(AtmosphericFog, gBufferData.ViewFar, gBufferData.ViewPos + ViewOffset, viewVector, gBufferData.ViewFar, float3(0, 0, 0));
|
||||
|
||||
// Pack GBuffer
|
||||
output.Light = color;
|
||||
@@ -64,36 +62,3 @@ GBufferOutput PS_Sky(MaterialInput input)
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Fog(Quad_VS2PS input) : SV_Target0
|
||||
{
|
||||
float4 result;
|
||||
/*
|
||||
// Sample GBuffer
|
||||
GBufferSample gBuffer = SampleGBuffer(GBuffer, input.TexCoord);
|
||||
|
||||
// TODO: set valid scene color for better inscatter reflectance
|
||||
//float3 sceneColor = gBuffer.Color * AtmosphericFogDensityOffset;
|
||||
float3 sceneColor = float3(0, 0, 0);
|
||||
|
||||
// Sample atmosphere color
|
||||
float3 viewVector = gBuffer.WorldPos - GBuffer.ViewPos;
|
||||
float SceneDepth = length(ViewVector);
|
||||
result = GetAtmosphericFog(AtmosphericFog, GBuffer.ViewFar, GBuffer.ViewPos, viewVector, SceneDepth, sceneColor);
|
||||
|
||||
//result.rgb = normalize(ViewVector);
|
||||
//result.rgb = ViewVector;
|
||||
//result.rgb = SceneDepth.xxx / GBuffer.ViewFar * 0.5f;
|
||||
|
||||
//result = float4(input.TexCoord, 0, 1);
|
||||
//result = AtmosphereTransmittanceTexture.Sample(SamplerLinearClamp, input.TexCoord);
|
||||
//result = float4(AtmosphereIrradianceTexture.Sample(SamplerLinearClamp, input.TexCoord).rgb*5.0, 1.0);
|
||||
//result = AtmosphereInscatterTexture.Sample(SamplerLinearClamp, float3(input.TexCoord.xy, (AtmosphericFogSunDirection.x+1.0)/2.0));
|
||||
*/
|
||||
|
||||
// TODO: finish fog
|
||||
result = float4(1, 0, 0, 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user