Reflection and deserialization for vertex data
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
namespace hexworld
|
namespace hexworld
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,132 +1,34 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Policy;
|
||||||
using hexworld.Util;
|
using hexworld.Util;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
using OpenTK.Graphics.OpenGL4;
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
|
||||||
namespace hexworld
|
namespace hexworld
|
||||||
{
|
{
|
||||||
public struct Vertex
|
public partial class HexRender : GameWindow
|
||||||
{
|
|
||||||
public Vector3 Position;
|
|
||||||
public Vector2 UV;
|
|
||||||
public Vector3 Normal;
|
|
||||||
|
|
||||||
public Vertex(Vector3 position, Vector2 uv, Vector3 normal)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
UV = uv;
|
|
||||||
Normal = normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct Tile
|
|
||||||
{
|
|
||||||
public Vector3 Position;
|
|
||||||
|
|
||||||
public Tile(Vector3 position)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HexRender : GameWindow
|
|
||||||
{
|
{
|
||||||
private Program pgm;
|
private Program pgm;
|
||||||
|
// todo: generate texture atlas
|
||||||
|
// or at least embed sub-uvs and materials into json
|
||||||
private Texture grass;
|
private Texture grass;
|
||||||
private Texture stone;
|
private Texture stone;
|
||||||
private Texture tex2;
|
|
||||||
|
|
||||||
private Matrix4 view;
|
private Matrix4 view;
|
||||||
private Matrix4 proj;
|
private Matrix4 proj;
|
||||||
|
|
||||||
private VBO tileVbo;
|
private VBO<Tile> tileVbo;
|
||||||
private VBO cubeVbo;
|
private VBO<Vertex> cubeVbo;
|
||||||
|
|
||||||
private readonly Vertex[] cubeVerts =
|
public HexRender(int width, int height)
|
||||||
{
|
: base(width, height, new GraphicsMode(32, 24, 0, 0))
|
||||||
// +X
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(+1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(+1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(+1, +0, +0)),
|
|
||||||
// -X
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(-1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(-1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(-1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(-1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(-1, +0, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(-1, +0, +0)),
|
|
||||||
// +Y
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, +1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(+0, +1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(+0, +1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(+0, +1, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+0, +1, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, +1, +0)),
|
|
||||||
// -Y
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(+0, -1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+0, -1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, -1, +0)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, -1, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, -.5f), new Vector2(1.0f, 0.5f), new Vector3(+0, -1, +0)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, +.5f), new Vector2(1.0f, 0.0f), new Vector3(+0, -1, +0)),
|
|
||||||
// +Z
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, +.5f), new Vector2(0.0f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, +.5f), new Vector2(0.0f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, +.5f), new Vector2(0.0f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, +.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, +.5f), new Vector2(0.5f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
// -Z
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, +0, -1)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, -.5f), new Vector2(0.0f, 0.5f), new Vector3(+0, +0, -1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(0.0f, 1.0f), new Vector3(+0, +0, -1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, -.5f), new Vector2(0.0f, 1.0f), new Vector3(+0, +0, -1)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, -.5f), new Vector2(0.5f, 1.0f), new Vector3(+0, +0, -1)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, -.5f), new Vector2(0.5f, 0.5f), new Vector3(+0, +0, -1)),
|
|
||||||
|
|
||||||
// Plane
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, 0.0f), new Vector2(0.5f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, +.5f, 0.0f), new Vector2(0.0f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, 0.0f), new Vector2(0.0f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(-.5f, -.5f, 0.0f), new Vector2(0.0f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(+.5f, -.5f, 0.0f), new Vector2(0.5f, 0.5f), new Vector3(+0, +0, +1)),
|
|
||||||
new Vertex(new Vector3(+.5f, +.5f, 0.0f), new Vector2(0.5f, 0.0f), new Vector3(+0, +0, +1)),
|
|
||||||
};
|
|
||||||
|
|
||||||
private Tile[] tiles =
|
|
||||||
{
|
|
||||||
// Grass
|
|
||||||
new Tile(new Vector3(-2, -2, 0)),
|
|
||||||
new Tile(new Vector3(-2, -1, 0)),
|
|
||||||
new Tile(new Vector3(-2, +0, 0)),
|
|
||||||
new Tile(new Vector3(-2, +1, 0)),
|
|
||||||
new Tile(new Vector3(-2, +2, 0)),
|
|
||||||
new Tile(new Vector3(+2, -2, 0)),
|
|
||||||
new Tile(new Vector3(+2, -1, 0)),
|
|
||||||
new Tile(new Vector3(+2, +0, 0)),
|
|
||||||
new Tile(new Vector3(+2, +1, 0)),
|
|
||||||
new Tile(new Vector3(+2, +2, 0)),
|
|
||||||
new Tile(new Vector3(-1, -2, 0)),
|
|
||||||
new Tile(new Vector3(-1, +2, 0)),
|
|
||||||
new Tile(new Vector3(+0, -2, 0)),
|
|
||||||
new Tile(new Vector3(+0, +2, 0)),
|
|
||||||
new Tile(new Vector3(+1, -2, 0)),
|
|
||||||
new Tile(new Vector3(+1, +2, 0)),
|
|
||||||
// Stone
|
|
||||||
new Tile(new Vector3(+0, +0, +1)),
|
|
||||||
new Tile(new Vector3(+0, +1, +1)),
|
|
||||||
new Tile(new Vector3(+0, -1, +1)),
|
|
||||||
new Tile(new Vector3(+1, +0, +1)),
|
|
||||||
new Tile(new Vector3(-1, +0, +1)),
|
|
||||||
};
|
|
||||||
|
|
||||||
public HexRender(int width, int height) : base(width, height, new GraphicsMode(32, 32, 0, 0))
|
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = Height;
|
Height = Height;
|
||||||
@@ -134,7 +36,6 @@ namespace hexworld
|
|||||||
Y = (DisplayDevice.Default.Height - Height) / 2;
|
Y = (DisplayDevice.Default.Height - Height) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Random rand = new Random();
|
|
||||||
private double t;
|
private double t;
|
||||||
|
|
||||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||||
@@ -151,7 +52,6 @@ namespace hexworld
|
|||||||
tiles[i].Position.Z = (float) (Math.Sin((t + ti.Position.X - ti.Position.Y / 1.5) / 1.5) * .25);
|
tiles[i].Position.Z = (float) (Math.Sin((t + ti.Position.X - ti.Position.Y / 1.5) / 1.5) * .25);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tileVbo.Data(tiles, BufferUsageHint.DynamicDraw);
|
|
||||||
tileVbo.Bind();
|
tileVbo.Bind();
|
||||||
GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr) (0), (IntPtr) (16 * 3 * sizeof(float)), tiles);
|
GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr) (0), (IntPtr) (16 * 3 * sizeof(float)), tiles);
|
||||||
VBO.Unbind();
|
VBO.Unbind();
|
||||||
@@ -161,10 +61,10 @@ namespace hexworld
|
|||||||
{
|
{
|
||||||
base.OnLoad(e);
|
base.OnLoad(e);
|
||||||
|
|
||||||
cubeVbo = new VBO();
|
cubeVbo = new VBO<Vertex>();
|
||||||
cubeVbo.Data(cubeVerts, BufferUsageHint.StaticDraw);
|
cubeVbo.Data(cubeVerts, BufferUsageHint.StaticDraw);
|
||||||
|
|
||||||
tileVbo = new VBO();
|
tileVbo = new VBO<Tile>();
|
||||||
tileVbo.Data(tiles, BufferUsageHint.DynamicDraw);
|
tileVbo.Data(tiles, BufferUsageHint.DynamicDraw);
|
||||||
|
|
||||||
var vs = new Shader(ShaderType.VertexShader)
|
var vs = new Shader(ShaderType.VertexShader)
|
||||||
@@ -187,31 +87,8 @@ namespace hexworld
|
|||||||
pgm.Link();
|
pgm.Link();
|
||||||
Console.Out.WriteLine(pgm.Log);
|
Console.Out.WriteLine(pgm.Log);
|
||||||
|
|
||||||
var pos = pgm.GetAttribute("locpos");
|
cubeVbo.AttribPointers(pgm);
|
||||||
var crd = pgm.GetAttribute("coord");
|
tileVbo.AttribPointers(pgm);
|
||||||
var nrm = pgm.GetAttribute("norm");
|
|
||||||
var tpos = pgm.GetAttribute("glbpos");
|
|
||||||
|
|
||||||
GL.EnableVertexAttribArray(pos);
|
|
||||||
GL.EnableVertexAttribArray(crd);
|
|
||||||
GL.EnableVertexAttribArray(nrm);
|
|
||||||
GL.EnableVertexAttribArray(tpos);
|
|
||||||
|
|
||||||
cubeVbo.Bind();
|
|
||||||
|
|
||||||
GL.VertexAttribPointer(pos, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float),
|
|
||||||
0);
|
|
||||||
GL.VertexAttribPointer(crd, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float),
|
|
||||||
3 * sizeof(float));
|
|
||||||
GL.VertexAttribPointer(nrm, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float),
|
|
||||||
5 * sizeof(float));
|
|
||||||
|
|
||||||
tileVbo.Bind();
|
|
||||||
|
|
||||||
GL.VertexAttribPointer(tpos, 3, VertexAttribPointerType.Float, false, 0, 0);
|
|
||||||
GL.VertexAttribDivisor(tpos, 1);
|
|
||||||
|
|
||||||
VBO.Unbind();
|
|
||||||
|
|
||||||
grass = Texture.FromBitmap(new Bitmap("grass.png"));
|
grass = Texture.FromBitmap(new Bitmap("grass.png"));
|
||||||
stone = Texture.FromBitmap(new Bitmap("stone.png"));
|
stone = Texture.FromBitmap(new Bitmap("stone.png"));
|
||||||
@@ -223,16 +100,18 @@ namespace hexworld
|
|||||||
|
|
||||||
GL.Viewport(ClientRectangle);
|
GL.Viewport(ClientRectangle);
|
||||||
|
|
||||||
GL.ClearColor(0.2392157F,0.5607843F,0.9960784F, 1f);
|
GL.ClearColor(0.2392157F, 0.5607843F, 0.9960784F, 1f);
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
||||||
|
|
||||||
GL.Enable(EnableCap.DepthTest);
|
GL.Enable(EnableCap.DepthTest);
|
||||||
GL.DepthFunc(DepthFunction.Lequal);
|
GL.DepthFunc(DepthFunction.Lequal);
|
||||||
GL.Enable(EnableCap.Blend);
|
GL.Enable(EnableCap.Blend);
|
||||||
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
||||||
|
GL.Enable(EnableCap.CullFace);
|
||||||
|
GL.CullFace(CullFaceMode.Back);
|
||||||
|
|
||||||
pgm.Use();
|
pgm.Use();
|
||||||
|
pgm.EnableAllAttribArrays();
|
||||||
|
|
||||||
grass.Bind(0);
|
grass.Bind(0);
|
||||||
stone.Bind(1);
|
stone.Bind(1);
|
||||||
@@ -247,9 +126,10 @@ namespace hexworld
|
|||||||
GL.UniformMatrix4(pgm.GetUniform("view"), false, ref view);
|
GL.UniformMatrix4(pgm.GetUniform("view"), false, ref view);
|
||||||
GL.UniformMatrix4(pgm.GetUniform("proj"), false, ref proj);
|
GL.UniformMatrix4(pgm.GetUniform("proj"), false, ref proj);
|
||||||
|
|
||||||
// GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 36, 6, 5, 16);
|
|
||||||
GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 0, 36, 5, 16);
|
GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 0, 36, 5, 16);
|
||||||
|
|
||||||
|
pgm.DisableAllAttribArrays();
|
||||||
|
|
||||||
SwapBuffers();
|
SwapBuffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,20 +47,42 @@ namespace hexworld.Util
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetUniform(string name, out int id)
|
||||||
|
{
|
||||||
|
return uniforms.TryGetValue(name, out id);
|
||||||
|
}
|
||||||
|
|
||||||
public int GetUniform(string name)
|
public int GetUniform(string name)
|
||||||
{
|
{
|
||||||
if (!uniforms.TryGetValue(name, out int id))
|
if (!TryGetUniform(name, out int id))
|
||||||
throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'");
|
throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'");
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetAttribute(string name, out int id)
|
||||||
|
{
|
||||||
|
return attributes.TryGetValue(name, out id);
|
||||||
|
}
|
||||||
|
|
||||||
public int GetAttribute(string name)
|
public int GetAttribute(string name)
|
||||||
{
|
{
|
||||||
if (!attributes.TryGetValue(name, out int id))
|
if (!TryGetAttribute(name, out int id))
|
||||||
throw new ShaderException($"Shader Program {Id} does not contain attribute '{name}'");
|
throw new ShaderException($"Shader Program {Id} does not contain id '{name}'");
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnableAllAttribArrays()
|
||||||
|
{
|
||||||
|
foreach (var loc in attributes.Values)
|
||||||
|
GL.EnableVertexAttribArray(loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisableAllAttribArrays()
|
||||||
|
{
|
||||||
|
foreach (var loc in attributes.Values)
|
||||||
|
GL.DisableVertexAttribArray(loc);
|
||||||
|
}
|
||||||
|
|
||||||
public void Use() => GL.UseProgram(Id);
|
public void Use() => GL.UseProgram(Id);
|
||||||
|
|
||||||
public static void UseDefault() => GL.UseProgram(0);
|
public static void UseDefault() => GL.UseProgram(0);
|
||||||
|
|||||||
@@ -8,7 +8,15 @@ using OpenTK.Graphics.OpenGL4;
|
|||||||
|
|
||||||
namespace hexworld.Util
|
namespace hexworld.Util
|
||||||
{
|
{
|
||||||
public class VBO : GLObject
|
public static class VBO
|
||||||
|
{
|
||||||
|
public static void Unbind()
|
||||||
|
{
|
||||||
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VBO<T> : GLObject where T : struct
|
||||||
{
|
{
|
||||||
public VBO()
|
public VBO()
|
||||||
: base((uint) GL.GenBuffer())
|
: base((uint) GL.GenBuffer())
|
||||||
@@ -20,17 +28,49 @@ namespace hexworld.Util
|
|||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, Id);
|
GL.BindBuffer(BufferTarget.ArrayBuffer, Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Data<T>(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) where T : struct
|
public void Data(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw)
|
||||||
{
|
{
|
||||||
Bind();
|
Bind();
|
||||||
var size = Marshal.SizeOf<T>();
|
var size = Marshal.SizeOf<T>();
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(size * data.Length), data, usage);
|
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (size * data.Length), data, usage);
|
||||||
Unbind();
|
VBO.Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Unbind()
|
// todo: this needs a better solution.
|
||||||
|
private static readonly int Stride;
|
||||||
|
private static readonly VertexPointerAttribute[] Attributes;
|
||||||
|
|
||||||
|
static VBO()
|
||||||
{
|
{
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
var attribList = new List<VertexPointerAttribute>();
|
||||||
|
Stride = Marshal.SizeOf<T>();
|
||||||
|
|
||||||
|
foreach (var fieldInfo in typeof(T).GetFields())
|
||||||
|
{
|
||||||
|
var attrs = fieldInfo.GetCustomAttributes(typeof(VertexPointerAttribute), false);
|
||||||
|
if (attrs.Length == 0) continue;
|
||||||
|
var offset = (int) Marshal.OffsetOf<T>(fieldInfo.Name);
|
||||||
|
foreach (var attr in attrs)
|
||||||
|
{
|
||||||
|
var vpa = (VertexPointerAttribute) attr;
|
||||||
|
vpa.Offset = offset;
|
||||||
|
attribList.Add(vpa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Attributes = attribList.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AttribPointers(Program pgm)
|
||||||
|
{
|
||||||
|
Bind();
|
||||||
|
foreach (var attr in Attributes)
|
||||||
|
{
|
||||||
|
if (!pgm.TryGetAttribute(attr.Name, out int loc)) continue;
|
||||||
|
GL.VertexAttribPointer(loc, attr.Size, attr.Type, attr.Normalized, Stride, attr.Offset);
|
||||||
|
GL.VertexAttribDivisor(loc, attr.Divisor);
|
||||||
|
}
|
||||||
|
VBO.Unbind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
22
hexworld/Util/VertexPointerAttribute.cs
Normal file
22
hexworld/Util/VertexPointerAttribute.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using OpenTK.Graphics.OpenGL4;
|
||||||
|
|
||||||
|
namespace hexworld.Util
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)]
|
||||||
|
public sealed class VertexPointerAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public int Size { get; }
|
||||||
|
public VertexAttribPointerType Type { get; set; } = VertexAttribPointerType.Float;
|
||||||
|
public bool Normalized { get; set; } = false;
|
||||||
|
public int Divisor { get; set; } = 0;
|
||||||
|
public int Offset { get; set; } = 0;
|
||||||
|
|
||||||
|
public VertexPointerAttribute(string name, int size)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
hexworld/VertexData.cs
Normal file
52
hexworld/VertexData.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using hexworld.Util;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using OpenTK;
|
||||||
|
|
||||||
|
namespace hexworld
|
||||||
|
{
|
||||||
|
public partial class HexRender
|
||||||
|
{
|
||||||
|
public struct Tile
|
||||||
|
{
|
||||||
|
[JsonProperty("pos")]
|
||||||
|
[VertexPointer("glbpos", 3, Divisor = 1)]
|
||||||
|
public Vector3 Position;
|
||||||
|
|
||||||
|
public Tile(Vector3 position)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Vertex
|
||||||
|
{
|
||||||
|
[JsonProperty("pos")]
|
||||||
|
[VertexPointer("locpos", 3)]
|
||||||
|
public Vector3 Position;
|
||||||
|
|
||||||
|
[JsonProperty("uv")]
|
||||||
|
[VertexPointer("coord", 2)]
|
||||||
|
public Vector2 UV;
|
||||||
|
|
||||||
|
[JsonProperty("norm")]
|
||||||
|
[VertexPointer("norm", 3)]
|
||||||
|
public Vector3 Normal;
|
||||||
|
|
||||||
|
public Vertex(Vector3 position, Vector2 uv, Vector3 normal)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
UV = uv;
|
||||||
|
Normal = normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Vertex[] cubeVerts = JsonConvert.DeserializeObject<Vertex[]>(File.ReadAllText("cube.json"));
|
||||||
|
private Tile[] tiles = JsonConvert.DeserializeObject<Tile[]>(File.ReadAllText("tiles.json"));
|
||||||
|
}
|
||||||
|
}
|
||||||
38
hexworld/cube.json
Normal file
38
hexworld/cube.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
[
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": -.5 }, "uv": { "x": 1, "y": .5 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": -.5 }, "uv": { "x": 1, "y": .5 }, "norm": { "x": 1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": -.5 }, "uv": { "x": 1, "y": .5 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": -1, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": -.5 }, "uv": { "x": 1, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": -.5 }, "uv": { "x": 1, "y": .5 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": .5 }, "uv": { "x": 1, "y": 0 }, "norm": { "x": 0, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": .5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": .5 }, "uv": { "x": 0, "y": 0 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": .5 }, "uv": { "x": 0, "y": .5 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": .5 }, "uv": { "x": 0, "y": .5 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": .5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": .5 }, "uv": { "x": .5, "y": .0 }, "norm": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": -.5, "z": -.5 }, "uv": { "x": 0, "y": .5 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": -.5 }, "uv": { "x": 0, "y": 0 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
{ "pos": { "x": -.5, "y": .5, "z": -.5 }, "uv": { "x": 0, "y": 0 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
{ "pos": { "x": .5, "y": .5, "z": -.5 }, "uv": { "x": .5, "y": 0 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
{ "pos": { "x": .5, "y": -.5, "z": -.5 }, "uv": { "x": .5, "y": .5 }, "norm": { "x": 0, "y": 0, "z": -1 } },
|
||||||
|
]
|
||||||
@@ -51,6 +51,7 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="VertexData.cs" />
|
||||||
<Compile Include="Driver.cs" />
|
<Compile Include="Driver.cs" />
|
||||||
<Compile Include="HexRender.cs" />
|
<Compile Include="HexRender.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@@ -61,6 +62,7 @@
|
|||||||
<Compile Include="Util\ShaderException.cs" />
|
<Compile Include="Util\ShaderException.cs" />
|
||||||
<Compile Include="Util\Texture.cs" />
|
<Compile Include="Util\Texture.cs" />
|
||||||
<Compile Include="Util\VBO.cs" />
|
<Compile Include="Util\VBO.cs" />
|
||||||
|
<Compile Include="Util\VertexPointerAttribute.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
@@ -72,6 +74,12 @@
|
|||||||
<None Include="s.vs.glsl">
|
<None Include="s.vs.glsl">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="cube.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Include="tiles.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="grass.png">
|
<Content Include="grass.png">
|
||||||
|
|||||||
23
hexworld/tiles.json
Normal file
23
hexworld/tiles.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[
|
||||||
|
{ "pos": { "x": -2, "y": -2, "z": 0 } },
|
||||||
|
{ "pos": { "x": -2, "y": -1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -2, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": -2, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": -2, "y": 2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 2, "y": -2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 2, "y": -1, "z": 0 } },
|
||||||
|
{ "pos": { "x": 2, "y": 0, "z": 0 } },
|
||||||
|
{ "pos": { "x": 2, "y": 1, "z": 0 } },
|
||||||
|
{ "pos": { "x": 2, "y": 2, "z": 0 } },
|
||||||
|
{ "pos": { "x": -1, "y": -2, "z": 0 } },
|
||||||
|
{ "pos": { "x": -1, "y": 2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 0, "y": -2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 0, "y": 2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 1, "y": -2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 1, "y": 2, "z": 0 } },
|
||||||
|
{ "pos": { "x": 0, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": 0, "y": 1, "z": 1 } },
|
||||||
|
{ "pos": { "x": 0, "y": -1, "z": 1 } },
|
||||||
|
{ "pos": { "x": -1, "y": 0, "z": 1 } },
|
||||||
|
{ "pos": { "x": 1, "y": 0, "z": 1 } }
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user