Create custom OpenGL bindings.
This removes the hard dependency on OpenTK for a core component of QUIK. Although not all environments are going to be using OpenGL, having it be independent from a vendor library would be more benefitial for more people.
This commit is contained in:
parent
b57677a6c2
commit
a50650e54a
@ -1,7 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using OpenTK.Graphics.OpenGL4;
|
using Quik.OpenGL;
|
||||||
|
using static Quik.OpenGL.GLEnum;
|
||||||
|
|
||||||
namespace Quik.OpenTK
|
namespace Quik.OpenTK
|
||||||
{
|
{
|
||||||
@ -17,8 +18,8 @@ namespace Quik.OpenTK
|
|||||||
int vs;
|
int vs;
|
||||||
int fs;
|
int fs;
|
||||||
|
|
||||||
vs = GL.CreateShader(ShaderType.VertexShader);
|
vs = GL.CreateShader(GL_VERTEX_SHADER);
|
||||||
fs = GL.CreateShader(ShaderType.FragmentShader);
|
fs = GL.CreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
_sp = GL.CreateProgram();
|
_sp = GL.CreateProgram();
|
||||||
|
|
||||||
@ -31,13 +32,13 @@ namespace Quik.OpenTK
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
GL.GetShader(vs, ShaderParameter.CompileStatus, out status);
|
GL.GetShader(vs, GL_COMPILE_STATUS, out status);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
throw new Exception(GL.GetShaderInfoLog(vs));
|
throw new Exception(GL.GetShaderInfoLog(vs));
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.GetShader(fs, ShaderParameter.CompileStatus, out status);
|
GL.GetShader(fs, GL_COMPILE_STATUS, out status);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
throw new Exception(GL.GetShaderInfoLog(fs));
|
throw new Exception(GL.GetShaderInfoLog(fs));
|
||||||
@ -50,7 +51,7 @@ namespace Quik.OpenTK
|
|||||||
GL.LinkProgram(_sp);
|
GL.LinkProgram(_sp);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
GL.GetProgram(_sp, GetProgramParameterName.LinkStatus, out status);
|
GL.GetProgram(_sp, GL_LINK_STATUS, out status);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
{
|
{
|
||||||
throw new Exception(GL.GetProgramInfoLog(_sp));
|
throw new Exception(GL.GetProgramInfoLog(_sp));
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using OpenTK.Graphics.OpenGL4;
|
using Quik.OpenGL;
|
||||||
|
using static Quik.OpenGL.GLEnum;
|
||||||
|
|
||||||
namespace Quik.OpenTK
|
namespace Quik.OpenTK
|
||||||
{
|
{
|
||||||
@ -21,20 +22,17 @@ namespace Quik.OpenTK
|
|||||||
|
|
||||||
TextureId = GL.GenTexture();
|
TextureId = GL.GenTexture();
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, TextureId);
|
GL.BindTexture(GL_TEXTURE_2D, TextureId);
|
||||||
|
|
||||||
GL.TexParameter(
|
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mipmaps ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR));
|
||||||
TextureTarget.Texture2D,
|
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
TextureParameterName.TextureMinFilter,
|
|
||||||
(int) (mipmaps ? TextureMinFilter.LinearMipmapNearest : TextureMinFilter.Linear));
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
||||||
|
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
TextureTarget.Texture2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
(PixelInternalFormat)GetGlImageFormat(format),
|
GetGlImageFormat(format),
|
||||||
Width, Height, 0,
|
Width, Height, 0,
|
||||||
PixelFormat.Rgba, PixelType.UnsignedByte,
|
GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,18 +63,18 @@ namespace Quik.OpenTK
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level, int alignment = 4)
|
public override void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level, int alignment = 4)
|
||||||
{
|
{
|
||||||
GL.BindTexture(TextureTarget.Texture2D, TextureId);
|
GL.BindTexture(GL_TEXTURE_2D, TextureId);
|
||||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, alignment);
|
GL.PixelStore(GL_UNPACK_ALIGNMENT, alignment);
|
||||||
GL.TexSubImage2D(TextureTarget.Texture2D, level, 0, 0, Width, Height, GetGlImageFormat(format), GetGlDataFormat(format), data);
|
GL.TexSubImage2D(GL_TEXTURE_2D, level, 0, 0, Width, Height, GetGlImageFormat(format), GetGlDataFormat(format), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level, int alignment = 4)
|
public override void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level, int alignment = 4)
|
||||||
{
|
{
|
||||||
GL.BindTexture(TextureTarget.Texture2D, TextureId);
|
GL.BindTexture(GL_TEXTURE_2D, TextureId);
|
||||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, alignment);
|
GL.PixelStore(GL_UNPACK_ALIGNMENT, alignment);
|
||||||
GL.TexSubImage2D(
|
GL.TexSubImage2D(
|
||||||
TextureTarget.Texture2D,
|
GL_TEXTURE_2D,
|
||||||
level,
|
level,
|
||||||
(int)location.Left,
|
(int)location.Left,
|
||||||
(int)location.Bottom,
|
(int)location.Bottom,
|
||||||
@ -90,28 +88,28 @@ namespace Quik.OpenTK
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void GenerateMipMaps()
|
public override void GenerateMipMaps()
|
||||||
{
|
{
|
||||||
GL.BindTexture(TextureTarget.Texture2D, TextureId);
|
GL.BindTexture(GL_TEXTURE_2D, TextureId);
|
||||||
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
GL.GenerateMipmap(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PixelFormat GetGlImageFormat(QuikImageFormat format)
|
private static GLEnum GetGlImageFormat(QuikImageFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case QuikImageFormat.RedF: case QuikImageFormat.RedU8:
|
case QuikImageFormat.RedF: case QuikImageFormat.RedU8:
|
||||||
return PixelFormat.Red;
|
return GL_RED;
|
||||||
case QuikImageFormat.RgbF: case QuikImageFormat.RgbU8:
|
case QuikImageFormat.RgbF: case QuikImageFormat.RgbU8:
|
||||||
return PixelFormat.Rgb;
|
return GL_RGB;
|
||||||
case QuikImageFormat.RgbaF: case QuikImageFormat.RgbaU8:
|
case QuikImageFormat.RgbaF: case QuikImageFormat.RgbaU8:
|
||||||
return PixelFormat.Rgba;
|
return GL_RGBA;
|
||||||
case QuikImageFormat.AlphaF: case QuikImageFormat.AlphaU8:
|
case QuikImageFormat.AlphaF: case QuikImageFormat.AlphaU8:
|
||||||
return PixelFormat.Alpha;
|
return GL_ALPHA;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PixelType GetGlDataFormat(QuikImageFormat format)
|
private static GLEnum GetGlDataFormat(QuikImageFormat format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
@ -119,12 +117,12 @@ namespace Quik.OpenTK
|
|||||||
case QuikImageFormat.RgbaF:
|
case QuikImageFormat.RgbaF:
|
||||||
case QuikImageFormat.RgbF:
|
case QuikImageFormat.RgbF:
|
||||||
case QuikImageFormat.AlphaF:
|
case QuikImageFormat.AlphaF:
|
||||||
return PixelType.Float;
|
return GL_FLOAT;
|
||||||
case QuikImageFormat.RedU8:
|
case QuikImageFormat.RedU8:
|
||||||
case QuikImageFormat.RgbaU8:
|
case QuikImageFormat.RgbaU8:
|
||||||
case QuikImageFormat.RgbU8:
|
case QuikImageFormat.RgbU8:
|
||||||
case QuikImageFormat.AlphaU8:
|
case QuikImageFormat.AlphaU8:
|
||||||
return PixelType.UnsignedByte;
|
return GL_UNSIGNED_BYTE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException();
|
throw new ArgumentOutOfRangeException();
|
||||||
|
77
Quik/OpenGL/GL.Buffer.cs
Normal file
77
Quik/OpenGL/GL.Buffer.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate void BufferDataProc(GLEnum target, int size, void* data, GLEnum usageHint);
|
||||||
|
|
||||||
|
private static GenObjectsProc _genBuffers;
|
||||||
|
private static GenObjectsProc _deleteBuffers;
|
||||||
|
private static BindSlottedProc _bindBuffer;
|
||||||
|
private static BufferDataProc _bufferData;
|
||||||
|
|
||||||
|
private static void LoadBuffer()
|
||||||
|
{
|
||||||
|
_genBuffers = GetProcAddress<GenObjectsProc>("glGenBuffers");
|
||||||
|
_deleteBuffers = GetProcAddress<GenObjectsProc>("glDeleteBuffers");
|
||||||
|
_bindBuffer = GetProcAddress<BindSlottedProc>("glBindBuffer");
|
||||||
|
_bufferData = GetProcAddress<BufferDataProc>("glBufferData");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenBuffers(int count, out int buffers)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &buffers)
|
||||||
|
_genBuffers(count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenBuffers(int[] buffers) => GenBuffers(buffers.Length, out buffers[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int GenBuffer()
|
||||||
|
{
|
||||||
|
GenBuffers(1, out int i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteBuffers(int count, ref int buffers)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &buffers)
|
||||||
|
_deleteBuffers(count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteBuffers(int[] buffers) => DeleteBuffers(buffers.Length, ref buffers[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteBuffer(int buffer) => DeleteBuffers(1, ref buffer);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BindBuffer(GLEnum target, int buffer)
|
||||||
|
{
|
||||||
|
_bindBuffer(target, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BufferData(GLEnum target, int size, IntPtr data, GLEnum usageHint) =>
|
||||||
|
_bufferData(target, size, (void*)data, usageHint);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BufferData<T>(GLEnum target, int size, ref T data, GLEnum usageHint)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
fixed (T* ptr = &data)
|
||||||
|
_bufferData(target, size, ptr, usageHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BufferData<T>(GLEnum target, int size, T[] data, GLEnum usageHint)
|
||||||
|
where T : unmanaged =>
|
||||||
|
BufferData(target, size, ref data[0], usageHint);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
96
Quik/OpenGL/GL.Program.cs
Normal file
96
Quik/OpenGL/GL.Program.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using static Quik.OpenGL.GLEnum;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate int CreateProgramProc();
|
||||||
|
private delegate void UseProgramProc(int program);
|
||||||
|
private delegate void AttachShaderProc(int program, int shader);
|
||||||
|
private delegate void DetachShaderProc(int program, int shader);
|
||||||
|
private delegate void LinkProgramProc(int program);
|
||||||
|
private delegate void GetProgramProc(int program, GLEnum pname, int *value);
|
||||||
|
private delegate void GetProgramInfoLogProc(int program, int maxLength, int * length, byte *infoLog);
|
||||||
|
private delegate void DeleteProgramProc(int program);
|
||||||
|
private delegate int GetShaderLocationProc(int program, byte *name);
|
||||||
|
|
||||||
|
private static CreateProgramProc _createProgram;
|
||||||
|
private static UseProgramProc _useProgram;
|
||||||
|
private static AttachShaderProc _attachShader;
|
||||||
|
private static DetachShaderProc _detachShader;
|
||||||
|
private static LinkProgramProc _linkProgram;
|
||||||
|
private static GetProgramProc _getProgram;
|
||||||
|
private static GetProgramInfoLogProc _getProgramInfoLog;
|
||||||
|
private static DeleteProgramProc _deleteProgram;
|
||||||
|
private static GetShaderLocationProc _getUniformLocation;
|
||||||
|
private static GetShaderLocationProc _getAttribLocation;
|
||||||
|
|
||||||
|
private static void LoadProgram()
|
||||||
|
{
|
||||||
|
_createProgram = GetProcAddress<CreateProgramProc>("glCreateProgram");
|
||||||
|
_useProgram = GetProcAddress<UseProgramProc>("glUseProgram");
|
||||||
|
_attachShader = GetProcAddress<AttachShaderProc>("glAttachShader");
|
||||||
|
_detachShader = GetProcAddress<DetachShaderProc>("glDetachShader");
|
||||||
|
_linkProgram = GetProcAddress<LinkProgramProc>("glLinkProgram");
|
||||||
|
_getProgram = GetProcAddress<GetProgramProc>("glGetProgramiv");
|
||||||
|
_getProgramInfoLog = GetProcAddress<GetProgramInfoLogProc>("glGetProgramInfoLog");
|
||||||
|
_deleteProgram = GetProcAddress<DeleteProgramProc>("glDeleteProgram");
|
||||||
|
_getUniformLocation = GetProcAddress<GetShaderLocationProc>("glGetUniformLocation");
|
||||||
|
_getAttribLocation = GetProcAddress<GetShaderLocationProc>("glGetAttribLocation");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int CreateProgram() => _createProgram();
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UseProgram(int program) => _useProgram(program);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void AttachShader(int program, int shader) => _attachShader(program, shader);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DetachShader(int program, int shader) => _detachShader(program, shader);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void LinkProgram(int program) => _linkProgram(program);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GetProgram(int program, GLEnum pname, out int value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
fixed (int* ptr = &value)
|
||||||
|
_getProgram(program, pname, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static string GetProgramInfoLog(int program)
|
||||||
|
{
|
||||||
|
GetProgram(program, GL_INFO_LOG_LENGTH, out int length);
|
||||||
|
byte[] infoLog = new byte[length];
|
||||||
|
|
||||||
|
fixed (byte *ptr = infoLog)
|
||||||
|
_getProgramInfoLog(program, length, &length, ptr);
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteProgram(int program) => _deleteProgram(program);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int GetUniformLocation(int program, string name)
|
||||||
|
{
|
||||||
|
fixed(byte* ptr = Encoding.UTF8.GetBytes(name))
|
||||||
|
return _getUniformLocation(program, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int GetAttribLocation(int program, string name)
|
||||||
|
{
|
||||||
|
fixed(byte* ptr = Encoding.UTF8.GetBytes(name))
|
||||||
|
return _getAttribLocation(program, ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
Quik/OpenGL/GL.Shader.cs
Normal file
110
Quik/OpenGL/GL.Shader.cs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using static Quik.OpenGL.GLEnum;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate int CreateShaderProc(GLEnum type);
|
||||||
|
private delegate void ShaderSourceProc(int shader, int count, byte** strings, int* length);
|
||||||
|
private delegate void CompileShaderProc(int shader);
|
||||||
|
private delegate void GetShaderProc(int shader, GLEnum pname, int* value);
|
||||||
|
private delegate void GetShaderInfoLogProc(int shader, int maxLength, int* length, byte* infoLog);
|
||||||
|
private delegate void DeleteShaderProc(int id);
|
||||||
|
|
||||||
|
private static CreateShaderProc _createShader;
|
||||||
|
private static ShaderSourceProc _shaderSource;
|
||||||
|
private static CompileShaderProc _compileShader;
|
||||||
|
private static GetShaderProc _getShader;
|
||||||
|
private static GetShaderInfoLogProc _getShaderInfoLog;
|
||||||
|
private static DeleteShaderProc _deleteShader;
|
||||||
|
|
||||||
|
private static void LoadShader()
|
||||||
|
{
|
||||||
|
_createShader = GetProcAddress<CreateShaderProc>("glCreateShader");
|
||||||
|
_shaderSource = GetProcAddress<ShaderSourceProc>("glShaderSource");
|
||||||
|
_compileShader = GetProcAddress<CompileShaderProc>("glCompileShader");
|
||||||
|
_getShader = GetProcAddress<GetShaderProc>("glGetShaderiv");
|
||||||
|
_getShaderInfoLog = GetProcAddress<GetShaderInfoLogProc>("glGetShaderInfoLog");
|
||||||
|
_deleteShader = GetProcAddress<DeleteShaderProc>("glDeleteShader");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int CreateShader(GLEnum type) => _createShader(type);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void ShaderSource(int shader, string source)
|
||||||
|
{
|
||||||
|
byte[] sourceUTF8 = Encoding.UTF8.GetBytes(source);
|
||||||
|
int length = sourceUTF8.Length;
|
||||||
|
|
||||||
|
fixed (byte* ptr = &sourceUTF8[0])
|
||||||
|
{
|
||||||
|
_shaderSource(shader, 1, &ptr, &length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void ShaderSource(int shader, string[] sources)
|
||||||
|
{
|
||||||
|
int count = sources.Length;
|
||||||
|
byte*[] pointers = new byte*[count];
|
||||||
|
int[] lengths = new int[count];
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
byte[] decoded = Encoding.UTF8.GetBytes(sources[i]);
|
||||||
|
int length = lengths[i] = decoded.Length;
|
||||||
|
IntPtr memory = Marshal.AllocHGlobal(decoded.Length);
|
||||||
|
|
||||||
|
Marshal.Copy(decoded, 0, memory, length);
|
||||||
|
pointers[i] = (byte*)memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fixed (byte** ptr = &pointers[0])
|
||||||
|
fixed (int * len = &lengths[0])
|
||||||
|
{
|
||||||
|
_shaderSource(shader, count, ptr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal((IntPtr)pointers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void CompileShader(int shader) => _compileShader(shader);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GetShader(int shader, GLEnum pname, out int value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
fixed (int *ptr = &value)
|
||||||
|
_getShader(shader, pname, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static string GetShaderInfoLog(int shader)
|
||||||
|
{
|
||||||
|
GetShader(shader, GL_INFO_LOG_LENGTH, out int length);
|
||||||
|
byte[] infoLog = new byte[length];
|
||||||
|
|
||||||
|
fixed (byte *ptr = infoLog)
|
||||||
|
_getShaderInfoLog(shader, length, &length, ptr);
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(infoLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteShader(int shader) => _deleteShader(shader);
|
||||||
|
}
|
||||||
|
}
|
147
Quik/OpenGL/GL.Texture.cs
Normal file
147
Quik/OpenGL/GL.Texture.cs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate void ActiveTextureProc(GLEnum unit);
|
||||||
|
private delegate void PixelStoreiProc(GLEnum pname, int param);
|
||||||
|
private delegate void PixelStorefProc(GLEnum pname, float param);
|
||||||
|
private delegate void TexImage2DProc(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, void *data);
|
||||||
|
private delegate void TexSubImage2DProc(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, void *data);
|
||||||
|
private delegate void TexParameteriProc(GLEnum target, GLEnum pname, int value);
|
||||||
|
private delegate void TexParameterfProc(GLEnum target, GLEnum pname, float value);
|
||||||
|
private delegate void TexParameterivProc(GLEnum target, GLEnum pname, int* value);
|
||||||
|
private delegate void TexParameterfvProc(GLEnum target, GLEnum pname, float* value);
|
||||||
|
private delegate void GenerateMipmapProc(GLEnum target);
|
||||||
|
|
||||||
|
private static GenObjectsProc _genTextures;
|
||||||
|
private static GenObjectsProc _deleteTextures;
|
||||||
|
private static BindSlottedProc _bindTexture;
|
||||||
|
private static ActiveTextureProc _activeTexture;
|
||||||
|
private static PixelStoreiProc _pixelStorei;
|
||||||
|
private static PixelStorefProc _pixelStoref;
|
||||||
|
private static TexImage2DProc _texImage2D;
|
||||||
|
private static TexSubImage2DProc _texSubImage2D;
|
||||||
|
private static TexParameteriProc _texParameteri;
|
||||||
|
private static TexParameterfProc _texParameterf;
|
||||||
|
private static TexParameterivProc _texParameteriv;
|
||||||
|
private static TexParameterfvProc _texParameterfv;
|
||||||
|
private static GenerateMipmapProc _generateMipmap;
|
||||||
|
|
||||||
|
private static void LoadTexture()
|
||||||
|
{
|
||||||
|
_genTextures = GetProcAddress<GenObjectsProc>("glGenTextures");
|
||||||
|
_deleteTextures = GetProcAddress<GenObjectsProc>("glDeleteTextures");
|
||||||
|
_bindTexture = GetProcAddress<BindSlottedProc>("glBindTexture");
|
||||||
|
_activeTexture = GetProcAddress<ActiveTextureProc>("glActiveTexture");
|
||||||
|
_pixelStorei = GetProcAddress<PixelStoreiProc>("glPixelStorei");
|
||||||
|
_pixelStoref = GetProcAddress<PixelStorefProc>("glPixelStoref");
|
||||||
|
_texImage2D = GetProcAddress<TexImage2DProc>("glTexImage2D");
|
||||||
|
_texSubImage2D = GetProcAddress<TexSubImage2DProc>("glTexSubImage2D");
|
||||||
|
_texParameteri = GetProcAddress<TexParameteriProc>("glTexParameteri");
|
||||||
|
_texParameterf = GetProcAddress<TexParameterfProc>("glTexParameterf");
|
||||||
|
_texParameteriv = GetProcAddress<TexParameterivProc>("glTexParameteriv");
|
||||||
|
_texParameterfv = GetProcAddress<TexParameterfvProc>("glTexParameterfv");
|
||||||
|
_generateMipmap = GetProcAddress<GenerateMipmapProc>("glGenerateMipmap");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenTextures(int count, out int textures)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &textures)
|
||||||
|
_genTextures(count, ptr);
|
||||||
|
}
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int GenTexture()
|
||||||
|
{
|
||||||
|
GenTextures(1, out int i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenTextures(int[] textures) => GenTextures(textures.Length, out textures[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteTextures(int count, in int textures)
|
||||||
|
{
|
||||||
|
fixed (int* ptr = &textures)
|
||||||
|
_deleteTextures(count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteTexture(int i) => DeleteTextures(1, i);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteTextures(int[] textures) => DeleteTextures(textures.Length, in textures[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BindTexture(GLEnum target, int texture) => _bindTexture(target, texture);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void ActiveTexture(GLEnum unit) => _activeTexture(unit);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void PixelStore(GLEnum pname, int value) => _pixelStorei(pname, value);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void PixelStore(GLEnum pname, float value) => _pixelStoref(pname, value);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexImage2D(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, IntPtr data) =>
|
||||||
|
_texImage2D(target, level, internalFormat, width, height, border, format, pixelType, (void*)data);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexImage2d<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, in T data) where T : unmanaged
|
||||||
|
{
|
||||||
|
fixed(T *ptr = &data)
|
||||||
|
_texImage2D(target, level, internalFormat, width, height, border, format, pixelType, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexImage2D<T>(GLEnum target, int level, GLEnum internalFormat, int width, int height, int border, GLEnum format, GLEnum pixelType, T[] data) where T : unmanaged =>
|
||||||
|
TexImage2d<T>(target, level, internalFormat, width, height, border, format, pixelType, in data[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexSubImage2D(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, IntPtr data) =>
|
||||||
|
_texSubImage2D(target, level, x, y, width, height,format, pixelType, (void*)data);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexSubImage2d<T>(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, in T data) where T : unmanaged
|
||||||
|
{
|
||||||
|
fixed(T *ptr = &data)
|
||||||
|
_texSubImage2D(target, level, x, y, width, height, format, pixelType, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexSubImage2D<T>(GLEnum target, int level, int x, int y, int width, int height, GLEnum format, GLEnum pixelType, T[] data) where T : unmanaged =>
|
||||||
|
TexSubImage2d<T>(target, level, x, y, width, height, format, pixelType, in data[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, int value) => _texParameteri(target, pname, value);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, GLEnum value) => _texParameteri(target, pname, (int)value);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, float value) => _texParameterf(target, pname, value);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, ref int values)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &values)
|
||||||
|
_texParameteriv(target, pname, ptr);
|
||||||
|
}
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, int[] values) => TexParameter(target, pname, ref values[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, ref float values)
|
||||||
|
{
|
||||||
|
fixed (float *ptr = &values)
|
||||||
|
_texParameterfv(target, pname, ptr);
|
||||||
|
}
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void TexParameter(GLEnum target, GLEnum pname, float[] values) => TexParameter(target, pname, ref values[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenerateMipmap(GLEnum target) => _generateMipmap(target);
|
||||||
|
}
|
||||||
|
}
|
208
Quik/OpenGL/GL.Uniform.cs
Normal file
208
Quik/OpenGL/GL.Uniform.cs
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate void Uniform1fProc(int location, float x);
|
||||||
|
private delegate void Uniform2fProc(int location, float x, float y);
|
||||||
|
private delegate void Uniform3fProc(int location, float x, float y, float z);
|
||||||
|
private delegate void Uniform4fProc(int location, float x, float y, float z, float w);
|
||||||
|
private delegate void Uniform1iProc(int location, int x);
|
||||||
|
private delegate void Uniform2iProc(int location, int x, int y);
|
||||||
|
private delegate void Uniform3iProc(int location, int x, int y, int z);
|
||||||
|
private delegate void Uniform4iProc(int location, int x, int y, int z, int w);
|
||||||
|
private delegate void UniformNfvProc(int location, int count, float* value);
|
||||||
|
private delegate void UniformNivProc(int location, int count, int* value);
|
||||||
|
private delegate void UniformMatrixNxNfvProc(int location, int count, bool transpose, float *value);
|
||||||
|
|
||||||
|
private static Uniform1fProc _uniform1f;
|
||||||
|
private static Uniform2fProc _uniform2f;
|
||||||
|
private static Uniform3fProc _uniform3f;
|
||||||
|
private static Uniform4fProc _uniform4f;
|
||||||
|
private static Uniform1iProc _uniform1i;
|
||||||
|
private static Uniform2iProc _uniform2i;
|
||||||
|
private static Uniform3iProc _uniform3i;
|
||||||
|
private static Uniform4iProc _uniform4i;
|
||||||
|
private static UniformNfvProc _uniform1fv;
|
||||||
|
private static UniformNfvProc _uniform2fv;
|
||||||
|
private static UniformNfvProc _uniform3fv;
|
||||||
|
private static UniformNfvProc _uniform4fv;
|
||||||
|
private static UniformNivProc _uniform1iv;
|
||||||
|
private static UniformNivProc _uniform2iv;
|
||||||
|
private static UniformNivProc _uniform3iv;
|
||||||
|
private static UniformNivProc _uniform4iv;
|
||||||
|
private static UniformMatrixNxNfvProc _uniformMatrix2fv;
|
||||||
|
private static UniformMatrixNxNfvProc _uniformMatrix3fv;
|
||||||
|
private static UniformMatrixNxNfvProc _uniformMatrix4fv;
|
||||||
|
|
||||||
|
public static void LoadUniform()
|
||||||
|
{
|
||||||
|
_uniform1f = GetProcAddress<Uniform1fProc>("glUniform1f");
|
||||||
|
_uniform2f = GetProcAddress<Uniform2fProc>("glUniform2f");
|
||||||
|
_uniform3f = GetProcAddress<Uniform3fProc>("glUniform3f");
|
||||||
|
_uniform4f = GetProcAddress<Uniform4fProc>("glUniform4f");
|
||||||
|
_uniform1i = GetProcAddress<Uniform1iProc>("glUniform1i");
|
||||||
|
_uniform2i = GetProcAddress<Uniform2iProc>("glUniform2i");
|
||||||
|
_uniform3i = GetProcAddress<Uniform3iProc>("glUniform3i");
|
||||||
|
_uniform4i = GetProcAddress<Uniform4iProc>("glUniform4i");
|
||||||
|
_uniform1fv = GetProcAddress<UniformNfvProc>("glUniform1fv");
|
||||||
|
_uniform2fv = GetProcAddress<UniformNfvProc>("glUniform2fv");
|
||||||
|
_uniform3fv = GetProcAddress<UniformNfvProc>("glUniform3fv");
|
||||||
|
_uniform4fv = GetProcAddress<UniformNfvProc>("glUniform4fv");
|
||||||
|
_uniform1iv = GetProcAddress<UniformNivProc>("glUniform1iv");
|
||||||
|
_uniform2iv = GetProcAddress<UniformNivProc>("glUniform2iv");
|
||||||
|
_uniform3iv = GetProcAddress<UniformNivProc>("glUniform3iv");
|
||||||
|
_uniform4iv = GetProcAddress<UniformNivProc>("glUniform4iv");
|
||||||
|
_uniformMatrix2fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix2fv");
|
||||||
|
_uniformMatrix3fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix3fv");
|
||||||
|
_uniformMatrix4fv = GetProcAddress<UniformMatrixNxNfvProc>("glUniformMatrix4fv");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform1(int location, float x)
|
||||||
|
{
|
||||||
|
_uniform1f(location, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform2(int location, float x, float y)
|
||||||
|
{
|
||||||
|
_uniform2f(location, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform3(int location, float x, float y, float z)
|
||||||
|
{
|
||||||
|
_uniform3f(location, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform4(int location, float x, float y, float z, float w)
|
||||||
|
{
|
||||||
|
_uniform4f(location, x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform1(int location, int x)
|
||||||
|
{
|
||||||
|
_uniform1i(location, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform2(int location, int x, int y)
|
||||||
|
{
|
||||||
|
_uniform2i(location, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform3(int location, int x, int y, int z)
|
||||||
|
{
|
||||||
|
_uniform3i(location, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform4(int location, int x, int y, int z, int w)
|
||||||
|
{
|
||||||
|
_uniform4i(location, x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform1(int location, int count, ref float first)
|
||||||
|
{
|
||||||
|
fixed(float *ptr = &first)
|
||||||
|
_uniform1fv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform2(int location, int count, ref float first)
|
||||||
|
{
|
||||||
|
fixed(float *ptr = &first)
|
||||||
|
_uniform2fv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform3(int location, int count, ref float first)
|
||||||
|
{
|
||||||
|
fixed(float *ptr = &first)
|
||||||
|
_uniform3fv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform4(int location, int count, ref float first)
|
||||||
|
{
|
||||||
|
fixed(float *ptr = &first)
|
||||||
|
_uniform4fv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform1(int location, int count, ref int first)
|
||||||
|
{
|
||||||
|
fixed(int *ptr = &first)
|
||||||
|
_uniform1iv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform2(int location, int count, ref int first)
|
||||||
|
{
|
||||||
|
fixed(int *ptr = &first)
|
||||||
|
_uniform2iv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform3(int location, int count, ref int first)
|
||||||
|
{
|
||||||
|
fixed(int *ptr = &first)
|
||||||
|
_uniform3iv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Uniform4(int location, int count, ref int first)
|
||||||
|
{
|
||||||
|
fixed(int *ptr = &first)
|
||||||
|
_uniform4iv(location, count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix2(int location, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix2fv(location, 1, transpose, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix3(int location, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix3fv(location, 1, transpose, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix4(int location, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix4fv(location, 1, transpose, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix2(int location, int count, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix2fv(location, count, transpose, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix3(int location, int count, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix3fv(location, count, transpose, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void UniformMatrix4(int location, int count, bool transpose, ref float m11)
|
||||||
|
{
|
||||||
|
fixed (float* ptr = &m11)
|
||||||
|
_uniformMatrix4fv(location, count, transpose, ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
Quik/OpenGL/GL.VertexArray.cs
Normal file
78
Quik/OpenGL/GL.VertexArray.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate void EnableVertexAttribArrayProc(int location);
|
||||||
|
private delegate void VertexAttribPointerProc(int location, int size, GLEnum type, bool normalized, int stride, IntPtr offset);
|
||||||
|
private delegate void VertexAttribIPointerProc(int location, int size, GLEnum type, int stride, IntPtr offset);
|
||||||
|
|
||||||
|
private static GenObjectsProc _genVertexArrays;
|
||||||
|
private static GenObjectsProc _deleteVertexArrays;
|
||||||
|
private static BindObjectProc _bindVertexArray;
|
||||||
|
private static EnableVertexAttribArrayProc _enableVertexAttribArray;
|
||||||
|
private static EnableVertexAttribArrayProc _disableVertexAttribArray;
|
||||||
|
private static VertexAttribPointerProc _vertexAttribPointer;
|
||||||
|
private static VertexAttribIPointerProc _vertexAttribIPointer;
|
||||||
|
|
||||||
|
private static void LoadVertexArrays()
|
||||||
|
{
|
||||||
|
_genVertexArrays = GetProcAddress<GenObjectsProc>("glGenVertexArrays");
|
||||||
|
_deleteVertexArrays = GetProcAddress<GenObjectsProc>("glDeleteVertexArrays");
|
||||||
|
_bindVertexArray = GetProcAddress<BindObjectProc>("glBindVertexArray");
|
||||||
|
_enableVertexAttribArray = GetProcAddress<EnableVertexAttribArrayProc>("glEnableVertexAttribArray");
|
||||||
|
_disableVertexAttribArray = GetProcAddress<EnableVertexAttribArrayProc>("glDisableVertexAttribArray");
|
||||||
|
_vertexAttribPointer = GetProcAddress<VertexAttribPointerProc>("glVertexAttribPointer");
|
||||||
|
_vertexAttribIPointer = GetProcAddress<VertexAttribIPointerProc>("glVertexAttribIPointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenVertexArrays(int count, out int vertexArrays)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &vertexArrays)
|
||||||
|
_genVertexArrays(count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static int GenVertexArray()
|
||||||
|
{
|
||||||
|
GenVertexArrays(1, out int i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void GenVertexArrays(int[] vertexArrays) => GenVertexArrays(vertexArrays.Length, out vertexArrays[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteVertexArrays(int count, ref int vertexArrays)
|
||||||
|
{
|
||||||
|
fixed (int *ptr = &vertexArrays)
|
||||||
|
_deleteVertexArrays(count, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteVertexArrays(int[] vertexArrays) => DeleteVertexArrays(vertexArrays.Length, ref vertexArrays[0]);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DeleteVertexArray(int vertexArray) => DeleteVertexArrays(1, ref vertexArray);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BindVertexArray(int vertexArray) => _bindVertexArray(vertexArray);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void EnableVertexAttribArray(int location) => _enableVertexAttribArray(location);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DisableVertexAttribArray(int location) => _disableVertexAttribArray(location);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void VertexAttribPointer(int location, int size, GLEnum type, bool normalized, int stride, int offset) =>
|
||||||
|
_vertexAttribPointer(location, size, type, normalized, stride, (IntPtr)offset);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void VertexAttibIPointer(int location, int size, GLEnum type, int stride, int offset) =>
|
||||||
|
_vertexAttribIPointer(location, size, type, stride, (IntPtr)offset);
|
||||||
|
}
|
||||||
|
}
|
83
Quik/OpenGL/GL.cs
Normal file
83
Quik/OpenGL/GL.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public delegate IntPtr GetProcAddressProc(string procName);
|
||||||
|
|
||||||
|
public unsafe static partial class GL
|
||||||
|
{
|
||||||
|
private delegate void GenObjectsProc(int count, int *ids);
|
||||||
|
private delegate void BindObjectProc(int id);
|
||||||
|
private delegate void BindSlottedProc(GLEnum target, int id);
|
||||||
|
private delegate void GLEnum1Proc(GLEnum x);
|
||||||
|
private delegate void GLEnum2Proc(GLEnum x, GLEnum y);
|
||||||
|
private delegate void GLI4Proc(int x, int y, int z, int w);
|
||||||
|
private delegate void GLF4Proc(float x, float y, float z, float w);
|
||||||
|
private delegate void DrawElementsProc(GLEnum primitive, int size, GLEnum type, void *offset);
|
||||||
|
private delegate void DrawArraysProc(GLEnum primitive, int size, void *offset);
|
||||||
|
|
||||||
|
private const short AggressiveInlining = (short)MethodImplOptions.AggressiveInlining;
|
||||||
|
private static GetProcAddressProc _getProcAddress;
|
||||||
|
private static GLEnum1Proc _enable;
|
||||||
|
private static GLEnum1Proc _disable;
|
||||||
|
private static GLEnum2Proc _blendFunc;
|
||||||
|
private static GLEnum1Proc _depthFunc;
|
||||||
|
private static GLEnum1Proc _clear;
|
||||||
|
private static GLI4Proc _viewport;
|
||||||
|
private static GLF4Proc _clearColor;
|
||||||
|
private static DrawElementsProc _drawElements;
|
||||||
|
private static DrawArraysProc _drawArrays;
|
||||||
|
|
||||||
|
private static T GetProcAddress<T>(string procName)
|
||||||
|
where T : Delegate
|
||||||
|
{
|
||||||
|
IntPtr funcptr = _getProcAddress(procName);
|
||||||
|
return Marshal.GetDelegateForFunctionPointer<T>(funcptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoadBindings(GetProcAddressProc getProcAddress)
|
||||||
|
{
|
||||||
|
_getProcAddress = getProcAddress;
|
||||||
|
|
||||||
|
_enable = GetProcAddress<GLEnum1Proc>("glEnable");
|
||||||
|
_disable = GetProcAddress<GLEnum1Proc>("glDisable");
|
||||||
|
_blendFunc = GetProcAddress<GLEnum2Proc>("glBlendFunc");
|
||||||
|
_depthFunc = GetProcAddress<GLEnum1Proc>("glDepthFunc");
|
||||||
|
_clear = GetProcAddress<GLEnum1Proc>("glClear");
|
||||||
|
_viewport = GetProcAddress<GLI4Proc>("glViewport");
|
||||||
|
_clearColor = GetProcAddress<GLF4Proc>("glClearColor");
|
||||||
|
_drawElements = GetProcAddress<DrawElementsProc>("glDrawElements");
|
||||||
|
_drawArrays = GetProcAddress<DrawArraysProc>("glDrawArrays");
|
||||||
|
|
||||||
|
LoadBuffer();
|
||||||
|
LoadProgram();
|
||||||
|
LoadShader();
|
||||||
|
LoadTexture();
|
||||||
|
LoadUniform();
|
||||||
|
LoadVertexArrays();
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Enable(GLEnum cap) => _enable(cap);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Disable(GLEnum cap) => _disable(cap);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void BlendFunc(GLEnum src, GLEnum dst) => _blendFunc(src, dst);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DepthFunc(GLEnum func) => _depthFunc(func);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Clear(GLEnum buffer_bits) => _clear(buffer_bits);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void Viewport(int x, int y, int w, int h) => _viewport(x, y, w, h);
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void ClearColor(float r, float g, float b, float a) => _clearColor(r, g, b, a);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DrawElements(GLEnum primitive, int count, GLEnum type, int offset) => _drawElements(primitive, count, type, (void*)offset);
|
||||||
|
|
||||||
|
[MethodImpl(AggressiveInlining)]
|
||||||
|
public static void DrawArrays(GLEnum primitive, int count, int offset) => _drawArrays(primitive, count, (void*)offset);
|
||||||
|
}
|
||||||
|
}
|
56
Quik/OpenGL/GLEnum.cs
Normal file
56
Quik/OpenGL/GLEnum.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
namespace Quik.OpenGL
|
||||||
|
{
|
||||||
|
public enum GLEnum : int
|
||||||
|
{
|
||||||
|
GL_MULTISAMPLE = 0x809D,
|
||||||
|
GL_BLEND = 0x0BE2,
|
||||||
|
|
||||||
|
GL_COLOR_BUFFER_BIT = 0x00004000,
|
||||||
|
|
||||||
|
GL_SRC_ALPHA = 0x0302,
|
||||||
|
GL_ONE_MINUS_SRC_ALPHA = 0x0303,
|
||||||
|
|
||||||
|
GL_VERTEX_SHADER = 0x8B31,
|
||||||
|
GL_FRAGMENT_SHADER = 0x8B30,
|
||||||
|
GL_INFO_LOG_LENGTH = 0x8B84,
|
||||||
|
GL_COMPILE_STATUS = 0x8B81,
|
||||||
|
GL_LINK_STATUS = 0x8B82,
|
||||||
|
|
||||||
|
GL_UNSIGNED_BYTE = 0x1401,
|
||||||
|
GL_UNSIGNED_SHORT = 0x1403,
|
||||||
|
GL_FLOAT = 0x1406,
|
||||||
|
|
||||||
|
GL_RED = 0x1903,
|
||||||
|
GL_ALPHA = 0x1906,
|
||||||
|
GL_RGB = 0x1907,
|
||||||
|
GL_RGBA = 0x1908,
|
||||||
|
|
||||||
|
GL_ARRAY_BUFFER = 0x8892,
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
|
||||||
|
|
||||||
|
GL_STREAM_DRAW = 0x88E0,
|
||||||
|
|
||||||
|
GL_TEXTURE_2D = 0x0DE1,
|
||||||
|
GL_UNPACK_ALIGNMENT = 0x0CF5,
|
||||||
|
|
||||||
|
GL_TEXTURE_MAG_FILTER = 0x2800,
|
||||||
|
GL_TEXTURE_MIN_FILTER = 0x2801,
|
||||||
|
GL_NEAREST = 0x2600,
|
||||||
|
GL_LINEAR = 0x2601,
|
||||||
|
GL_NEAREST_MIPMAP_NEAREST = 0x2700,
|
||||||
|
GL_LINEAR_MIPMAP_NEAREST = 0x2701,
|
||||||
|
GL_NEAREST_MIPMAP_LINEAR = 0x2702,
|
||||||
|
GL_LINEAR_MIPMAP_LINEAR = 0x2703,
|
||||||
|
|
||||||
|
GL_TEXTURE_WRAP_S = 0x2802,
|
||||||
|
GL_TEXTURE_WRAP_T = 0x2803,
|
||||||
|
GL_CLAMP_TO_EDGE = 0x812F,
|
||||||
|
GL_CLAMP_TO_BORDER = 0x812D,
|
||||||
|
GL_MIRRORED_REPEAT = 0x8370,
|
||||||
|
GL_MIRROR_CLAMP_TO_EDGE = 0x8743,
|
||||||
|
GL_CLAMP = 0x2900,
|
||||||
|
GL_REPEAT = 0x2901,
|
||||||
|
|
||||||
|
GL_TRIANGLES = 0x0004,
|
||||||
|
}
|
||||||
|
}
|
@ -3,8 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Quik;
|
using Quik;
|
||||||
using Quik.VertexGenerator;
|
using Quik.VertexGenerator;
|
||||||
using OpenTK.Graphics.OpenGL4;
|
|
||||||
using OpenTK.Mathematics;
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
using OpenTK.Windowing.Common;
|
using OpenTK.Windowing.Common;
|
||||||
using OpenTK.Windowing.Desktop;
|
using OpenTK.Windowing.Desktop;
|
||||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
@ -12,6 +12,9 @@ using Quik.FreeType;
|
|||||||
using Quik.OpenTK;
|
using Quik.OpenTK;
|
||||||
using Quik.Typography;
|
using Quik.Typography;
|
||||||
using Quik.Controls;
|
using Quik.Controls;
|
||||||
|
using Quik.OpenGL;
|
||||||
|
using GL = Quik.OpenGL.GL;
|
||||||
|
using static Quik.OpenGL.GLEnum;
|
||||||
|
|
||||||
namespace QuikTestApplication
|
namespace QuikTestApplication
|
||||||
{
|
{
|
||||||
@ -56,7 +59,7 @@ void main()
|
|||||||
NativeWindow window = new NativeWindow(windowSettings);
|
NativeWindow window = new NativeWindow(windowSettings);
|
||||||
|
|
||||||
window.Context.MakeCurrent();
|
window.Context.MakeCurrent();
|
||||||
GL.LoadBindings(new GLFWBindingsContext());
|
GL.LoadBindings(new GLFWBindingsContext().GetProcAddress);
|
||||||
|
|
||||||
FreeTypeFontManager fontManager = new FreeTypeFontManager();
|
FreeTypeFontManager fontManager = new FreeTypeFontManager();
|
||||||
QuikContext context = new QuikContext(new OpenGLTextureManager(), fontManager);
|
QuikContext context = new QuikContext(new OpenGLTextureManager(), fontManager);
|
||||||
@ -93,7 +96,7 @@ void main()
|
|||||||
root.MouseUp += (_,_) => Console.WriteLine("up");
|
root.MouseUp += (_,_) => Console.WriteLine("up");
|
||||||
root.Add(button);
|
root.Add(button);
|
||||||
|
|
||||||
GL.Enable(EnableCap.Multisample);
|
GL.Enable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
int sp;
|
int sp;
|
||||||
{
|
{
|
||||||
@ -101,8 +104,8 @@ void main()
|
|||||||
|
|
||||||
sp = GL.CreateProgram();
|
sp = GL.CreateProgram();
|
||||||
|
|
||||||
vs = GL.CreateShader(ShaderType.VertexShader);
|
vs = GL.CreateShader(GL_VERTEX_SHADER);
|
||||||
fs = GL.CreateShader(ShaderType.FragmentShader);
|
fs = GL.CreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
GL.ShaderSource(vs, vertex);
|
GL.ShaderSource(vs, vertex);
|
||||||
GL.CompileShader(vs);
|
GL.CompileShader(vs);
|
||||||
@ -125,14 +128,14 @@ void main()
|
|||||||
vao = GL.GenVertexArray();
|
vao = GL.GenVertexArray();
|
||||||
GL.BindVertexArray(vao);
|
GL.BindVertexArray(vao);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
|
GL.BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);
|
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
|
||||||
int loc;
|
int loc;
|
||||||
GL.VertexAttribPointer(
|
GL.VertexAttribPointer(
|
||||||
loc = GL.GetAttribLocation(sp, "position"),
|
loc = GL.GetAttribLocation(sp, "position"),
|
||||||
2,
|
2,
|
||||||
VertexAttribPointerType.Float,
|
GL_FLOAT,
|
||||||
false,
|
false,
|
||||||
QuikVertex.Stride,
|
QuikVertex.Stride,
|
||||||
QuikVertex.PositionOffset);
|
QuikVertex.PositionOffset);
|
||||||
@ -140,7 +143,7 @@ void main()
|
|||||||
GL.VertexAttribPointer(
|
GL.VertexAttribPointer(
|
||||||
loc = GL.GetAttribLocation(sp, "texcoord"),
|
loc = GL.GetAttribLocation(sp, "texcoord"),
|
||||||
2,
|
2,
|
||||||
VertexAttribPointerType.Float,
|
GL_FLOAT,
|
||||||
false,
|
false,
|
||||||
QuikVertex.Stride,
|
QuikVertex.Stride,
|
||||||
QuikVertex.TextureCoordinatesOffset);
|
QuikVertex.TextureCoordinatesOffset);
|
||||||
@ -148,7 +151,7 @@ void main()
|
|||||||
GL.VertexAttribPointer(
|
GL.VertexAttribPointer(
|
||||||
loc = GL.GetAttribLocation(sp, "color"),
|
loc = GL.GetAttribLocation(sp, "color"),
|
||||||
4,
|
4,
|
||||||
VertexAttribPointerType.UnsignedByte,
|
GL_UNSIGNED_BYTE,
|
||||||
true,
|
true,
|
||||||
QuikVertex.Stride,
|
QuikVertex.Stride,
|
||||||
QuikVertex.ColorOffset);
|
QuikVertex.ColorOffset);
|
||||||
@ -182,10 +185,10 @@ void main()
|
|||||||
|
|
||||||
int whiteTexture = GL.GenTexture();
|
int whiteTexture = GL.GenTexture();
|
||||||
uint[] whitePixel = {0xFFFFFFFF};
|
uint[] whitePixel = {0xFFFFFFFF};
|
||||||
GL.BindTexture(TextureTarget.Texture2D, whiteTexture);
|
GL.BindTexture(GL_TEXTURE_2D, whiteTexture);
|
||||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 1, 1, 0, PixelFormat.Rgba, PixelType.UnsignedByte, whitePixel);
|
GL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, whitePixel);
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest);
|
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
context.DefaultFont = context.FontManager.GetFont(new QuikFontStyle("Arial", 16, QuikFontType.Normal));
|
context.DefaultFont = context.FontManager.GetFont(new QuikFontStyle("Arial", 16, QuikFontType.Normal));
|
||||||
|
|
||||||
@ -231,9 +234,9 @@ void main()
|
|||||||
GL.Viewport(0, 0, window.Size.X, window.Size.Y);
|
GL.Viewport(0, 0, window.Size.X, window.Size.Y);
|
||||||
|
|
||||||
GL.ClearColor(1,1,1,1);
|
GL.ClearColor(1,1,1,1);
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
GL.Clear(GL_COLOR_BUFFER_BIT);
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(GL_BLEND);
|
||||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
Matrix4 matrix = Matrix4.CreateOrthographicOffCenter(
|
Matrix4 matrix = Matrix4.CreateOrthographicOffCenter(
|
||||||
0,
|
0,
|
||||||
@ -242,7 +245,7 @@ void main()
|
|||||||
(float)window.Size.Y*dpi/72f,
|
(float)window.Size.Y*dpi/72f,
|
||||||
1,
|
1,
|
||||||
-1);
|
-1);
|
||||||
GL.UniformMatrix4(loc, false, ref matrix);
|
GL.UniformMatrix4(loc, false, ref matrix.Row0.X);
|
||||||
|
|
||||||
context.Draw.Commands.Enqueue(
|
context.Draw.Commands.Enqueue(
|
||||||
new QuikCommandRectangle(new QuikRectangle(120, 60, 20, 20))
|
new QuikCommandRectangle(new QuikRectangle(120, 60, 20, 20))
|
||||||
@ -303,21 +306,21 @@ void main()
|
|||||||
gen.ConsumeCommand(command);
|
gen.ConsumeCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, gen.VertexCount * QuikVertex.Stride, ref gen.VertexBuffer[0], BufferUsageHint.StreamDraw);
|
GL.BufferData(GL_ARRAY_BUFFER, gen.VertexCount * QuikVertex.Stride, gen.VertexBuffer, GL_STREAM_DRAW);
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, gen.ElementCount * 2, ref gen.ElementBuffer[0], BufferUsageHint.StreamDraw);
|
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, gen.ElementCount * 2, gen.ElementBuffer, GL_STREAM_DRAW);
|
||||||
|
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(GL_BLEND);
|
||||||
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
|
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
foreach (QuikDrawCall call in gen.DrawCalls)
|
foreach (QuikDrawCall call in gen.DrawCalls)
|
||||||
{
|
{
|
||||||
GL.BindTexture(
|
GL.BindTexture(
|
||||||
TextureTarget.Texture2D,
|
GL_TEXTURE_2D,
|
||||||
call.Texture == null ? whiteTexture : (call.Texture as OpenGLTexture).TextureId);
|
call.Texture == null ? whiteTexture : (call.Texture as OpenGLTexture).TextureId);
|
||||||
if (call.Texture != null)
|
if (call.Texture != null)
|
||||||
GL.Uniform2(offsetLoc, 0.5f / call.Texture.Width, 0.5f / call.Texture.Height);
|
GL.Uniform2(offsetLoc, 0.5f / call.Texture.Width, 0.5f / call.Texture.Height);
|
||||||
GL.DrawElements(BeginMode.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset);
|
GL.DrawElements(GL_TRIANGLES, call.Count, GL_UNSIGNED_SHORT, call.Offset);
|
||||||
}
|
}
|
||||||
GL.Disable(EnableCap.Blend);
|
GL.Disable(GL_BLEND);
|
||||||
|
|
||||||
int callCount = gen.DrawCalls.Count;
|
int callCount = gen.DrawCalls.Count;
|
||||||
gen.Clear();
|
gen.Clear();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
![QUIK](assets/quik.svg) Quick User Interface Kit
|
![QUIK](assets/quik.svg) QUIK: User Interface Kit
|
||||||
===============================
|
=================================================
|
||||||
QUIK is an immediate mode user interface kit intended for embedding in other
|
QUIK is an immediate mode user interface kit intended for embedding in other
|
||||||
C# applications. When rendering UI elements, a command buffer is generated may
|
C# applications. When rendering UI elements, a command buffer is generated may
|
||||||
can be converted to any other rendering commands using built-in or self made
|
can be converted to any other rendering commands using built-in or self made
|
||||||
|
Loading…
Reference in New Issue
Block a user