Skip to content

Commit

Permalink
[Native] Move C++ methods for SpriteBatch and FastTextRenderer to C# (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Jklawreszuk authored Oct 10, 2023
1 parent a5b539f commit d61d532
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 4,512 deletions.
105 changes: 101 additions & 4 deletions sources/engine/Stride.Graphics/FastTextRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ namespace Stride.Graphics
/// </summary>
public class FastTextRenderer : ComponentBase
{
private static readonly VertexPositionNormalTexture[] BaseVertexBufferData =
{
// Position Normal UV Coordinates
new( new(-1, 1, 0), new(0, 0, 1), new(0, 0) ),
new( new(1, 1, 0 ), new(0, 0, 1 ), new(1, 0 )),
new( new(-1, -1, 0 ), new(0, 0, 1 ), new(0, 1 )),
new( new(1, -1, 0 ), new(0, 0, 1 ), new(1, 1 )),
};
private const int VertexBufferCount = 2;

private const int IndexStride = sizeof(int);
Expand Down Expand Up @@ -211,12 +219,11 @@ public unsafe void End([NotNull] GraphicsContext graphicsContext)
var constantInfos = new RectangleF(GlyphWidth, GlyphHeight, DebugSpriteWidth, DebugSpriteHeight);
foreach (var textInfo in stringsToDraw)
{
Span<VertexPositionNormalTexture> vertexPositionSpan = new((void*)mappedVertexBufferPointer, VertexBufferLength);
var textLength = textInfo.Text.Length;
var textLengthPointer = new IntPtr(&textLength);

Native.NativeInvoke.xnGraphicsFastTextRendererGenerateVertices(constantInfos, textInfo.RenderingInfo, textInfo.Text, out textLengthPointer, out mappedVertexBufferPointer);
GraphicsFastTextRendererGenerateVertices(constantInfos, textInfo.RenderingInfo, textInfo.Text, ref textLength, vertexPositionSpan);

charsToRenderCount += *(int*)textLengthPointer.ToPointer();
charsToRenderCount += textLength;
}
}

Expand Down Expand Up @@ -247,6 +254,96 @@ public unsafe void End([NotNull] GraphicsContext graphicsContext)
graphicsContext.CommandList.DrawIndexed(charsToRenderCount * 6);
}

public unsafe void GraphicsFastTextRendererGenerateVertices(RectangleF constantInfos, RectangleF renderInfos, string textPointer, ref int textLength, Span<VertexPositionNormalTexture> vertexBuffer)
{
float fX = renderInfos.X / renderInfos.Width;
float fY = renderInfos.Y / renderInfos.Height;
float fW = constantInfos.X / renderInfos.Width;
float fH = constantInfos.Y / renderInfos.Height;

RectangleF destination = new(fX, fY, fW, fH);
RectangleF source = new(0.0f, 0.0f, constantInfos.X, constantInfos.Y);

// Copy the array length (since it may change during an iteration)
int textCharCount = textLength;

float scaledDestinationX;
float scaledDestinationY = -(destination.Y * 2f - 1f);

float invertedWidth = 1f / constantInfos.Width;
float invertedHeight = 1f / constantInfos.Height;

Span<(Vector2 Position, Vector2 TextureCoordinate)> baseData = stackalloc (Vector2, Vector2)[4]
{
( new(-destination.Width, +destination.Height), new(0 * source.Width * invertedWidth, 0 * source.Height * invertedHeight) ),
( new(+destination.Width, +destination.Height), new(1 * source.Width * invertedWidth, 0 * source.Height * invertedHeight) ),
( new(-destination.Width, -destination.Height), new(0 * source.Width * invertedWidth, 1 * source.Height * invertedHeight) ),
( new(+destination.Width, -destination.Height), new(1 * source.Width * invertedWidth, 1 * source.Height * invertedHeight) ),
};

int j = 0;

for (int i = 0; i < textCharCount; i++)
{
char currentChar = textPointer[i];

if (currentChar == '\v')
{
// Tabulation
destination.X += 8 * fX;
--textLength;
continue;
}
else if (currentChar >= 10 && currentChar <= 13) // '\n' '\v' '\f' '\r'
{
destination.X = fX;
destination.Y += fH;
scaledDestinationY = -(destination.Y * 2f - 1f);
--textLength;
continue;
}
else if (currentChar < 32 || currentChar > 126)
{
currentChar = ' ';
}

source.X = (currentChar % 32 * constantInfos.X) * invertedWidth;
source.Y = (currentChar / 32 % 4 * constantInfos.Y) * invertedHeight;

scaledDestinationX = destination.X * 2f - 1f;

// 0
vertexBuffer[j].Position.X = scaledDestinationX + baseData[0].Position.X;
vertexBuffer[j].Position.Y = scaledDestinationY + baseData[0].Position.Y;
vertexBuffer[j].TextureCoordinate.X = source.X + baseData[0].TextureCoordinate.X;
vertexBuffer[j].TextureCoordinate.Y = source.Y + baseData[0].TextureCoordinate.Y;
j++;

// 1
vertexBuffer[j].Position.X = scaledDestinationX + baseData[1].Position.X;
vertexBuffer[j].Position.Y = scaledDestinationY + baseData[1].Position.Y;
vertexBuffer[j].TextureCoordinate.X = source.X + baseData[1].TextureCoordinate.X;
vertexBuffer[j].TextureCoordinate.Y = source.Y + baseData[1].TextureCoordinate.Y;
j++;

// 2
vertexBuffer[j].Position.X = scaledDestinationX + baseData[2].Position.X;
vertexBuffer[j].Position.Y = scaledDestinationY + baseData[2].Position.Y;
vertexBuffer[j].TextureCoordinate.X = source.X + baseData[2].TextureCoordinate.X;
vertexBuffer[j].TextureCoordinate.Y = source.Y + baseData[2].TextureCoordinate.Y;
j++;

// 3
vertexBuffer[j].Position.X = scaledDestinationX + baseData[3].Position.X;
vertexBuffer[j].Position.Y = scaledDestinationY + baseData[3].Position.Y;
vertexBuffer[j].TextureCoordinate.X = source.X + baseData[3].TextureCoordinate.X;
vertexBuffer[j].TextureCoordinate.Y = source.Y + baseData[3].TextureCoordinate.Y;
j++;

destination.X += destination.Width;
}
}

/// <summary>
/// Sets or gets the color to use when drawing the text.
/// </summary>
Expand Down
39 changes: 37 additions & 2 deletions sources/engine/Stride.Graphics/SpriteBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Runtime.InteropServices;
using System.Text;
using Stride.Core.Mathematics;
using Stride.Native;
using Stride.Rendering;

namespace Stride.Graphics
Expand Down Expand Up @@ -590,9 +589,45 @@ internal unsafe void DrawSprite(Texture texture, ref RectangleF destination, boo

protected override unsafe void UpdateBufferValuesFromElementInfo(ref ElementInfo elementInfo, IntPtr vertexPtr, IntPtr indexPtr, int vertexOffset)
{
var vertex = (VertexPositionColorTextureSwizzle*)vertexPtr;
fixed (SpriteDrawInfo* drawInfo = &elementInfo.DrawInfo)
{
NativeInvoke.UpdateBufferValuesFromElementInfo(new IntPtr(drawInfo), vertexPtr, indexPtr, vertexOffset);
float deltaX = 1.0f / drawInfo->TextureSize.X;
float deltaY = 1.0f / drawInfo->TextureSize.Y;

Vector2 rotation = new(1,0);

if (Math.Abs(drawInfo->Rotation) > float.Epsilon)
{
(rotation.X, rotation.Y) = MathF.SinCos(drawInfo->Rotation);
}

Vector2 origin = drawInfo->Origin;
origin.X /= Math.Max(float.Epsilon, drawInfo->Source.Width);
origin.Y /= Math.Max(float.Epsilon, drawInfo->Source.Height);

for (int j = 0; j < 4; j++)
{
Vector2 corner = CornerOffsets[j];
Vector2 position;
position.X = (corner.X - origin.X) * drawInfo->Destination.Width;
position.Y = (corner.Y - origin.Y) * drawInfo->Destination.Height;

vertex->Position.X = drawInfo->Destination.X + (position.X * rotation.X) - (position.Y * rotation.Y);
vertex->Position.Y = drawInfo->Destination.Y + (position.X * rotation.Y) + (position.Y * rotation.X);
vertex->Position.Z = drawInfo->Depth;
vertex->Position.W = 1.0f;
vertex->ColorScale = drawInfo->ColorScale;
vertex->ColorAdd = drawInfo->ColorAdd;

corner = CornerOffsets[((j ^ (int)drawInfo->SpriteEffects) + (int)drawInfo->Orientation) % 4];
vertex->TextureCoordinate.X = (drawInfo->Source.X + corner.X * drawInfo->Source.Width) * deltaX;
vertex->TextureCoordinate.Y = (drawInfo->Source.Y + corner.Y * drawInfo->Source.Height) * deltaY;

vertex->Swizzle = (int)drawInfo->Swizzle;

vertex++;
}
}
}

Expand Down
3 changes: 0 additions & 3 deletions sources/engine/Stride.Graphics/Stride.Graphics.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
</PropertyGroup>
<Import Project="..\..\targets\Stride.props" />
<PropertyGroup>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<StrideAssemblyProcessor>true</StrideAssemblyProcessor>
<StridePlatformDependent>true</StridePlatformDependent>
<StrideBuildTags>*</StrideBuildTags>
Expand Down Expand Up @@ -43,7 +41,6 @@
<GlobalPropertiesToRemove>TargetFramework;StrideGraphicsApi</GlobalPropertiesToRemove>
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
</ProjectReference>
<ProjectReference Include="..\Stride.Native\Stride.Native.csproj" />
<ProjectReference Include="..\Stride.Shaders\Stride.Shaders.csproj" />
<ProjectReference Include="..\Stride\Stride.csproj" />
<PackageReference Include="System.Memory" Version="4.5.4" />
Expand Down
3 changes: 2 additions & 1 deletion sources/engine/Stride.Input/Stride.Input.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project>
<Project>
<PropertyGroup>
<StrideRuntime>true</StrideRuntime>
<StrideRuntimeWindowsNet6>true</StrideRuntimeWindowsNet6>
Expand All @@ -21,6 +21,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Stride.Games\Stride.Games.csproj" />
<ProjectReference Include="..\Stride.Native\Stride.Native.csproj" />
<PackageReference Include="SharpDX.RawInput" Version="4.2.0" Condition="$(TargetFramework.StartsWith('net4'))" />
<PackageReference Include="SharpDX.DirectInput" Version="4.2.0" Condition="$(TargetFramework.Contains('-windows'))" />
<PackageReference Include="SharpDX.XInput" Version="4.2.0" Condition="$(TargetFramework.Contains('-windows'))" />
Expand Down
112 changes: 0 additions & 112 deletions sources/engine/Stride.Native/FastTextRenderer/FastTextRenderer.c

This file was deleted.

Loading

0 comments on commit d61d532

Please sign in to comment.