Implement the first version of the direct rendering API.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Dashboard.Drawing
|
namespace Dashboard.Drawing
|
||||||
{
|
{
|
||||||
@@ -31,11 +32,9 @@ namespace Dashboard.Drawing
|
|||||||
UnsignedByte,
|
UnsignedByte,
|
||||||
UnsignedShort,
|
UnsignedShort,
|
||||||
UnsignedInt,
|
UnsignedInt,
|
||||||
UnsignedLong,
|
|
||||||
Byte,
|
Byte,
|
||||||
Short,
|
Short,
|
||||||
Int,
|
Int,
|
||||||
Long,
|
|
||||||
Half,
|
Half,
|
||||||
Float,
|
Float,
|
||||||
Double,
|
Double,
|
||||||
@@ -48,7 +47,6 @@ namespace Dashboard.Drawing
|
|||||||
UnsignedLong,
|
UnsignedLong,
|
||||||
Short,
|
Short,
|
||||||
Int,
|
Int,
|
||||||
Long,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BlendFunction
|
public enum BlendFunction
|
||||||
@@ -138,10 +136,12 @@ namespace Dashboard.Drawing
|
|||||||
|
|
||||||
public readonly record struct BlendMode(bool Enabled, BlendFactor Color, BlendFactor Alpha)
|
public readonly record struct BlendMode(bool Enabled, BlendFactor Color, BlendFactor Alpha)
|
||||||
{
|
{
|
||||||
[MemberNotNullWhen(true, nameof(Unified))]
|
[MemberNotNullWhen(false, nameof(Unified), nameof(UnifiedEquation))]
|
||||||
public bool IsSeparate => Color != Alpha;
|
public bool IsSeparate => Color != Alpha;
|
||||||
public BlendFactor? Unified => IsSeparate ? null : Color;
|
public BlendFactor? Unified => IsSeparate ? null : Color;
|
||||||
public BlendEquation Equation { get; init; } = BlendEquation.Add;
|
public BlendEquation? UnifiedEquation => IsSeparate ? null : ColorEquation;
|
||||||
|
public BlendEquation ColorEquation { get; init; } = BlendEquation.Add;
|
||||||
|
public BlendEquation AlphaEquation { get; init; } = BlendEquation.Add;
|
||||||
public Color Constant { get; init; } = System.Drawing.Color.Black;
|
public Color Constant { get; init; } = System.Drawing.Color.Black;
|
||||||
|
|
||||||
public BlendMode(BlendFunction source, BlendFunction destination)
|
public BlendMode(BlendFunction source, BlendFunction destination)
|
||||||
@@ -176,13 +176,13 @@ namespace Dashboard.Drawing
|
|||||||
public int Divisor { get; init; } = 1;
|
public int Divisor { get; init; } = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record struct UniformDescriptor(UniformType Type, long Offset, long Size);
|
public record struct UniformDescriptor(int Location, UniformType Type, long Offset, long Size);
|
||||||
|
|
||||||
public struct DrawCall(MeshPrimitive primitive, IBuffer vertexBuffer)
|
public struct DrawCall(MeshPrimitive primitive, IBuffer vertexBuffer, int first, int count)
|
||||||
{
|
{
|
||||||
public IShader? ShaderPipeline { get; init; }
|
public IShader? ShaderPipeline { get; init; }
|
||||||
public Box2d ViewportRegion { get; init; }
|
public Box2d ViewportRegion { get; init; } = new Box2d(Vector2.Zero, Vector2.PositiveInfinity);
|
||||||
public Box2d ScissorRegion { get; init; }
|
public Box2d ScissorRegion { get; init; } = new Box2d(Vector2.PositiveInfinity, Vector2.PositiveInfinity);
|
||||||
public WindingOrder FrontFace { get; init; } = WindingOrder.Counterclockwise;
|
public WindingOrder FrontFace { get; init; } = WindingOrder.Counterclockwise;
|
||||||
public FaceCulling CullMode { get; init; } = FaceCulling.Back;
|
public FaceCulling CullMode { get; init; } = FaceCulling.Back;
|
||||||
public BlendMode BlendMode { get; init; } = BlendMode.Normal;
|
public BlendMode BlendMode { get; init; } = BlendMode.Normal;
|
||||||
@@ -198,13 +198,19 @@ namespace Dashboard.Drawing
|
|||||||
public float LineWidth { get; init; }= 1.0f;
|
public float LineWidth { get; init; }= 1.0f;
|
||||||
|
|
||||||
public MeshPrimitive Primitive { get; init; } = primitive;
|
public MeshPrimitive Primitive { get; init; } = primitive;
|
||||||
public List<ITexture> Textures { get; init; } = [];
|
public List<ITexture?> Textures { get; init; } = [];
|
||||||
public List<VertexAttribute> Attributes { get; init; } = [];
|
public List<VertexAttribute> Attributes { get; init; } = [];
|
||||||
public List<UniformDescriptor> Uniforms { get; init; } = [];
|
public List<UniformDescriptor> Uniforms { get; init; } = [];
|
||||||
public IndexType IndexType { get; init; } = IndexType.UnsignedShort;
|
public IndexType IndexType { get; init; } = IndexType.UnsignedShort;
|
||||||
|
|
||||||
|
public int First { get; init; } = first;
|
||||||
|
public int Count { get; init; } = count;
|
||||||
|
public long Offset { get; init; } = 0;
|
||||||
|
public int BaseVertex { get; init; } = 0;
|
||||||
|
|
||||||
public IBuffer VertexBuffer { get; init; } = vertexBuffer;
|
public IBuffer VertexBuffer { get; init; } = vertexBuffer;
|
||||||
public IBuffer? ElementBuffer { get; init; }
|
public IBuffer? ElementBuffer { get; init; }
|
||||||
|
public ReadOnlyMemory<byte> UniformData { get; init; } = ReadOnlyMemory<byte>.Empty;
|
||||||
public IBuffer? UniformBuffer { get; init; }
|
public IBuffer? UniformBuffer { get; init; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Numerics;
|
||||||
using Dashboard.Drawing;
|
using Dashboard.Drawing;
|
||||||
using Dashboard.Pal;
|
using Dashboard.Pal;
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
@@ -12,10 +14,11 @@ namespace Dashboard.OpenGL.Drawing
|
|||||||
public Version DriverVersion { get; } = new Version(0, 1);
|
public Version DriverVersion { get; } = new Version(0, 1);
|
||||||
IContextBase IContextExtensionBase.Context => Context;
|
IContextBase IContextExtensionBase.Context => Context;
|
||||||
|
|
||||||
|
private int _vao = -1;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Require(DeviceContext context) => Context = context;
|
public void Require(DeviceContext context) => Context = context;
|
||||||
@@ -23,7 +26,10 @@ namespace Dashboard.OpenGL.Drawing
|
|||||||
|
|
||||||
public void Begin()
|
public void Begin()
|
||||||
{
|
{
|
||||||
|
if (_vao == -1)
|
||||||
|
{
|
||||||
|
GL.CreateVertexArray(out _vao);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void End()
|
public void End()
|
||||||
@@ -51,7 +57,22 @@ namespace Dashboard.OpenGL.Drawing
|
|||||||
|
|
||||||
public void Draw(DrawCall drawCall)
|
public void Draw(DrawCall drawCall)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
Vector2 size = Context.FramebufferSize;
|
||||||
|
drawCall.SetAll(size, _vao, false);
|
||||||
|
|
||||||
|
if (drawCall.ElementBuffer is null)
|
||||||
|
{
|
||||||
|
GL.DrawArrays(drawCall.Primitive.OpenGL, drawCall.First, drawCall.Count);
|
||||||
|
}
|
||||||
|
else if (drawCall.BaseVertex == 0)
|
||||||
|
{
|
||||||
|
GL.DrawElements(drawCall.Primitive.OpenGL, drawCall.Count, drawCall.IndexType.OpenGL, (nint)drawCall.Offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.DrawElementsBaseVertex(drawCall.Primitive.OpenGL, drawCall.Count, drawCall.IndexType.OpenGL, (nint)drawCall.Offset, drawCall.BaseVertex);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,474 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using Dashboard.Drawing;
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using UniformType = Dashboard.Drawing.UniformType;
|
||||||
|
using Vector2 = System.Numerics.Vector2;
|
||||||
|
|
||||||
|
namespace Dashboard.OpenGL.Drawing
|
||||||
|
{
|
||||||
|
public static class GLStateExtensions
|
||||||
|
{
|
||||||
|
extension(VertexAttributeType type)
|
||||||
|
{
|
||||||
|
public All OpenGL => type switch
|
||||||
|
{
|
||||||
|
VertexAttributeType.UnsignedByte => All.UnsignedByte,
|
||||||
|
VertexAttributeType.UnsignedShort => All.UnsignedShort,
|
||||||
|
VertexAttributeType.UnsignedInt => All.UnsignedInt,
|
||||||
|
VertexAttributeType.Byte => All.Byte,
|
||||||
|
VertexAttributeType.Short => All.Short,
|
||||||
|
VertexAttributeType.Int => All.Int,
|
||||||
|
VertexAttributeType.Half => All.HalfFloat,
|
||||||
|
VertexAttributeType.Float => All.Float,
|
||||||
|
VertexAttributeType.Double => All.Double,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
public VertexAttribType VertexAttribType => (VertexAttribType)type.OpenGL;
|
||||||
|
public VertexAttribPointerType VertexAttribPointerType => (VertexAttribPointerType)type.OpenGL;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(TextureType type)
|
||||||
|
{
|
||||||
|
public TextureTarget OpenGL => type switch
|
||||||
|
{
|
||||||
|
TextureType.Texture1D => TextureTarget.Texture1D,
|
||||||
|
TextureType.Texture2D => TextureTarget.Texture2D,
|
||||||
|
TextureType.Texture2DArray => TextureTarget.Texture2DArray,
|
||||||
|
TextureType.Texture2DCube => TextureTarget.TextureCubeMap,
|
||||||
|
TextureType.Texture3D => TextureTarget.Texture3D,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(BlendEquation eq)
|
||||||
|
{
|
||||||
|
public BlendEquationMode OpenGL => eq switch
|
||||||
|
{
|
||||||
|
BlendEquation.Add => BlendEquationMode.FuncAdd,
|
||||||
|
BlendEquation.Subtract => BlendEquationMode.FuncSubtract,
|
||||||
|
BlendEquation.Max => BlendEquationMode.Max,
|
||||||
|
BlendEquation.Min => BlendEquationMode.Min,
|
||||||
|
BlendEquation.ReverseSubtract => BlendEquationMode.FuncReverseSubtract,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(BlendFunction mode)
|
||||||
|
{
|
||||||
|
public BlendingFactor OpenGL => mode switch
|
||||||
|
{
|
||||||
|
BlendFunction.One => BlendingFactor.One,
|
||||||
|
BlendFunction.Zero => BlendingFactor.Zero,
|
||||||
|
BlendFunction.SourceAlpha => BlendingFactor.SrcAlpha,
|
||||||
|
BlendFunction.OneMinusSourceAlpha => BlendingFactor.OneMinusSrcAlpha,
|
||||||
|
BlendFunction.DestinationAlpha => BlendingFactor.DstAlpha,
|
||||||
|
BlendFunction.OneMinusDestinationAlpha => BlendingFactor.OneMinusDstAlpha,
|
||||||
|
BlendFunction.SourceColor => BlendingFactor.SrcColor,
|
||||||
|
BlendFunction.OneMinusSourceColor => BlendingFactor.OneMinusSrcColor,
|
||||||
|
BlendFunction.DestinationColor => BlendingFactor.DstColor,
|
||||||
|
BlendFunction.OneMinusDestinationColor => BlendingFactor.OneMinusDstColor,
|
||||||
|
BlendFunction.ConstantColor => BlendingFactor.OneMinusConstantColor,
|
||||||
|
BlendFunction.OneMinusConstantColor => BlendingFactor.OneMinusConstantColor,
|
||||||
|
BlendFunction.ConstantAlpha => BlendingFactor.OneMinusConstantAlpha,
|
||||||
|
BlendFunction.OneMinusConstantAlpha => BlendingFactor.OneMinusConstantAlpha,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(TestFunction test)
|
||||||
|
{
|
||||||
|
public All OpenGL => test switch
|
||||||
|
{
|
||||||
|
TestFunction.Always => All.Always,
|
||||||
|
TestFunction.Equal => All.Equal,
|
||||||
|
TestFunction.Greater => All.Greater,
|
||||||
|
TestFunction.GreaterThanOrEqual => All.Gequal,
|
||||||
|
TestFunction.LessThan => All.Less,
|
||||||
|
TestFunction.LessThanOrEqual => All.Lequal,
|
||||||
|
TestFunction.Never => All.Never,
|
||||||
|
TestFunction.NotEqual => All.Notequal,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
|
||||||
|
public DepthFunction DepthFunction => (DepthFunction)test.OpenGL;
|
||||||
|
public StencilFunction StencilFunction => (StencilFunction)test.OpenGL;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(StencilOperation op)
|
||||||
|
{
|
||||||
|
public StencilOp OpenGL => op switch
|
||||||
|
{
|
||||||
|
StencilOperation.Keep => StencilOp.Keep,
|
||||||
|
StencilOperation.Zero => StencilOp.Zero,
|
||||||
|
StencilOperation.Replace => StencilOp.Replace,
|
||||||
|
StencilOperation.Increment => StencilOp.Incr,
|
||||||
|
StencilOperation.UncheckedIncrement => StencilOp.IncrWrap,
|
||||||
|
StencilOperation.Decrement => StencilOp.Decr,
|
||||||
|
StencilOperation.UncheckedDecrement => StencilOp.DecrWrap,
|
||||||
|
StencilOperation.Invert => StencilOp.Invert,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(MeshPrimitive primitive)
|
||||||
|
{
|
||||||
|
public PrimitiveType OpenGL => primitive switch
|
||||||
|
{
|
||||||
|
MeshPrimitive.Line => PrimitiveType.Lines,
|
||||||
|
MeshPrimitive.Point => PrimitiveType.Points,
|
||||||
|
MeshPrimitive.Triangle => PrimitiveType.Triangles,
|
||||||
|
MeshPrimitive.TriangleFan => PrimitiveType.TriangleFan,
|
||||||
|
MeshPrimitive.TriangleStrip => PrimitiveType.TriangleStrip,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(IndexType index)
|
||||||
|
{
|
||||||
|
public DrawElementsType OpenGL => index switch
|
||||||
|
{
|
||||||
|
IndexType.Int or IndexType.UnsignedInt => DrawElementsType.UnsignedInt,
|
||||||
|
IndexType.Short or IndexType.UnsignedShort => DrawElementsType.UnsignedShort,
|
||||||
|
IndexType.UnsignedLong => throw new NotSupportedException(),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(BlendMode mode)
|
||||||
|
{
|
||||||
|
public void SetEnabled()
|
||||||
|
{
|
||||||
|
if (mode.Enabled)
|
||||||
|
GL.Enable(EnableCap.Blend);
|
||||||
|
else
|
||||||
|
GL.Disable(EnableCap.Blend);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMode()
|
||||||
|
{
|
||||||
|
if (mode.IsSeparate)
|
||||||
|
{
|
||||||
|
GL.BlendEquationSeparate(mode.ColorEquation.OpenGL, mode.AlphaEquation.OpenGL);
|
||||||
|
GL.BlendFuncSeparate(
|
||||||
|
mode.Color.Source.OpenGL, mode.Color.Destination.OpenGL,
|
||||||
|
mode.Alpha.Source.OpenGL, mode.Alpha.Destination.OpenGL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.BlendEquation(mode.UnifiedEquation.Value.OpenGL);
|
||||||
|
GL.BlendFunc(mode.Unified.Value.Source.OpenGL, mode.Unified.Value.Destination.OpenGL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetConstant()
|
||||||
|
{
|
||||||
|
GL.BlendColor(mode.Constant.R / 255f, mode.Constant.G / 255f,mode.Constant.B / 255f,mode.Constant.A / 255f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAll()
|
||||||
|
{
|
||||||
|
mode.SetEnabled();
|
||||||
|
mode.SetConstant();
|
||||||
|
mode.SetMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(DepthMode mode)
|
||||||
|
{
|
||||||
|
public void SetEnabled()
|
||||||
|
{
|
||||||
|
if (mode.Test)
|
||||||
|
GL.Enable(EnableCap.DepthTest);
|
||||||
|
else
|
||||||
|
GL.Disable(EnableCap.DepthTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMask() => GL.DepthMask(mode.Mask);
|
||||||
|
|
||||||
|
public void SetFunction() => GL.DepthFunc(mode.Function.DepthFunction);
|
||||||
|
|
||||||
|
public void SetAll()
|
||||||
|
{
|
||||||
|
mode.SetEnabled();
|
||||||
|
mode.SetMask();
|
||||||
|
mode.SetFunction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(StencilMode mode)
|
||||||
|
{
|
||||||
|
public void SetEnabled()
|
||||||
|
{
|
||||||
|
if (mode.Enabled)
|
||||||
|
GL.Enable(EnableCap.StencilTest);
|
||||||
|
else
|
||||||
|
GL.Disable(EnableCap.StencilTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFunction() => GL.StencilFunc(mode.Function.StencilFunction, mode.Reference, (uint)mode.Mask);
|
||||||
|
|
||||||
|
public void SetOperations() => GL.StencilOp(mode.Fail.OpenGL, mode.DepthFail.OpenGL, mode.Pass.OpenGL);
|
||||||
|
|
||||||
|
public void SetAll()
|
||||||
|
{
|
||||||
|
mode.SetEnabled();
|
||||||
|
mode.SetFunction();
|
||||||
|
mode.SetOperations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension(DrawCall call)
|
||||||
|
{
|
||||||
|
public void UsePipeline() => GL.UseProgram((call.ShaderPipeline as GLShader)?.Handle ?? 0);
|
||||||
|
|
||||||
|
// TODO: clamp to viewport size
|
||||||
|
|
||||||
|
public void SetViewport(Vector2 size)
|
||||||
|
{
|
||||||
|
Vector2 min = Vector2.Max(Vector2.Zero, call.ViewportRegion.Min);
|
||||||
|
Vector2 max = Vector2.Min(size, call.ViewportRegion.Max);
|
||||||
|
|
||||||
|
GL.Viewport(
|
||||||
|
(int)Math.Round(min.X),
|
||||||
|
(int)Math.Round(size.Y - max.Y),
|
||||||
|
(int)Math.Round(max.X - min.X),
|
||||||
|
(int)Math.Round(max.Y - min.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetScissor(Vector2 size)
|
||||||
|
{
|
||||||
|
if (call.ScissorRegion == new Box2d(Vector2.PositiveInfinity, Vector2.PositiveInfinity))
|
||||||
|
{
|
||||||
|
GL.Disable(EnableCap.ScissorTest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.Enable(EnableCap.ScissorTest);
|
||||||
|
GL.Scissor(
|
||||||
|
(int)Math.Round(call.ViewportRegion.Left),
|
||||||
|
(int)Math.Round(size.Y - call.ViewportRegion.Top),
|
||||||
|
(int)Math.Round(call.ViewportRegion.Right - call.ViewportRegion.Left),
|
||||||
|
(int)Math.Round(call.ViewportRegion.Bottom - call.ViewportRegion.Top));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetFrontFace()
|
||||||
|
{
|
||||||
|
GL.FrontFace(call.FrontFace switch
|
||||||
|
{
|
||||||
|
WindingOrder.Clockwise => FrontFaceDirection.Cw,
|
||||||
|
WindingOrder.Counterclockwise => FrontFaceDirection.Ccw,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCullMode()
|
||||||
|
{
|
||||||
|
if (call.CullMode == FaceCulling.None)
|
||||||
|
{
|
||||||
|
GL.Disable(EnableCap.CullFace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.Enable(EnableCap.CullFace);
|
||||||
|
|
||||||
|
GL.CullFace(call.CullMode switch
|
||||||
|
{
|
||||||
|
FaceCulling.Both => TriangleFace.FrontAndBack,
|
||||||
|
FaceCulling.Front => TriangleFace.Front,
|
||||||
|
FaceCulling.Back => TriangleFace.Back,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBlendMode() => call.BlendMode.SetAll();
|
||||||
|
public void SetDepthMode() => call.DepthMode.SetAll();
|
||||||
|
public void SetStencilMode() => call.StencilMode.SetAll();
|
||||||
|
|
||||||
|
public void SetPrimitiveRestart()
|
||||||
|
{
|
||||||
|
if (!call.EnableRestart)
|
||||||
|
{
|
||||||
|
GL.Disable(EnableCap.PrimitiveRestart);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.Enable(EnableCap.PrimitiveRestart);
|
||||||
|
GL.PrimitiveRestartIndex((uint)call.RestartIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetColorMask()
|
||||||
|
{
|
||||||
|
GL.ColorMask(call.RedMask, call.GreenMask, call.BlueMask, call.AlphaMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPointSize()
|
||||||
|
{
|
||||||
|
GL.PointSize(call.PointSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLineWidth()
|
||||||
|
{
|
||||||
|
GL.LineWidth(call.LineWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UseTextures()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
foreach (ITexture? texture in call.Textures)
|
||||||
|
{
|
||||||
|
GL.ActiveTexture((TextureUnit)((int)TextureUnit.Texture0 + i));
|
||||||
|
if (texture is GLTexture glTexture)
|
||||||
|
{
|
||||||
|
GL.BindTexture(glTexture.Type.OpenGL, glTexture.Handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateVertexArrays(int vao)
|
||||||
|
{
|
||||||
|
GL.BindVertexArray(vao);
|
||||||
|
|
||||||
|
if (call.ElementBuffer != null)
|
||||||
|
{
|
||||||
|
GL.BindBuffer(BufferTarget.ElementArrayBuffer, (call.ElementBuffer as GLBuffer)?.Handle ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, (call.VertexBuffer as GLBuffer)?.Handle ?? 0);
|
||||||
|
|
||||||
|
foreach(VertexAttribute attrib in call.Attributes)
|
||||||
|
{
|
||||||
|
GL.VertexAttribPointer(
|
||||||
|
(uint)attrib.Location,
|
||||||
|
attrib.Components,
|
||||||
|
attrib.Type.VertexAttribPointerType,
|
||||||
|
false,
|
||||||
|
(int)attrib.Stride,
|
||||||
|
(nint)attrib.Offset);
|
||||||
|
GL.EnableVertexAttribArray((uint)attrib.Location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateUniforms(bool transpose = false)
|
||||||
|
{
|
||||||
|
int bufferIndex = 0;
|
||||||
|
foreach (UniformDescriptor uniform in call.Uniforms)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> uniformData = call.UniformData.Span;
|
||||||
|
|
||||||
|
switch (uniform.Type)
|
||||||
|
{
|
||||||
|
case UniformType.I1:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<int> span = CastSpan<int>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform1i(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.I2:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector2i> span = CastSpan<Vector2i>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform2i(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.I3:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector3i> span = CastSpan<Vector3i>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform3i(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.I4:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector4i> span = CastSpan<Vector4i>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform4i(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.F1:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<float> span = CastSpan<float>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform1f(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.F2:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector2> span = CastSpan<Vector2>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform2f(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.F3:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector3> span = CastSpan<Vector3>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform3f(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.F4:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Vector4> span = CastSpan<Vector4>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.Uniform4f(uniform.Location, span.Length, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.Mat2:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Matrix2> span = CastSpan<Matrix2>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.UniformMatrix2f(uniform.Location, span.Length, transpose, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.Mat3:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Matrix3> span = CastSpan<Matrix3>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.UniformMatrix3f(uniform.Location, span.Length, transpose, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.Mat4:
|
||||||
|
{
|
||||||
|
ReadOnlySpan<Matrix4> span = CastSpan<Matrix4>(uniformData, uniform.Offset, uniform.Size);
|
||||||
|
GL.UniformMatrix4f(uniform.Location, span.Length, transpose, span);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UniformType.Buffer:
|
||||||
|
{
|
||||||
|
int buffer = (call.UniformBuffer as GLBuffer)?.Handle ?? 0;
|
||||||
|
int index = bufferIndex++;
|
||||||
|
GL.BindBufferRange(BufferTarget.UniformBuffer, (uint)index, buffer, (nint)uniform.Offset, (int)uniform.Size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
ReadOnlySpan<T> CastSpan<T>(ReadOnlySpan<byte> bytes, long offset, long size)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
return MemoryMarshal.Cast<byte, T>(bytes.Slice((int)offset, (int)size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAll(Vector2 size, int vao, bool transpose = false)
|
||||||
|
{
|
||||||
|
call.UsePipeline();
|
||||||
|
call.SetViewport(size); call.SetScissor(size);
|
||||||
|
call.SetFrontFace();
|
||||||
|
call.SetCullMode();
|
||||||
|
call.SetBlendMode();
|
||||||
|
call.SetDepthMode();
|
||||||
|
call.SetStencilMode();
|
||||||
|
call.SetPrimitiveRestart();
|
||||||
|
call.SetColorMask();
|
||||||
|
call.SetDepthMode();
|
||||||
|
call.SetPointSize();
|
||||||
|
call.SetLineWidth();
|
||||||
|
call.UseTextures();
|
||||||
|
call.UpdateUniforms(transpose);
|
||||||
|
call.UpdateVertexArrays(vao);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ namespace Dashboard.OpenGL.Drawing
|
|||||||
GL.LinkProgram(program);
|
GL.LinkProgram(program);
|
||||||
GL.GetProgrami(program, ProgramProperty.LinkStatus, out int flag);
|
GL.GetProgrami(program, ProgramProperty.LinkStatus, out int flag);
|
||||||
|
|
||||||
if (flag == 0)
|
if (flag != 0)
|
||||||
return program;
|
return program;
|
||||||
|
|
||||||
GL.GetProgramInfoLog(program, out log);
|
GL.GetProgramInfoLog(program, out log);
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ namespace Dashboard.Controls
|
|||||||
dcb.ResetScissor();
|
dcb.ResetScissor();
|
||||||
dcb.ResetTransforms();
|
dcb.ResetTransforms();
|
||||||
|
|
||||||
|
dcb.ClearDepth();
|
||||||
|
|
||||||
if (Background is SolidColorBrush solidColorBrush)
|
if (Background is SolidColorBrush solidColorBrush)
|
||||||
dcb.ClearColor(solidColorBrush.Color);
|
dcb.ClearColor(solidColorBrush.Color);
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Application app = new Pal2Application(new ToolkitOptions()
|
|||||||
{
|
{
|
||||||
GraphicsApiHints = new OpenGLGraphicsApiHints()
|
GraphicsApiHints = new OpenGLGraphicsApiHints()
|
||||||
{
|
{
|
||||||
Version = new Version(3, 2),
|
Version = new Version(4, 1),
|
||||||
ForwardCompatibleFlag = true,
|
ForwardCompatibleFlag = true,
|
||||||
DebugFlag = true,
|
DebugFlag = true,
|
||||||
Profile = OpenGLProfile.Core,
|
Profile = OpenGLProfile.Core,
|
||||||
@@ -82,9 +82,39 @@ float[] vertices = new float[]
|
|||||||
};
|
};
|
||||||
vertex.Write(0, vertices);
|
vertex.Write(0, vertices);
|
||||||
|
|
||||||
DrawCall call = new DrawCall(MeshPrimitive.Triangle, vertex)
|
IShader shader = direct.CreatePipeline(new GlslShaderCreateInfo()
|
||||||
{
|
{
|
||||||
ShaderPipeline = null,
|
VertexShader =
|
||||||
|
"""
|
||||||
|
#version 410
|
||||||
|
layout (location = 0) in vec3 apos;
|
||||||
|
layout (location = 1) in vec4 acolor;
|
||||||
|
|
||||||
|
out vec4 vcolor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(apos, 1);
|
||||||
|
vcolor = acolor;
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
FragmentShader =
|
||||||
|
"""
|
||||||
|
#version 410
|
||||||
|
in vec4 vcolor;
|
||||||
|
out vec4 fcolor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
fcolor = vcolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
""",
|
||||||
|
});
|
||||||
|
|
||||||
|
DrawCall call = new DrawCall(MeshPrimitive.Triangle, vertex, 0, 3)
|
||||||
|
{
|
||||||
|
ShaderPipeline = shader,
|
||||||
Attributes =
|
Attributes =
|
||||||
[
|
[
|
||||||
new VertexAttribute(0, 3, VertexAttributeType.Float, 0, 8 * sizeof(float)),
|
new VertexAttribute(0, 3, VertexAttributeType.Float, 0, 8 * sizeof(float)),
|
||||||
|
|||||||
Reference in New Issue
Block a user