Merge branch 'grid-update' of https://github.com/Swiggies/FlaxEngine into Swiggies-grid-update
#2663
This commit is contained in:
BIN
Content/Shaders/Editor/Grid.flax
(Stored with Git LFS)
Normal file
BIN
Content/Shaders/Editor/Grid.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using FlaxEngine;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FlaxEditor.Gizmo
|
||||
{
|
||||
@@ -15,91 +16,119 @@ namespace FlaxEditor.Gizmo
|
||||
[HideInEditor]
|
||||
private sealed class Renderer : PostProcessEffect
|
||||
{
|
||||
private IntPtr _debugDrawContext;
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct Data
|
||||
{
|
||||
public Matrix WorldMatrix;
|
||||
public Matrix ViewProjectionMatrix;
|
||||
public Float4 GridColor;
|
||||
public Float3 ViewPos;
|
||||
public float Far;
|
||||
public Float3 Padding;
|
||||
public float GridSize;
|
||||
}
|
||||
|
||||
private static readonly uint[] _triangles =
|
||||
{
|
||||
0, 2, 1, // Face front
|
||||
1, 3, 0,
|
||||
};
|
||||
|
||||
private GPUBuffer[] _vbs = new GPUBuffer[1];
|
||||
private GPUBuffer _vertexBuffer;
|
||||
private GPUBuffer _indexBuffer;
|
||||
private GPUPipelineState _psGrid;
|
||||
private Shader _shader;
|
||||
|
||||
public Renderer()
|
||||
{
|
||||
Order = -100;
|
||||
UseSingleTarget = true;
|
||||
Location = PostProcessEffectLocation.BeforeForwardPass;
|
||||
Location = PostProcessEffectLocation.Default;
|
||||
_shader = FlaxEngine.Content.LoadAsyncInternal<Shader>("Shaders/Editor/Grid");
|
||||
}
|
||||
|
||||
~Renderer()
|
||||
{
|
||||
if (_debugDrawContext != IntPtr.Zero)
|
||||
{
|
||||
DebugDraw.FreeContext(_debugDrawContext);
|
||||
_debugDrawContext = IntPtr.Zero;
|
||||
}
|
||||
Destroy(ref _psGrid);
|
||||
Destroy(ref _vertexBuffer);
|
||||
Destroy(ref _indexBuffer);
|
||||
_shader = null;
|
||||
}
|
||||
|
||||
public override void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
|
||||
public override unsafe void Render(GPUContext context, ref RenderContext renderContext, GPUTexture input, GPUTexture output)
|
||||
{
|
||||
if (_shader == null)
|
||||
return;
|
||||
Profiler.BeginEventGPU("Editor Grid");
|
||||
|
||||
if (_debugDrawContext == IntPtr.Zero)
|
||||
_debugDrawContext = DebugDraw.AllocateContext();
|
||||
DebugDraw.SetContext(_debugDrawContext);
|
||||
DebugDraw.UpdateContext(_debugDrawContext, 1.0f / Mathf.Max(Engine.FramesPerSecond, 1));
|
||||
|
||||
var viewPos = (Vector3)renderContext.View.Position;
|
||||
var plane = new Plane(Vector3.Zero, Vector3.UnitY);
|
||||
var dst = CollisionsHelper.DistancePlanePoint(ref plane, ref viewPos);
|
||||
|
||||
var options = Editor.Instance.Options.Options;
|
||||
float space = options.Viewport.ViewportGridScale, size;
|
||||
if (dst <= 500.0f)
|
||||
Vector3 camPos = renderContext.View.WorldPosition;
|
||||
float gridSize = renderContext.View.Far + 20000;
|
||||
|
||||
// Lazy-init resources
|
||||
if (_vertexBuffer == null)
|
||||
{
|
||||
size = 8000;
|
||||
_vertexBuffer = new GPUBuffer();
|
||||
var desc = GPUBufferDescription.Vertex(sizeof(Float3), 4);
|
||||
_vertexBuffer.Init(ref desc);
|
||||
}
|
||||
else if (dst <= 2000.0f)
|
||||
if (_indexBuffer == null)
|
||||
{
|
||||
space *= 2;
|
||||
size = 8000;
|
||||
_indexBuffer = new GPUBuffer();
|
||||
fixed (uint* ptr = _triangles)
|
||||
{
|
||||
var desc = GPUBufferDescription.Index(sizeof(uint), _triangles.Length, new IntPtr(ptr));
|
||||
_indexBuffer.Init(ref desc);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (_psGrid == null)
|
||||
{
|
||||
space *= 20;
|
||||
size = 100000;
|
||||
_psGrid = new GPUPipelineState();
|
||||
var desc = GPUPipelineState.Description.Default;
|
||||
desc.BlendMode = BlendingMode.AlphaBlend;
|
||||
desc.CullMode = CullMode.TwoSided;
|
||||
desc.VS = _shader.GPU.GetVS("VS_Grid");
|
||||
desc.PS = _shader.GPU.GetPS("PS_Grid");
|
||||
_psGrid.Init(ref desc);
|
||||
}
|
||||
|
||||
float bigLineIntensity = 0.8f;
|
||||
Color bigColor = Color.Gray * bigLineIntensity;
|
||||
Color color = bigColor * 0.8f;
|
||||
int count = (int)(size / space);
|
||||
int midLine = count / 2;
|
||||
int bigLinesMod = count / 8;
|
||||
|
||||
Vector3 start = new Vector3(0, 0, size * -0.5f);
|
||||
Vector3 end = new Vector3(0, 0, size * 0.5f);
|
||||
|
||||
for (int i = 0; i <= count; i++)
|
||||
// Update vertices of the plane
|
||||
// TODO: perf this operation in a Vertex Shader
|
||||
var vertices = new Float3[]
|
||||
{
|
||||
start.X = end.X = i * space + start.Z;
|
||||
Color lineColor = color;
|
||||
if (i == midLine)
|
||||
lineColor = Color.Blue * bigLineIntensity;
|
||||
else if (i % bigLinesMod == 0)
|
||||
lineColor = bigColor;
|
||||
DebugDraw.DrawLine(start, end, lineColor);
|
||||
new Float3(-gridSize + camPos.X, 0, -gridSize + camPos.Z),
|
||||
new Float3(gridSize + camPos.X, 0, gridSize + camPos.Z),
|
||||
new Float3(-gridSize + camPos.X, 0, gridSize + camPos.Z),
|
||||
new Float3(gridSize + camPos.X, 0, -gridSize + camPos.Z),
|
||||
};
|
||||
fixed (Float3* ptr = vertices)
|
||||
{
|
||||
context.UpdateBuffer(_vertexBuffer, new IntPtr(ptr), (uint)(sizeof(Float3) * vertices.Length));
|
||||
}
|
||||
|
||||
start = new Vector3(size * -0.5f, 0, 0);
|
||||
end = new Vector3(size * 0.5f, 0, 0);
|
||||
|
||||
for (int i = 0; i <= count; i++)
|
||||
// Update constant buffer data
|
||||
var cb = _shader.GPU.GetCB(0);
|
||||
if (cb != IntPtr.Zero)
|
||||
{
|
||||
start.Z = end.Z = i * space + start.X;
|
||||
Color lineColor = color;
|
||||
if (i == midLine)
|
||||
lineColor = Color.Red * bigLineIntensity;
|
||||
else if (i % bigLinesMod == 0)
|
||||
lineColor = bigColor;
|
||||
DebugDraw.DrawLine(start, end, lineColor);
|
||||
var data = new Data();
|
||||
Matrix.Multiply(ref renderContext.View.View, ref renderContext.View.Projection, out var viewProjection);
|
||||
data.WorldMatrix = Matrix.Identity;
|
||||
Matrix.Transpose(ref viewProjection, out data.ViewProjectionMatrix);
|
||||
data.ViewPos = renderContext.View.WorldPosition;
|
||||
data.GridColor = options.Viewport.ViewportGridColor;
|
||||
data.Far = renderContext.View.Far;
|
||||
data.GridSize = options.Viewport.ViewportGridViewDistance;
|
||||
context.UpdateCB(cb, new IntPtr(&data));
|
||||
}
|
||||
|
||||
DebugDraw.Draw(ref renderContext, input.View(), null, true);
|
||||
DebugDraw.SetContext(IntPtr.Zero);
|
||||
// Draw geometry using custom Pixel Shader and Vertex Shader
|
||||
context.BindCB(0, cb);
|
||||
context.BindIB(_indexBuffer);
|
||||
_vbs[0] = _vertexBuffer;
|
||||
context.BindVB(_vbs);
|
||||
context.SetState(_psGrid);
|
||||
context.SetRenderTarget(renderContext.Buffers.DepthBuffer.View(), input.View());
|
||||
context.DrawIndexed((uint)_triangles.Length);
|
||||
|
||||
Profiler.EndEventGPU();
|
||||
}
|
||||
|
||||
@@ -129,5 +129,19 @@ namespace FlaxEditor.Options
|
||||
[DefaultValue(50.0f), Limit(25.0f, 500.0f, 5.0f)]
|
||||
[EditorDisplay("Defaults"), EditorOrder(220), Tooltip("The default editor viewport grid scale.")]
|
||||
public float ViewportGridScale { get; set; } = 50.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the view distance you can see the grid.
|
||||
/// </summary>
|
||||
[DefaultValue(2500.0f)]
|
||||
[EditorDisplay("Grid"), EditorOrder(300), Tooltip("The maximum distance you will be able to see the grid.")]
|
||||
public float ViewportGridViewDistance { get; set; } = 2500.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the grid color.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.5,0.5,0.5,1.0")]
|
||||
[EditorDisplay("Grid"), EditorOrder(310), Tooltip("The color for the viewport grid.")]
|
||||
public Color ViewportGridColor { get; set; } = new Color(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
151
Source/Shaders/Editor/Grid.shader
Normal file
151
Source/Shaders/Editor/Grid.shader
Normal file
@@ -0,0 +1,151 @@
|
||||
// Implementation based on:
|
||||
// "The Best Darn Grid Shader (Yet)", Medium, Oct 2023
|
||||
// Ben Golus
|
||||
// https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#3e73
|
||||
|
||||
#define USE_FORWARD true;
|
||||
|
||||
#include "./Flax/Common.hlsl"
|
||||
|
||||
META_CB_BEGIN(0, Data)
|
||||
float4x4 WorldMatrix;
|
||||
float4x4 ViewProjectionMatrix;
|
||||
float4 GridColor;
|
||||
float3 ViewPos;
|
||||
float Far;
|
||||
float3 Padding;
|
||||
float GridSize;
|
||||
META_CB_END
|
||||
|
||||
// Geometry data passed to the vertex shader
|
||||
struct ModelInput
|
||||
{
|
||||
float3 Position : POSITION;
|
||||
};
|
||||
|
||||
// Interpolants passed from the vertex shader
|
||||
struct VertexOutput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
float3 WorldPosition : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Interpolants passed to the pixel shader
|
||||
struct PixelInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
noperspective float2 TexCoord : TEXCOORD0;
|
||||
float3 WorldPosition : TEXCOORD1;
|
||||
};
|
||||
|
||||
// Vertex shader function for grid rendering
|
||||
META_VS(true, FEATURE_LEVEL_ES2)
|
||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||
META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, ALIGN, PER_VERTEX, 0, true)
|
||||
VertexOutput VS_Grid(ModelInput input)
|
||||
{
|
||||
VertexOutput output;
|
||||
output.WorldPosition = mul(float4(input.Position.xyz, 1), WorldMatrix).xyz;
|
||||
output.Position = mul(float4(input.Position.xyz, 1), ViewProjectionMatrix);
|
||||
return output;
|
||||
}
|
||||
|
||||
float invLerp(float from, float to, float value)
|
||||
{
|
||||
return (value - from) / (to - from);
|
||||
}
|
||||
|
||||
float remap(float origFrom, float origTo, float targetFrom, float targetTo, float value)
|
||||
{
|
||||
float rel = invLerp(origFrom, origTo, value);
|
||||
return lerp(targetFrom, targetTo, rel);
|
||||
}
|
||||
|
||||
float ddLength(float a)
|
||||
{
|
||||
return length(float2(ddx(a), ddy(a)));
|
||||
}
|
||||
|
||||
float GetLine(float pos, float scale, float thickness)
|
||||
{
|
||||
float lineWidth = thickness;
|
||||
float coord = (pos * 0.01) * scale;
|
||||
|
||||
float2 uvDDXY = float2(ddx(coord), ddy(coord));
|
||||
|
||||
float deriv = float(length(uvDDXY.xy));
|
||||
float drawWidth = clamp(lineWidth, deriv, 0.5);
|
||||
float lineAA = deriv * 1.5;
|
||||
float gridUV = abs(coord);
|
||||
float grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
|
||||
grid2 *= saturate(lineWidth / drawWidth);
|
||||
grid2 = lerp(grid2, lineWidth, saturate(deriv * 2.0 - 1.0));
|
||||
|
||||
float grid = lerp(grid2, 1.0, grid2);
|
||||
return grid;
|
||||
}
|
||||
|
||||
float GetGrid(float3 pos, float scale, float thickness)
|
||||
{
|
||||
float lineWidth = thickness;
|
||||
float2 coord = (pos.xz * 0.01) * scale;
|
||||
|
||||
float4 uvDDXY = float4(ddx(coord), ddy(coord));
|
||||
|
||||
float2 deriv = float2(length(uvDDXY.xz), length(uvDDXY.yw));
|
||||
float2 drawWidth = clamp(lineWidth, deriv, 0.5);
|
||||
float2 lineAA = deriv * 1.5;
|
||||
float2 gridUV = 1.0 - abs(frac(coord) * 2.0 - 1.0);
|
||||
float2 grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
|
||||
grid2 *= saturate(lineWidth / drawWidth);
|
||||
grid2 = lerp(grid2, lineWidth, saturate(deriv * 2.0 - 1.0));
|
||||
|
||||
float grid = lerp(grid2.x, 1.0, grid2.y);
|
||||
return grid;
|
||||
}
|
||||
|
||||
float4 GetColor(float3 pos, float scale)
|
||||
{
|
||||
float dist = 1 - saturate(distance(float3(ViewPos.x, 0, ViewPos.z), pos) / GridSize);
|
||||
|
||||
// Line width
|
||||
float g1LW = 0.01;
|
||||
// Major line Z
|
||||
float l1 = GetLine(pos.x, 1, g1LW * 2);
|
||||
// Major line X
|
||||
float l2 = GetLine(pos.z, 1, g1LW);
|
||||
|
||||
// Main grid
|
||||
float g1 = GetGrid(pos, 1, g1LW * 0.8);
|
||||
float g2 = GetGrid(pos, 2, g1LW * 0.4);
|
||||
float g3 = GetGrid(pos, 0.1, g1LW * 2);
|
||||
|
||||
float camFadeLarge = clamp(invLerp(2500, 4000, abs(ViewPos.y)),0, g3);
|
||||
g3 *= camFadeLarge;
|
||||
|
||||
float g4 = GetGrid(pos, 10, g1LW);
|
||||
float camFadeTiny = clamp(invLerp(150, 100, abs(ViewPos.y)), 0, g4);
|
||||
g4 *= camFadeTiny;
|
||||
|
||||
float grid = 0;
|
||||
grid = max(l1, l2);
|
||||
grid = max(grid, g1);
|
||||
grid = max(grid, g2);
|
||||
grid = max(grid, g3);
|
||||
grid = max(grid, g4);
|
||||
|
||||
float4 color = grid * GridColor;
|
||||
color = lerp(color, float4(1,0,0,1), l2);
|
||||
color = lerp(color, float4(0,0,1,1), l1);
|
||||
color *= dist;
|
||||
return color;
|
||||
}
|
||||
|
||||
// Pixel shader function for grid rendering
|
||||
META_PS(true, FEATURE_LEVEL_ES2)
|
||||
float4 PS_Grid(PixelInput input) : SV_Target
|
||||
{
|
||||
float4 color = GetColor(input.WorldPosition, 1);
|
||||
return color;
|
||||
}
|
||||
Reference in New Issue
Block a user