Image support for vertex generator.

This commit is contained in:
H. Utku Maden 2024-04-14 23:21:08 +03:00
parent 5aa9a2f4e6
commit fe3c2d0550
3 changed files with 166 additions and 49 deletions

@ -1,3 +1,4 @@
using Quik.Media;
using System;
using System.Collections;
using System.Collections.Generic;
@ -13,7 +14,7 @@ namespace Quik.VertexGenerator
private int _start;
private int _baseOffset;
private QRectangle _bounds;
private QuikTexture _texture;
private QImage _texture;
public int ZDepth { get; private set; }
public QuikVertex[] VertexArray => _vertices.InternalArray;
@ -32,7 +33,7 @@ namespace Quik.VertexGenerator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void StartDrawCall(in QRectangle bounds, QuikTexture texture, int baseOffset)
public void StartDrawCall(in QRectangle bounds, QImage texture, int baseOffset)
{
_start = ElementCount;
_texture = texture;
@ -47,7 +48,7 @@ namespace Quik.VertexGenerator
public void StartDrawCall(in QRectangle bounds, int baseOffset) => StartDrawCall(bounds, null, baseOffset);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void StartDrawCall(in QRectangle bounds, QuikTexture texture) => StartDrawCall(bounds, texture, _vertices.Count);
public void StartDrawCall(in QRectangle bounds, QImage texture) => StartDrawCall(bounds, texture, _vertices.Count);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddVertex(in QuikVertex vertex)
@ -99,9 +100,9 @@ namespace Quik.VertexGenerator
public int Start { get; }
public int Count { get; }
public QRectangle Bounds { get; }
public QuikTexture Texture { get; }
public QImage Texture { get; }
public DrawCall(int start, int count, in QRectangle bounds, QuikTexture texture)
public DrawCall(int start, int count, in QRectangle bounds, QImage texture)
{
Start = start;
Count = count;

@ -28,10 +28,16 @@ namespace Quik.VertexGenerator
/// </summary>
public int ZIndex;
/// <summary>
/// The texture layer to draw for 3d images.
/// </summary>
public float TextureLayer;
public static int PositionOffset => 0;
public static unsafe int TextureCoordinatesOffset => sizeof(QVec2);
public static unsafe int ColorOffset => 2 * sizeof(QVec2);
public static unsafe int ZIndexOffset => ColorOffset + sizeof(QColor);
public static unsafe int TextureLayerOffset => ZIndexOffset + sizeof(int);
public static unsafe int Stride => sizeof(QuikVertex);
}
}

@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Quik.CommandMachine;
using Quik.Media;
using Quik.Typography;
namespace Quik.VertexGenerator
{
@ -13,6 +15,9 @@ namespace Quik.VertexGenerator
/// </summary>
protected float CurveGranularity =>
(Style["-vertex-curve-granularity"] is float value) ? value : 1.0f;
protected bool BlendTextures =>
(Style["-vertex-blend-textures"] is bool value) ? value : false;
protected QuikVertex StrokeVertex => new QuikVertex()
{
ZIndex = Style.ZIndex ?? this.ZIndex,
@ -24,13 +29,19 @@ namespace Quik.VertexGenerator
Color = Style.Color ?? QColor.White,
};
protected QuikVertex ImageVertex => new QuikVertex()
{
ZIndex = Style.ZIndex ?? this.ZIndex,
Color = BlendTextures ? (Style.Color ?? QColor.White) : QColor.White,
};
public override void Reset()
{
base.Reset();
DrawQueue.Clear();
}
protected override void ChildProcessCommand(Command name, CommandEnumerator queue)
protected override void ChildProcessCommand(Command name, CommandQueue queue)
{
base.ChildProcessCommand(name, queue);
@ -39,6 +50,7 @@ namespace Quik.VertexGenerator
case Command.Line: LineProc(queue); break;
case Command.Bezier: BezierProc(queue); break;
case Command.Rectangle: RectangleProc(queue); break;
case Command.Image: ImageProc(queue); break;
default: break;
}
}
@ -55,7 +67,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QLine> LineList = new List<QLine>();
private void LineProc(CommandEnumerator queue)
private void LineProc(CommandQueue queue)
{
Frame frame = queue.Dequeue();
@ -280,7 +292,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QBezier> BezierList = new List<QBezier>();
private void BezierProc(CommandEnumerator queue)
private void BezierProc(CommandQueue queue)
{
Frame a = queue.Dequeue();
Frame b;
@ -397,7 +409,7 @@ namespace Quik.VertexGenerator
}
private readonly List<QRectangle> RectangleList = new List<QRectangle>();
private void RectangleProc(CommandEnumerator queue)
private void RectangleProc(CommandQueue queue)
{
Frame frame = queue.Dequeue();
RectangleList.Clear();
@ -422,8 +434,8 @@ namespace Quik.VertexGenerator
{
QRectangle outer = RectangleList[i];
QRectangle inner = new QRectangle(
outer.Right - stroke, outer.Bottom + stroke,
outer.Left + stroke, outer.Top - stroke);
outer.Right - stroke, outer.Bottom - stroke,
outer.Left + stroke, outer.Top + stroke);
GenerateRectangleBase(inner, Math.Max(radius - stroke, 0.0f));
@ -469,13 +481,13 @@ namespace Quik.VertexGenerator
QVec2 aPos, bPos, cPos, dPos;
QuikVertex v = FillVertex;
aPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + radius);
aPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
bPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + radius);
bPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
cPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - radius);
cPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius);
DrawQueue.AddVertex(v);
dPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - radius);
dPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius);
DrawQueue.AddVertex(v);
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
@ -496,9 +508,9 @@ namespace Quik.VertexGenerator
// Draw east rectangle.
v.Position = new QVec2(rectangle.Right, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
DrawQueue.AddVertex(v);
DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(7);
@ -516,9 +528,9 @@ namespace Quik.VertexGenerator
// Draw west rectangle.
v.Position = new QVec2(rectangle.Left, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Left, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
DrawQueue.AddElement(11); DrawQueue.AddElement(0); DrawQueue.AddElement(3);
@ -609,13 +621,13 @@ namespace Quik.VertexGenerator
DrawQueue.RestoreOffset();
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom);
@ -669,13 +681,13 @@ namespace Quik.VertexGenerator
// a-b-c-d
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
// ef-gh-ij-kl
@ -684,24 +696,24 @@ namespace Quik.VertexGenerator
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Bottom);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Right, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Top);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Left, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
// mno
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
nPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + radius);
nPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom);
DrawQueue.AddVertex(v);
@ -709,15 +721,15 @@ namespace Quik.VertexGenerator
// pqr
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom);
DrawQueue.AddVertex(v);
qPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + radius);
qPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Right, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
// stu
v.Position = new QVec2(rectangle.Right, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
DrawQueue.AddVertex(v);
tPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - radius);
tPos = v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top);
DrawQueue.AddVertex(v);
@ -726,9 +738,9 @@ namespace Quik.VertexGenerator
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top);
DrawQueue.AddVertex(v);
wPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - radius);
wPos = v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Left, rectangle.Top + radius);
DrawQueue.AddVertex(v);
// E
@ -859,23 +871,23 @@ namespace Quik.VertexGenerator
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom + stroke);
v.Position = new QVec2(rectangle.Left + radius, rectangle.Bottom - stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Right, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom + radius);
v.Position = new QVec2(rectangle.Right - stroke, rectangle.Bottom - radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Left + radius, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top - stroke);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top + stroke);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Right - radius, rectangle.Top);
DrawQueue.AddVertex(v);
@ -884,9 +896,9 @@ namespace Quik.VertexGenerator
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top - radius);
v.Position = new QVec2(rectangle.Left + stroke, rectangle.Top + radius);
DrawQueue.AddVertex(v);
v.Position = new QVec2(rectangle.Left, rectangle.Bottom + radius);
DrawQueue.AddVertex(v);
@ -1000,6 +1012,104 @@ namespace Quik.VertexGenerator
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(4);
}
private void ImageProc(CommandQueue queue)
{
Frame frame = queue.Dequeue();
ImageCommandFlags flags = (ImageCommandFlags)frame.I1;
QImage image = queue.Dequeue().As<QImage>();
int count = flags.HasFlag(ImageCommandFlags.Single) ? 1 : frame.I2;
if (flags.HasFlag(ImageCommandFlags.Image3d))
{
Image3d(queue, image, count);
}
else
{
Image2d(queue, image, count, flags.HasFlag(ImageCommandFlags.UVs));
}
}
private void Image2d(CommandQueue queue, QImage image, int count, bool uv)
{
DrawQueue.StartDrawCall(Viewport, image);
for (int i = 0; i < count; i++)
{
QRectangle rect = (QRectangle)queue.Dequeue();
QRectangle uvs;
if (uv)
{
uvs = (QRectangle)queue.Dequeue();
}
else
{
uvs = new QRectangle(1, 1, 0, 0);
}
DrawQueue.RestoreOffset();
QuikVertex vertex = ImageVertex;
vertex.Position = new QVec2(rect.Top, rect.Left);
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Left);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Bottom, rect.Left);
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Left);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Bottom, rect.Right);
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Right);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Top, rect.Right);
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Right);
DrawQueue.AddVertex(vertex);
DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
}
DrawQueue.EndDrawCall();
}
private void Image3d(CommandQueue queue, QImage image, int count)
{
DrawQueue.StartDrawCall(Viewport, image);
for (int i = 0; i < count; i++)
{
QRectangle rect = (QRectangle)queue.Dequeue();
QRectangle uvs = (QRectangle)queue.Dequeue();
int layer = (int)queue.Dequeue();
DrawQueue.RestoreOffset();
QuikVertex vertex = ImageVertex;
vertex.TextureLayer = layer;
vertex.Position = new QVec2(rect.Top, rect.Left);
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Left);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Bottom, rect.Left);
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Left);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Bottom, rect.Right);
vertex.TextureCoordinates = new QVec2(uvs.Bottom, uvs.Right);
DrawQueue.AddVertex(vertex);
vertex.Position = new QVec2(rect.Top, rect.Right);
vertex.TextureCoordinates = new QVec2(uvs.Top, uvs.Right);
DrawQueue.AddVertex(vertex);
DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
}
DrawQueue.EndDrawCall();
}
private struct LineInfo
{
public int BaseOffset { get; }