More OO-like. a bit easier to read/use things

This commit is contained in:
2017-02-24 21:22:13 -05:00
parent 338efc337e
commit 2710007ec2
12 changed files with 348 additions and 75 deletions

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace hexworld
{
public class Program
public class Driver
{
public static void Main(string[] args)
{

View File

@@ -6,6 +6,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using hexworld.Util;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat;
@@ -36,31 +37,32 @@ namespace hexworld
private readonly Vert[] _verts =
{
// +X
new Vert(+1, +1, -1, 1.0f, 0.5f), new Vert(+1, +1, +1, 1.0f, 0.0f), new Vert(+1, -1, +1, 0.5f, 0.0f),
new Vert(+1, -1, +1, 0.5f, 0.0f), new Vert(+1, -1, -1, 0.5f, 0.5f), new Vert(+1, +1, -1, 1.0f, 0.5f),
new Vert(+.5f, +.5f, -.5f, 1.0f, 0.5f), new Vert(+.5f, +.5f, +.5f, 1.0f, 0.0f), new Vert(+.5f, -.5f, +.5f, 0.5f, 0.0f),
new Vert(+.5f, -.5f, +.5f, 0.5f, 0.0f), new Vert(+.5f, -.5f, -.5f, 0.5f, 0.5f), new Vert(+.5f, +.5f, -.5f, 1.0f, 0.5f),
// -X
new Vert(-1, +1, +1, 0.5f, 0.0f), new Vert(-1, +1, -1, 0.5f, 0.5f), new Vert(-1, -1, -1, 1.0f, 0.5f),
new Vert(-1, -1, -1, 1.0f, 0.5f), new Vert(-1, -1, +1, 1.0f, 0.0f), new Vert(-1, +1, +1, 0.5f, 0.0f),
new Vert(-.5f, +.5f, +.5f, 0.5f, 0.0f), new Vert(-.5f, +.5f, -.5f, 0.5f, 0.5f), new Vert(-.5f, -.5f, -.5f, 1.0f, 0.5f),
new Vert(-.5f, -.5f, -.5f, 1.0f, 0.5f), new Vert(-.5f, -.5f, +.5f, 1.0f, 0.0f), new Vert(-.5f, +.5f, +.5f, 0.5f, 0.0f),
// +Y
new Vert(+1, +1, -1, 0.5f, 0.5f), new Vert(-1, +1, -1, 1.0f, 0.5f), new Vert(-1, +1, +1, 1.0f, 0.0f),
new Vert(-1, +1, +1, 1.0f, 0.0f), new Vert(+1, +1, +1, 0.5f, 0.0f), new Vert(+1, +1, -1, 0.5f, 0.5f),
new Vert(+.5f, +.5f, -.5f, 0.5f, 0.5f), new Vert(-.5f, +.5f, -.5f, 1.0f, 0.5f), new Vert(-.5f, +.5f, +.5f, 1.0f, 0.0f),
new Vert(-.5f, +.5f, +.5f, 1.0f, 0.0f), new Vert(+.5f, +.5f, +.5f, 0.5f, 0.0f), new Vert(+.5f, +.5f, -.5f, 0.5f, 0.5f),
// -Y
new Vert(+1, -1, +1, 1.0f, 0.0f), new Vert(-1, -1, +1, 0.5f, 0.0f), new Vert(-1, -1, -1, 0.5f, 0.5f),
new Vert(-1, -1, -1, 0.5f, 0.5f), new Vert(+1, -1, -1, 1.0f, 0.5f), new Vert(+1, -1, +1, 1.0f, 0.0f),
new Vert(+.5f, -.5f, +.5f, 1.0f, 0.0f), new Vert(-.5f, -.5f, +.5f, 0.5f, 0.0f), new Vert(-.5f, -.5f, -.5f, 0.5f, 0.5f),
new Vert(-.5f, -.5f, -.5f, 0.5f, 0.5f), new Vert(+.5f, -.5f, -.5f, 1.0f, 0.5f), new Vert(+.5f, -.5f, +.5f, 1.0f, 0.0f),
// +Z
new Vert(+1, +1, +1, 0.5f, 0.0f), new Vert(-1, +1, +1, 0.0f, 0.0f), new Vert(-1, -1, +1, 0.0f, 0.5f),
new Vert(-1, -1, +1, 0.0f, 0.5f), new Vert(+1, -1, +1, 0.5f, 0.5f), new Vert(+1, +1, +1, 0.5f, 0.0f),
new Vert(+.5f, +.5f, +.5f, 0.5f, 0.0f), new Vert(-.5f, +.5f, +.5f, 0.0f, 0.0f), new Vert(-.5f, -.5f, +.5f, 0.0f, 0.5f),
new Vert(-.5f, -.5f, +.5f, 0.0f, 0.5f), new Vert(+.5f, -.5f, +.5f, 0.5f, 0.5f), new Vert(+.5f, +.5f, +.5f, 0.5f, 0.0f),
// -Z
new Vert(+1, +1, -1, 0.5f, 0.5f), new Vert(-1, +1, -1, 0.0f, 0.5f), new Vert(-1, -1, -1, 0.0f, 1.0f),
new Vert(-1, -1, -1, 0.0f, 1.0f), new Vert(+1, -1, -1, 0.5f, 1.0f), new Vert(+1, +1, -1, 0.5f, 0.5f),
new Vert(+.5f, +.5f, -.5f, 0.5f, 0.5f), new Vert(-.5f, +.5f, -.5f, 0.0f, 0.5f), new Vert(-.5f, -.5f, -.5f, 0.0f, 1.0f),
new Vert(-.5f, -.5f, -.5f, 0.0f, 1.0f), new Vert(+.5f, -.5f, -.5f, 0.5f, 1.0f), new Vert(+.5f, +.5f, -.5f, 0.5f, 0.5f),
};
private Matrix4 _view = Matrix4.Identity;
private Matrix4 _proj = Matrix4.Identity;
private int _pgm;
private int _texLoc;
private int _tex2Loc;
private Program _pgm;
private Texture _tex1;
private Texture _tex2;
public HexWindow(int width, int height)
: base(width, height)
@@ -71,6 +73,7 @@ namespace hexworld
Y = (DisplayDevice.Default.Height - Height) / 2;
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
@@ -84,64 +87,33 @@ namespace hexworld
{
base.OnLoad(e);
var vertsVbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vertsVbo);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_verts.Length * Vert.SizeInBytes), _verts,
BufferUsageHint.StaticDraw);
var vbo = new VBO();
vbo.Data(_verts);
var vs = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vs, File.ReadAllText("s.vs.glsl"));
GL.CompileShader(vs);
Console.Out.WriteLine("vs:" + GL.GetShaderInfoLog(vs));
var vs = new Shader(ShaderType.VertexShader) {Source = File.ReadAllText("s.vs.glsl")};
if (!vs.Compile())
Console.Out.WriteLine($"vs: {vs.Log}");
var fs = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fs, File.ReadAllText("s.fs.glsl"));
GL.CompileShader(fs);
Console.Out.WriteLine("fs: " + GL.GetShaderInfoLog(fs));
var fs = new Shader(ShaderType.FragmentShader) {Source = File.ReadAllText("s.fs.glsl")};
if (!fs.Compile())
Console.Out.WriteLine($"fs: {fs.Log}");
_pgm = GL.CreateProgram();
GL.AttachShader(_pgm, vs);
GL.AttachShader(_pgm, fs);
GL.LinkProgram(_pgm);
Console.Out.WriteLine("pgm: " + GL.GetProgramInfoLog(_pgm));
_pgm = new Program();
_pgm.Attach(vs);
_pgm.Attach(fs);
if (!_pgm.Link())
Console.Out.WriteLine($"pgm: {_pgm.Log}");
GL.BindBuffer(BufferTarget.ArrayBuffer, vertsVbo);
vbo.Bind();
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vert.SizeInBytes, 0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, Vert.SizeInBytes, Vector3.SizeInBytes);
VBO.Unbind();
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
_tex1 = Texture.FromBitmap(new Bitmap("tex.png"));
var texBmp = new Bitmap("tex.png");
_texLoc = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _texLoc);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
(int) TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
(int) TextureMagFilter.Nearest);
var texData = texBmp.LockBits(new Rectangle(0, 0, texBmp.Width, texBmp.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texBmp.Width, texBmp.Height, 0,
PixelFormat.Bgra, PixelType.UnsignedByte, texData.Scan0);
texBmp.UnlockBits(texData);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
var tex2Bmp = new Bitmap("tex2.png");
_tex2Loc = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _tex2Loc);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
(int) TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
(int) TextureMagFilter.Nearest);
var tex2Data = tex2Bmp.LockBits(new Rectangle(0, 0, tex2Bmp.Width, tex2Bmp.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, tex2Bmp.Width, tex2Bmp.Height, 0,
PixelFormat.Bgra, PixelType.UnsignedByte, tex2Data.Scan0);
tex2Bmp.UnlockBits(tex2Data);
GL.BindTexture(TextureTarget.Texture2D, 0);
_tex2 = Texture.FromBitmap(new Bitmap("tex2.png"));
}
protected override void OnRenderFrame(FrameEventArgs e)
@@ -152,19 +124,24 @@ namespace hexworld
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Enable(EnableCap.DepthTest);
GL.UseProgram(_pgm);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, _tex2Loc);
GL.Uniform1(GL.GetUniformLocation(_pgm, "tex"), 0);
_pgm.Use();
GL.UniformMatrix4(GL.GetUniformLocation(_pgm, "view"), false, ref _view);
GL.UniformMatrix4(GL.GetUniformLocation(_pgm, "proj"), false, ref _proj);
_tex1.Bind(0);
_tex2.Bind(1);
GL.Uniform1(_pgm.GetUniform("tex"), 0);
GL.UniformMatrix4(_pgm.GetUniform("view"), false, ref _view);
GL.UniformMatrix4(_pgm.GetUniform("proj"), false, ref _proj);
GL.DrawArrays(PrimitiveType.Triangles, 0, _verts.Length);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.Uniform1(_pgm.GetUniform("tex"), 1);
_view = Matrix4.CreateTranslation(0, 2, 0) * _view;
GL.UniformMatrix4(_pgm.GetUniform("view"), false, ref _view);
GL.DrawArrays(PrimitiveType.Triangles, 0, _verts.Length);
SwapBuffers();
}

View File

@@ -19,7 +19,7 @@ using System.Runtime.InteropServices;
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
// The following GUID is for the Id of the typelib if this project is exposed to COM
[assembly: Guid("ad9ed057-fb47-44cb-8839-22924b409706")]
// Version information for an assembly consists of the following four values:

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace hexworld.Util
{
public static class Extensions
{
public static byte[] ToBytes<T>(this T[] arr) where T : struct
{
var size = Marshal.SizeOf<T>()*arr.Length;
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(arr, ptr, false);
Marshal.Copy(ptr, bytes, 0, size);
Marshal.FreeHGlobal(ptr);
return bytes;
}
}
}

22
hexworld/Util/GLObject.cs Normal file
View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace hexworld.Util
{
public abstract class GLObject
{
public uint Id { get; protected set; }
protected GLObject(uint id)
{
Id = id;
}
public static explicit operator uint(GLObject o) => o.Id;
public static explicit operator int(GLObject o) => (int) o.Id;
}
}

63
hexworld/Util/Program.cs Normal file
View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace hexworld.Util
{
public class Program : GLObject
{
private Dictionary<string, int> uniforms = new Dictionary<string, int>();
private Dictionary<string, int> attributes = new Dictionary<string, int>();
public string Log => GL.GetProgramInfoLog((int) Id);
public Program()
: base((uint) GL.CreateProgram())
{
}
public void Attach(Shader shader) => GL.AttachShader(Id, shader.Id);
public bool Link()
{
uniforms.Clear();
attributes.Clear();
GL.LinkProgram(Id);
GL.GetProgram(Id, GetProgramParameterName.LinkStatus, out int success);
if (success == 0) return false;
GL.GetProgram(Id, GetProgramParameterName.ActiveUniforms, out int uniformcount);
for (var i = 0; i < uniformcount; i++)
{
var sb = new StringBuilder(256);
GL.GetActiveUniformName((int) Id, i, sb.Capacity, out int length, sb);
uniforms[sb.ToString()] = i;
}
GL.GetProgram(Id, GetProgramParameterName.ActiveAttributes, out int attributecount);
for (var i = 0; i < attributecount; i++)
{
var sb = new StringBuilder(256);
GL.GetActiveAttrib((int) Id, i, sb.Capacity, out int length, out int size,
out ActiveAttribType type, sb);
attributes[sb.ToString()] = i;
}
return true;
}
public int GetUniform(string name)
{
if (!uniforms.TryGetValue(name, out int id))
throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'");
else return id;
}
public void Use() => GL.UseProgram(Id);
public static void UseDefault() => GL.UseProgram(0);
}
}

39
hexworld/Util/Shader.cs Normal file
View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace hexworld.Util
{
public class Shader : GLObject
{
public readonly ShaderType Type;
public string Source
{
get
{
var sb = new StringBuilder(1024);
GL.GetShaderSource(Id, sb.Capacity, out int length, sb);
return sb.ToString();
}
set { GL.ShaderSource((int) Id, value); }
}
public string Log => GL.GetShaderInfoLog((int) Id);
public Shader(ShaderType type)
: base((uint) GL.CreateShader(type))
{
Type = type;
}
public bool Compile()
{
GL.CompileShader(Id);
GL.GetShader(Id, ShaderParameter.CompileStatus, out int success);
return success != 0;
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Runtime.Serialization;
namespace hexworld.Util
{
[Serializable]
public class ShaderException : Exception
{
public ShaderException()
{
}
public ShaderException(string message)
: base(message)
{
}
public ShaderException(string message, Exception inner)
: base(message, inner)
{
}
protected ShaderException(
SerializationInfo info,
StreamingContext context)
: base(info, context)
{
}
}
}

74
hexworld/Util/Texture.cs Normal file
View File

@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat;
namespace hexworld.Util
{
// todo: this structure doesn't fit GL at all. need to fix it.
// need to reconcile ActiveTexture and BindTexture
public class Texture : GLObject
{
public TextureTarget Target;
public Texture(TextureTarget target = TextureTarget.Texture2D)
: base((uint) GL.GenTexture())
{
Target = target;
}
public void Bind()
{
GL.BindTexture(Target, Id);
}
public void Bind(TextureUnit unit)
{
GL.ActiveTexture(unit);
Bind();
}
public void Bind(int unit)
{
GL.ActiveTexture(TextureUnit.Texture0 + unit);
Bind();
}
public void Unbind()
{
GL.BindTexture(Target, 0);
}
public void Unbind(TextureUnit unit)
{
GL.ActiveTexture(unit);
Unbind();
}
public void Unbind(int unit)
{
GL.ActiveTexture(TextureUnit.Texture0 + unit);
Unbind();
}
public static Texture FromBitmap(Bitmap bmp)
{
var tex = new Texture(TextureTarget.Texture2D);
tex.Bind();
GL.TexParameter(tex.Target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Nearest);
GL.TexParameter(tex.Target, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest);
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
GL.TexImage2D(tex.Target, 0, PixelInternalFormat.Rgba, bmp.Width, bmp.Height, 0, PixelFormat.Bgra,
PixelType.UnsignedByte, data.Scan0);
bmp.UnlockBits(data);
tex.Unbind();
return tex;
}
}
}

36
hexworld/Util/VBO.cs Normal file
View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace hexworld.Util
{
public class VBO : GLObject
{
public VBO()
: base((uint) GL.GenBuffer())
{
}
public void Bind()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, Id);
}
public void Data<T>(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) where T : struct
{
Bind();
var size = Marshal.SizeOf<T>();
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(size * data.Length), data, usage);
Unbind();
}
public static void Unbind()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
}
}

View File

@@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -51,8 +52,15 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Game.cs" />
<Compile Include="Program.cs" />
<Compile Include="Driver.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Util\Extensions.cs" />
<Compile Include="Util\GLObject.cs" />
<Compile Include="Util\Program.cs" />
<Compile Include="Util\Shader.cs" />
<Compile Include="Util\ShaderException.cs" />
<Compile Include="Util\Texture.cs" />
<Compile Include="Util\VBO.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />

View File

@@ -6,5 +6,5 @@ uniform sampler2D tex;
void main ()
{
gl_FragColor = texture(tex, vTexCoord) + vec4(.1);
gl_FragColor = texture(tex, vTexCoord);
}