Support materials in 2D Quad Renderer!

- Lost Circle rendering along the way
- Cleaned up 2D shaders
This commit is contained in:
Simon Lübeß
2025-02-11 14:02:16 +01:00
parent 76087d6ba4
commit 06b981e88a
9 changed files with 223 additions and 188 deletions
+69 -60
View File
@@ -113,14 +113,14 @@ namespace GlitchyEngine.Renderer
struct QueueLine: this(float4 Start, float4 End, ColorRGBA Color, float Depth, uint32 entityId = uint32.MaxValue) { }
struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, float4 uvTransform, uint32 entityId = uint32.MaxValue) { }
struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, Material Material, float Depth, float4 uvTransform, uint32 entityId = uint32.MaxValue) { }
struct QueueCircle : QueueQuad
{
public float InnerRadius;
public this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, float4 uvTransform, float innerRadius, uint32 entityId = uint32.MaxValue)
: base(Transform, Color, Texture, Depth, uvTransform, entityId)
public this(Matrix Transform, ColorRGBA Color, Texture Texture, Material material, float Depth, float4 uvTransform, float innerRadius, uint32 entityId = uint32.MaxValue)
: base(Transform, Color, Texture, material, Depth, uvTransform, entityId)
{
InnerRadius = innerRadius;
}
@@ -131,6 +131,8 @@ namespace GlitchyEngine.Renderer
private static bool s_sceneRunning;
#endif
private static Matrix sceneViewProjection;
private static AssetHandle<Effect> s_quadBatchEffect;
private static Material s_quadBatchMaterial ~ _?.ReleaseRef();
private static AssetHandle<Effect> s_circleBatchEffect;
@@ -524,12 +526,12 @@ namespace GlitchyEngine.Renderer
s_currentLineEffect = s_lineBatchEffect;
Matrix viewProjection = camera.Projection * Matrix.Invert(transform);
sceneViewProjection = camera.Projection * Matrix.Invert(transform);
s_quadBatchMaterial.SetVariable("ViewProjection", viewProjection);
s_quadBatchMaterial.SetVariable("ViewProjection", sceneViewProjection);
//s_currentQuadEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_currentCircleEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_currentLineEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_currentCircleEffect.Get()?.Variables["ViewProjection"].SetData(sceneViewProjection);
s_currentLineEffect.Get()?.Variables["ViewProjection"].SetData(sceneViewProjection);
s_drawOrder = drawOrder;
@@ -566,12 +568,12 @@ namespace GlitchyEngine.Renderer
s_currentLineEffect = s_lineBatchEffect;
Matrix viewProjection = camera.Projection * camera.View;
sceneViewProjection = camera.Projection * camera.View;
//s_currentQuadEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_quadBatchMaterial.SetVariable("ViewProjection", viewProjection);
s_currentCircleEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_currentLineEffect.Get()?.Variables["ViewProjection"].SetData(viewProjection);
s_quadBatchMaterial.SetVariable("ViewProjection", sceneViewProjection);
s_currentCircleEffect.Get()?.Variables["ViewProjection"].SetData(sceneViewProjection);
s_currentLineEffect.Get()?.Variables["ViewProjection"].SetData(sceneViewProjection);
s_drawOrder = drawOrder;
@@ -606,17 +608,17 @@ namespace GlitchyEngine.Renderer
/// Adds a quad instance to the instance queue.
[Inline]
private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture texture, float depth, float4 uvTransform, uint32 id = uint32.MaxValue)
private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture texture, Material material, float depth, float4 uvTransform, uint32 id = uint32.MaxValue)
{
s_QuadinstanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform, id));
s_QuadinstanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, material, depth, uvTransform, id));
s_statistics.QuadCount++;
}
/// Adds a circle instance to the instance queue.
[Inline]
private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, float4 uvTransform, float innerRadius, uint32 id = uint32.MaxValue)
private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, Material material, float depth, float4 uvTransform, float innerRadius, uint32 id = uint32.MaxValue)
{
s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius, id));
s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, material, depth, uvTransform, innerRadius, id));
s_statistics.CircleCount++;
}
@@ -628,7 +630,7 @@ namespace GlitchyEngine.Renderer
s_statistics.LineCount++;
}
private static void FlushQuadInstances(Texture texture)
private static void FlushQuadInstances(Material material, Texture texture)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -639,11 +641,11 @@ namespace GlitchyEngine.Renderer
//s_currentQuadEffect.ApplyChanges();
//s_currentQuadEffect.Bind();
s_quadBatchMaterial.Bind();
material.Bind();
using (TextureViewBinding tvb = texture.GetViewBinding())
{
if (s_quadBatchMaterial.Effect.Textures.TryGetValue("Texture", let textureEntry))
if (material.Effect.Textures.TryGetValue("Texture", let textureEntry))
{
if (textureEntry.PsSlot != null)
{
@@ -721,7 +723,14 @@ namespace GlitchyEngine.Renderer
// Circle comparison
private static int TextureComparison(QueueCircle lhs, QueueCircle rhs)
{
return (int)Internal.UnsafeCastToPtr(lhs.Texture) - (int)Internal.UnsafeCastToPtr(rhs.Texture);
// When we sort by texture, we can choose the most optimal order.
// So we sort by material first, so we don't have to change too much state all the time.
int materialCmp = (int)Internal.UnsafeCastToPtr(lhs.Texture) <=> (int)Internal.UnsafeCastToPtr(rhs.Texture);
if (materialCmp != 0)
return materialCmp;
else
return (int)Internal.UnsafeCastToPtr(lhs.Texture) - (int)Internal.UnsafeCastToPtr(rhs.Texture);
}
private static int BackToFrontComparison(QueueCircle lhs, QueueCircle rhs)
{
@@ -799,13 +808,11 @@ namespace GlitchyEngine.Renderer
// TODO: per object blendstate
RenderCommand.SetBlendState(s_transparentBlendState);
let quadMaterial = s_quadBatchMaterial;//s_currentQuadEffect.Get();
if (quadMaterial == null)
return;
Texture texture = s_QuadinstanceQueue[0].Texture;
//quadMaterial.SetTexture("Texture", .Invalid);
Material material = s_QuadinstanceQueue[0].Material;
// TODO: Actually use an engine buffer?
material.SetVariable("ViewProjection", sceneViewProjection);
s_setQuadInstances = 0;
@@ -814,23 +821,23 @@ namespace GlitchyEngine.Renderer
var quad = ref s_QuadinstanceQueue[i];
// flush every time the texture changes
if(quad.Texture != texture)
if(quad.Texture != texture || quad.Material != material)
{
FlushQuadInstances(texture);
FlushQuadInstances(material, texture);
material = quad.Material;
texture = quad.Texture;
//quadMaterial.SetTexture("Texture", .Invalid);
}
s_rawQuadInstances[s_setQuadInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId);
if(s_setQuadInstances == s_rawQuadInstances.Count)
{
FlushQuadInstances(texture);
FlushQuadInstances(material, texture);
}
}
FlushQuadInstances(texture);
FlushQuadInstances(material, texture);
s_QuadinstanceQueue.Clear();
}
@@ -1019,28 +1026,28 @@ namespace GlitchyEngine.Renderer
public static void DrawQuad(float2 position, float2 size, float rotation, ColorRGBA color)
{
DrawQuad(float3(position, 0.0f), size, rotation, s_whiteTexture, color);
DrawQuad(float3(position, 0.0f), size, rotation, s_whiteTexture, s_quadBatchMaterial, color);
}
/// Like DrawQuad but the pivot point is the top left corner
public static void DrawQuadPivotCorner(float2 position, float2 size, float rotation, ColorRGBA color)
{
DrawQuadPivotCorner(float3(position, 0.0f), size, rotation, s_whiteTexture, color);
DrawQuadPivotCorner(float3(position, 0.0f), size, rotation, s_whiteTexture, s_quadBatchMaterial, color);
}
public static void DrawQuad(float3 position, float2 size, float rotation, ColorRGBA color)
{
DrawQuad(position, size, rotation, s_whiteTexture, color);
DrawQuad(position, size, rotation, s_whiteTexture, s_quadBatchMaterial, color);
}
public static void DrawQuadPivotCorner(float3 position, float2 size, float rotation, ColorRGBA color)
{
DrawQuadPivotCorner(position, size, rotation, s_whiteTexture, color);
DrawQuadPivotCorner(position, size, rotation, s_whiteTexture, s_quadBatchMaterial, color);
}
public static void DrawQuad(Matrix transform, ColorRGBA color)
{
DrawQuad(transform, s_whiteTexture, color);
DrawQuad(transform, s_whiteTexture, s_quadBatchMaterial, color);
}
// Quad Subtexture
@@ -1057,59 +1064,59 @@ namespace GlitchyEngine.Renderer
// Subtex only
public static void DrawQuad(float2 position, float2 size, float rotation, SubTexture2D texture, ColorRGBA color = .White)
public static void DrawQuad(float2 position, float2 size, float rotation, SubTexture2D texture, Material material = null, ColorRGBA color = .White)
{
DrawQuad(float3(position, 0.0f), size, rotation, texture.Texture, .White, texture.TexCoords);
DrawQuad(float3(position, 0.0f), size, rotation, texture.Texture, material, color, texture.TexCoords);
}
public static void DrawQuad(float3 position, float2 size, float rotation, SubTexture2D texture, ColorRGBA color = .White)
public static void DrawQuad(float3 position, float2 size, float rotation, SubTexture2D texture, Material material = null, ColorRGBA color = .White)
{
DrawQuad(position, size, rotation, texture.Texture, .White, texture.TexCoords);
DrawQuad(position, size, rotation, texture.Texture, material, color, texture.TexCoords);
}
public static void DrawQuad(Matrix transform, SubTexture2D texture, ColorRGBA color = .White)
public static void DrawQuad(Matrix transform, SubTexture2D texture, Material material = null, ColorRGBA color = .White)
{
DrawQuad(transform, texture.Texture, color, texture.TexCoords);
DrawQuad(transform, texture.Texture, material, color, texture.TexCoords);
}
// Subtex + Texcoords
public static void DrawQuad(float2 position, float2 size, float rotation, SubTexture2D subtexture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuad(float2 position, float2 size, float rotation, SubTexture2D subtexture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
float4 uv = CalculateSubTexcoords(subtexture.TexCoords, uvTransform);
DrawQuad(float3(position, 0.0f), size, rotation, subtexture.Texture, .White, uv);
DrawQuad(float3(position, 0.0f), size, rotation, subtexture.Texture, material, color, uv);
}
public static void DrawQuad(float3 position, float2 size, float rotation, SubTexture2D subtexture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuad(float3 position, float2 size, float rotation, SubTexture2D subtexture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
float4 uv = CalculateSubTexcoords(subtexture.TexCoords, uvTransform);
DrawQuad(position, size, rotation, subtexture.Texture, .White, uv);
DrawQuad(position, size, rotation, subtexture.Texture, material, color, uv);
}
public static void DrawQuad(Matrix transform, SubTexture2D subtexture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue)
public static void DrawQuad(Matrix transform, SubTexture2D subtexture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue)
{
float4 uv = CalculateSubTexcoords(subtexture.TexCoords, uvTransform);
DrawQuad(transform, subtexture.Texture, color, uv, entityId);
DrawQuad(transform, subtexture.Texture, material, color, uv, entityId);
}
// Textured Quad
public static void DrawQuad(float2 position, float2 size, float rotation, Texture texture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuad(float2 position, float2 size, float rotation, Texture texture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
DrawQuad(float3(position, 0.0f), size, rotation, texture, color, uvTransform);
DrawQuad(float3(position, 0.0f), size, rotation, texture, material, color, uvTransform);
}
public static void DrawQuad(float3 position, float2 size, float rotation, Texture texture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuad(float3 position, float2 size, float rotation, Texture texture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
Matrix transform = Calculate2DTransform(position, size, rotation);
DrawQuad(transform, texture, color, uvTransform);
DrawQuad(transform, texture, material, color, uvTransform);
}
public static void DrawQuad(Matrix transform, Texture texture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue)
public static void DrawQuad(Matrix transform, Texture texture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue)
{
Debug.Profiler.ProfileRendererFunction!();
@@ -1117,7 +1124,7 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
#endif
QueueQuadInstance(transform, color, texture, transform.Translation.Z, uvTransform, entityId);
QueueQuadInstance(transform, color, texture, material ?? s_quadBatchMaterial, transform.Translation.Z, uvTransform, entityId);
if(s_drawOrder == .Immediate)
{
@@ -1142,7 +1149,8 @@ namespace GlitchyEngine.Renderer
uvTransform = sprite.TextureCoordinates;
}
DrawQuad(transform, spriteTexture ?? s_whiteTexture, spriteRenderer.Color, uvTransform, entityId);
// TODO: Material for Sprite renderer
DrawQuad(transform, spriteTexture ?? s_whiteTexture, null, spriteRenderer.Color, uvTransform, entityId);
}
public static void DrawCircle(Matrix transform, CircleRendererComponent* spriteRenderer, uint32 entityId)
@@ -1152,14 +1160,14 @@ namespace GlitchyEngine.Renderer
// Textured quad pivot
public static void DrawQuadPivotCorner(float2 position, float2 size, float rotation, Texture2D texture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuadPivotCorner(float2 position, float2 size, float rotation, Texture2D texture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
DrawQuadPivotCorner(float3(position, 0.0f), size, rotation, texture, color, uvTransform);
DrawQuadPivotCorner(float3(position, 0.0f), size, rotation, texture, material, color, uvTransform);
}
public static void DrawQuadPivotCorner(float3 position, float2 size, float rotation, Texture2D texture, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
public static void DrawQuadPivotCorner(float3 position, float2 size, float rotation, Texture2D texture, Material material = null, ColorRGBA color = .White, float4 uvTransform = .(0, 0, 1, 1))
{
DrawQuad(position + float3(size.X / 2, size.Y / -2, 0), size, rotation, texture, color, uvTransform);
DrawQuad(position + float3(size.X / 2, size.Y / -2, 0), size, rotation, texture, material, color, uvTransform);
}
// Circle
@@ -1194,7 +1202,8 @@ namespace GlitchyEngine.Renderer
Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene.");
#endif
QueueCircleInstance(transform, color, texture, transform.Translation.Z, uvTransform, innerRadius, entityId);
Runtime.FatalError("Circle renderer currently broken, do we need it?");
QueueCircleInstance(transform, color, texture, null, transform.Translation.Z, uvTransform, innerRadius, entityId);
if(s_drawOrder == .Immediate)
{
+13 -30
View File
@@ -19,6 +19,7 @@ namespace GlitchyEngine.Renderer.Text
internal static FT_Library s_Library;
public static AssetHandle<Effect> _msdfEffect;
public static Material _msdfMaterial ~ _?.ReleaseRef();
internal static bool s_isInitialized;
@@ -33,6 +34,7 @@ namespace GlitchyEngine.Renderer.Text
// TODO: We might get away with a non blocking load here, but not for now!
_msdfEffect = Content.LoadAsset("Resources/Shaders/msdfShader.hlsl", null, true);
_msdfMaterial = new Material(_msdfEffect);
s_isInitialized = true;
}
@@ -558,9 +560,9 @@ namespace GlitchyEngine.Renderer.Text
textRenderer.NeedsRebuild = false;
}
public static void DrawText(PreparedText text, Matrix transform, ColorRGBA fontColor = .White)
public static void DrawText(PreparedText text, Matrix transform, ColorRGBA fontColor = .White, uint32 entityId = uint32.MaxValue)
{
/*Debug.Profiler.ProfileRendererFunction!();
Debug.Profiler.ProfileRendererFunction!();
text.AddRef();
defer text.ReleaseRef();
@@ -568,20 +570,9 @@ namespace GlitchyEngine.Renderer.Text
if (text.Glyphs.Count == 0)
return;
Renderer2D.Flush();
// TODO: this is very not good!
// At some point we will support using materials with the 2D renderer. At that point we can simply bind different materials with fonts (or glyphs?) and don't need this hack anymore. One day...
var lastEffect = Renderer2D.[Friend]s_currentQuadEffect;
Renderer2D.[Friend]s_currentQuadEffect = _msdfEffect;
// TODO: oh no....
// Copy viewProjection from current effect
Matrix viewProjection = Renderer2D.[Friend]s_quadBatchEffect.Variables["ViewProjection"].[Friend]GetData<Matrix>();
_msdfEffect.Variables["ViewProjection"].SetData(viewProjection);
// TODO: this doesn't really work with fallback fonts
// TODO: this doesn't really work with fallback fonts unless we use the same settings for all fonts
float2 unitRange = ((float)text.Font._range) / float2(text.Font._atlas.Width, text.Font._atlas.Height);
_msdfEffect.Variables["UnitRange"].SetData(unitRange);
_msdfMaterial.SetVariable("UnitRange", unitRange);
List<Texture2D> atlasses = scope .();
@@ -608,11 +599,9 @@ namespace GlitchyEngine.Renderer.Text
float2 atlasSize = .(atlas.Width, atlas.Height);
float adjustToPenX = glyphDesc.AdjustToPen;
//adjustToPenX *= glyphFontScale;
adjustToPenX *= glyph.Scale;
float adjustToBaseline = glyphDesc.AdjustToBaseLine;
//adjustToBaseline *= glyphFontScale;
adjustToBaseline *= glyph.Scale;
// Rectangle on the screen
@@ -630,31 +619,25 @@ namespace GlitchyEngine.Renderer.Text
texRect /= float4(atlasSize, atlasSize);
// Show quads
// Renderer2D.DrawQuad(float3(viewportRect.X + viewportRect.Z / 2, viewportRect.Y + viewportRect.W / 2, 1), .(viewportRect.Z, viewportRect.W), 0, .Red);
float3 position = .(viewportRect.X + viewportRect.Z / 2, viewportRect.Y + viewportRect.W / 2, 0);
Matrix glyphTransform = transform * Matrix.Translation(position) * Matrix.Scaling(viewportRect.Z, viewportRect.W, 1.0f);
Renderer2D.DrawQuad(glyphTransform, atlas, glyphColor, texRect);
//Renderer2D.DrawQuad(float2(viewportRect.X + viewportRect.Z / 2, viewportRect.Y + viewportRect.W / 2), .(viewportRect.Z, viewportRect.W), 0, atlas, glyphColor, texRect);
// Show pen positions
// Renderer2D.DrawQuad(float3(float2(x, y) + glyph.Position, -1), .(1), 0, .Green);
Renderer2D.DrawQuad(glyphTransform, atlas, material: _msdfMaterial, color: glyphColor, uvTransform: texRect, entityId: entityId);
}
// TODO: Get rid of the flush.
// We need to flush, because currently Renderer2D doesn't increase the counter of passed textures.
// Once it does that, we can
// 1. Stop manually holding the references in this method
// 2. Stop forcing a flush (which could make having multiple text instances way more efficient)
Renderer2D.Flush();
// TODO: not good!
// Change back effect
Renderer2D.[Friend]s_currentQuadEffect = lastEffect;
// release all atlas textures
for(int i < atlasses.Count)
{
atlasses[i].ReleaseRef();
}*/
}
}
}
}
+2 -2
View File
@@ -139,7 +139,7 @@ class SceneRenderer
if (editorFlags.Flags.HasFlag(.HideInScene) || text.PreparedText == null)
continue;
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform, text.Color);
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform, text.Color, entity.Index);
}
Renderer2D.EndScene();
@@ -230,7 +230,7 @@ class SceneRenderer
if (editorFlags.Flags.HasFlag(.HideInScene) || text.PreparedText == null)
continue;
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform, text.Color);
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform, text.Color, entity.Index);
}
//FontRenderer.DrawText(_smallLinesInfo, 0, 0);