154 lines
5.9 KiB
C#
154 lines
5.9 KiB
C#
using System.Drawing;
|
|
using static OpenGL.GL;
|
|
|
|
namespace OpenGLTutorial.Rendering.Display {
|
|
public class Shape {
|
|
|
|
public int Mode { get; set; }
|
|
public uint Vao { get; private set; }
|
|
private uint Vbo { get; set; }
|
|
private float[] Vertices { get; set; }
|
|
private bool _loaded = false;
|
|
|
|
public Shape(float[] vertices, int mode = GL_STATIC_DRAW) {
|
|
Vertices = vertices;
|
|
Mode = mode;
|
|
}
|
|
|
|
public unsafe void Load() {
|
|
if (_loaded || Vertices.Length == 0) return;
|
|
_loaded = true;
|
|
|
|
Vao = glGenVertexArray();
|
|
Vbo = glGenBuffer();
|
|
|
|
glBindVertexArray(Vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
|
|
|
|
fixed (float* v = &Vertices[0]) {
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * Vertices.Length, v, Mode);
|
|
}
|
|
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, false, 8 * sizeof(float), (void*)0);
|
|
glEnableVertexAttribArray(0);
|
|
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, false, 8 * sizeof(float), (void*)(2 * sizeof(float)));
|
|
glEnableVertexAttribArray(1);
|
|
|
|
glVertexAttribPointer(2, 2, GL_FLOAT, false, 8 * sizeof(float), (void*)(6 * sizeof(float)));
|
|
glEnableVertexAttribArray(2);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
public void Delete() {
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
glDeleteBuffer(Vbo);
|
|
glDeleteVertexArray(Vao);
|
|
}
|
|
|
|
public unsafe void SetVertices(float[] vertices) {
|
|
Vertices = vertices;
|
|
if (vertices.Length == 0) return;
|
|
glBindVertexArray(Vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, Vbo);
|
|
|
|
fixed (float* v = &Vertices[0]) {
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * Vertices.Length, v, Mode);
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
public int GetVertexCount() => Vertices.Length / 8;
|
|
|
|
}
|
|
|
|
public static class Shapes {
|
|
|
|
public static float[] Rectangle => new[] {
|
|
-0.5f, 0.5f, 1f, 1f, 1f, 1f, 0.0f, 1.0f, // top left
|
|
0.5f, 0.5f, 1f, 1f, 1f, 1f, 1.0f, 1.0f, // top right
|
|
-0.5f, -0.5f, 1f, 1f, 1f, 1f, 0.0f, 0.0f, // bottom left
|
|
|
|
0.5f, 0.5f, 1f, 1f, 1f, 1f, 1.0f, 1.0f, // top right
|
|
0.5f, -0.5f, 1f, 1f, 1f, 1f, 1.0f, 0.0f, // bottom right
|
|
-0.5f, -0.5f, 1f, 1f, 1f, 1f, 0.0f, 0.0f, // bottom left
|
|
};
|
|
|
|
public static float[] Triangle => new[] {
|
|
0.0f, -0.5f, 1f, 1f, 1f, 1f, 0.5f, 1.0f, // top center
|
|
0.5f, 0.5f, 1f, 1f, 1f, 1f, 1.0f, 0.0f, // bottom right
|
|
-0.5f, 0.5f, 1f, 1f, 1f, 1f, 0.0f, 0.0f, // bottom left
|
|
};
|
|
|
|
public static float[] CreateRectangle(Dimensions position, Color color, Dimensions uv) => new[] {
|
|
position.X, position.MaxY, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.X, uv.MaxY, // top left
|
|
position.MaxX, position.MaxY, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.MaxX, uv.MaxY, // top right
|
|
position.X, position.Y, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.X, uv.Y, // bottom left
|
|
|
|
position.MaxX, position.MaxY, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.MaxX, uv.MaxY, // top right
|
|
position.MaxX, position.Y, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.MaxX, uv.Y, // bottom right
|
|
position.X, position.Y, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.X, uv.Y, // bottom left
|
|
};
|
|
|
|
public static float[] CreateTriangle(Dimensions position, Color color, Dimensions uv) => new[] {
|
|
position.CenterX, position.Y, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.CenterX, uv.MaxY, // top center
|
|
position.MaxX, position.MaxY, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.MaxX, uv.Y, // bottom right
|
|
position.X, position.MaxY, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha(), uv.X, uv.Y, // bottom left
|
|
};
|
|
|
|
}
|
|
|
|
public readonly struct Dimensions {
|
|
public static Dimensions Identity => new (0.0f, 0.0f, 1.0f, 1.0f);
|
|
public static Dimensions Centered => new (-0.5f, -0.5f, 1.0f, 1.0f);
|
|
|
|
public float X { get; }
|
|
public float Y { get; }
|
|
public float Width { get; }
|
|
public float Height { get; }
|
|
|
|
public Dimensions(float x, float y, float width, float height) {
|
|
X = x;
|
|
Y = y;
|
|
Width = width;
|
|
Height = height;
|
|
}
|
|
|
|
public float MaxX => X + Width;
|
|
public float MaxY => Y + Height;
|
|
|
|
public float CenterX => X + (Width / 2.0f);
|
|
public float CenterY => Y + (Height / 2.0f);
|
|
}
|
|
|
|
public static class ColorExtensions {
|
|
|
|
private static float Map(float value, float min, float max, float mMin, float mMax) {
|
|
float norm = (value - min) / (max - min);
|
|
return (mMax - mMin) * norm + mMin;
|
|
}
|
|
|
|
public static float GetRed(this Color color) {
|
|
return Map(color.R, 0, 255, 0, 1);
|
|
}
|
|
|
|
public static float GetGreen(this Color color) {
|
|
return Map(color.G, 0, 255, 0, 1);
|
|
}
|
|
|
|
public static float GetBlue(this Color color) {
|
|
return Map(color.B, 0, 255, 0, 1);
|
|
}
|
|
|
|
public static float GetAlpha(this Color color) {
|
|
return Map(color.A, 0, 255, 0, 1);
|
|
}
|
|
|
|
}
|
|
} |