From 338efc337e2f336ecd60f5e764e9990524c37e94 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Fri, 24 Feb 2017 16:31:15 -0500 Subject: [PATCH] Slowly getting things working --- {WhatTheTexture => InstanceTiles}/App.config | 6 +- .../InstanceTiles.csproj | 15 +- .../OpenTK.dll.config | 0 InstanceTiles/Program.cs | 61 ++++++ .../Properties/AssemblyInfo.cs | 6 +- .../packages.config | 0 WhatTheTexture/Program.cs | 79 ------- WhatTheTexture/tex.png | Bin 1095 -> 0 bytes hexworld.sln | 12 +- hexworld/App.config | 6 +- hexworld/Cube.cs | 23 -- hexworld/Game.cs | 172 +++++++++++++++ hexworld/Program.cs | 200 +----------------- hexworld/fs.glsl | 10 - hexworld/hexworld.csproj | 20 +- hexworld/s.fs.glsl | 10 + hexworld/s.vs.glsl | 15 ++ hexworld/tex.png | Bin 18932 -> 5234 bytes hexworld/tex2.png | Bin 0 -> 490 bytes hexworld/vs.glsl | 17 -- 20 files changed, 297 insertions(+), 355 deletions(-) rename {WhatTheTexture => InstanceTiles}/App.config (59%) rename WhatTheTexture/WhatTheTexture.csproj => InstanceTiles/InstanceTiles.csproj (85%) rename {WhatTheTexture => InstanceTiles}/OpenTK.dll.config (100%) create mode 100644 InstanceTiles/Program.cs rename {WhatTheTexture => InstanceTiles}/Properties/AssemblyInfo.cs (89%) rename {WhatTheTexture => InstanceTiles}/packages.config (100%) delete mode 100644 WhatTheTexture/Program.cs delete mode 100644 WhatTheTexture/tex.png delete mode 100644 hexworld/Cube.cs create mode 100644 hexworld/Game.cs delete mode 100644 hexworld/fs.glsl create mode 100644 hexworld/s.fs.glsl create mode 100644 hexworld/s.vs.glsl create mode 100644 hexworld/tex2.png delete mode 100644 hexworld/vs.glsl diff --git a/WhatTheTexture/App.config b/InstanceTiles/App.config similarity index 59% rename from WhatTheTexture/App.config rename to InstanceTiles/App.config index 88fa402..bae5d6d 100644 --- a/WhatTheTexture/App.config +++ b/InstanceTiles/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/WhatTheTexture/WhatTheTexture.csproj b/InstanceTiles/InstanceTiles.csproj similarity index 85% rename from WhatTheTexture/WhatTheTexture.csproj rename to InstanceTiles/InstanceTiles.csproj index 2368221..cfcf1e3 100644 --- a/WhatTheTexture/WhatTheTexture.csproj +++ b/InstanceTiles/InstanceTiles.csproj @@ -4,13 +4,14 @@ Debug AnyCPU - {E7B84735-45AA-439A-A64B-2AF248447660} + {282D9C70-9531-4960-A84B-E314D68DABFF} Exe - WhatTheTexture - WhatTheTexture - v4.5.2 + InstanceTiles + InstanceTiles + v4.6.1 512 true + AnyCPU @@ -37,7 +38,6 @@ - @@ -54,10 +54,5 @@ - - - Always - - \ No newline at end of file diff --git a/WhatTheTexture/OpenTK.dll.config b/InstanceTiles/OpenTK.dll.config similarity index 100% rename from WhatTheTexture/OpenTK.dll.config rename to InstanceTiles/OpenTK.dll.config diff --git a/InstanceTiles/Program.cs b/InstanceTiles/Program.cs new file mode 100644 index 0000000..e8d0d73 --- /dev/null +++ b/InstanceTiles/Program.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK; + +namespace InstanceTiles +{ + internal class Program + { + private float[] points = + { + +.5f, +.5f, +.5f, -.5f, +.5f, +.5f, -.5f, -.5f, +.5f, + -.5f, -.5f, +.5f, +.5f, -.5f, +.5f, +.5f, +.5f, +.5f, + -.5f, +.5f, -.5f, +.5f, +.5f, -.5f, +.5f, -.5f, -.5f, + +.5f, -.5f, -.5f, -.5f, -.5f, -.5f, -.5f, +.5f, -.5f, + +.5f, +.5f, -.5f, +.5f, +.5f, +.5f, +.5f, -.5f, +.5f, + +.5f, -.5f, +.5f, +.5f, -.5f, -.5f, +.5f, +.5f, -.5f, + -.5f, +.5f, +.5f, -.5f, +.5f, -.5f, -.5f, -.5f, -.5f, + -.5f, -.5f, -.5f, -.5f, -.5f, +.5f, -.5f, +.5f, +.5f, + +.5f, +.5f, -.5f, -.5f, +.5f, -.5f, -.5f, +.5f, +.5f, + -.5f, +.5f, +.5f, +.5f, +.5f, +.5f, +.5f, +.5f, -.5f, + +.5f, -.5f, +.5f, -.5f, -.5f, +.5f, -.5f, -.5f, -.5f, + -.5f, -.5f, -.5f, +.5f, -.5f, -.5f, +.5f, -.5f, +.5f, + }; + + private float[] texCoords = + { + 1.0f, 0.0f, 5.0f, 0.0f, 5.0f, 1.0f, + 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 5.0f, + 1.0f, 0.5f, 0.0f, 0.5f, 0.0f, 1.0f, + 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, + 0.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, + 0.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.0f, + }; + + private float[] cubePoints = + { + 0, 0, 0, + 1, 0, 0, + 0, 1, 0, + }; + + private float[] cubeTexCoords = + { + 0.05f + }; + + private static void Main(string[] args) + { + + } + } +} \ No newline at end of file diff --git a/WhatTheTexture/Properties/AssemblyInfo.cs b/InstanceTiles/Properties/AssemblyInfo.cs similarity index 89% rename from WhatTheTexture/Properties/AssemblyInfo.cs rename to InstanceTiles/Properties/AssemblyInfo.cs index 1259cde..5195eb1 100644 --- a/WhatTheTexture/Properties/AssemblyInfo.cs +++ b/InstanceTiles/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("WhatTheTexture")] +[assembly: AssemblyTitle("InstanceTiles")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WhatTheTexture")] +[assembly: AssemblyProduct("InstanceTiles")] [assembly: AssemblyCopyright("Copyright © 2017")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e7b84735-45aa-439a-a64b-2af248447660")] +[assembly: Guid("282d9c70-9531-4960-a84b-e314d68dabff")] // Version information for an assembly consists of the following four values: // diff --git a/WhatTheTexture/packages.config b/InstanceTiles/packages.config similarity index 100% rename from WhatTheTexture/packages.config rename to InstanceTiles/packages.config diff --git a/WhatTheTexture/Program.cs b/WhatTheTexture/Program.cs deleted file mode 100644 index 2c615b9..0000000 --- a/WhatTheTexture/Program.cs +++ /dev/null @@ -1,79 +0,0 @@ -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; -using OpenTK.Graphics.OpenGL; -using PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; - -namespace WhatTheTexture -{ - internal class Program : GameWindow - { - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - Width = 1920; - Height = 1080; - X = (DisplayDevice.Default.Width - Width) / 2; - Y = (DisplayDevice.Default.Height - Height) / 2; - - GL.Enable(EnableCap.Texture2D); - - var image = new Bitmap("tex.png"); - - var texID = GL.GenTexture(); - - GL.ActiveTexture(TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, texID); - var bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), - ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, - (int) TextureMinFilter.Nearest); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, - (int) TextureMagFilter.Nearest); - - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bitmapData.Width, bitmapData.Height, 0, - PixelFormat.Bgra, PixelType.UnsignedByte, bitmapData.Scan0); - - image.UnlockBits(bitmapData); - - GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); - - GL.Viewport(ClientRectangle); - - GL.Begin(PrimitiveType.Triangles); - - GL.TexCoord2(0, 0); - GL.Vertex2(-.8, -.8); - GL.TexCoord2(1, 0); - GL.Vertex2(.8, -.8); - GL.TexCoord2(0, 1); - GL.Vertex2(-.8, .8); - - GL.TexCoord2(1, 1); - GL.Vertex2(.8, .8); - GL.TexCoord2(1, 0); - GL.Vertex2(.8, -.8); - GL.TexCoord2(0, 1); - GL.Vertex2(-.8, .8); - - GL.End(); - - SwapBuffers(); - } - - private static void Main(string[] args) - { - using (var p = new Program()) - { - p.Run(); - } - } - } -} \ No newline at end of file diff --git a/WhatTheTexture/tex.png b/WhatTheTexture/tex.png deleted file mode 100644 index 4b43e1ef173d12e85839dedd6bc79d9cebceba08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1095 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1SEZ8zRdwrjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qucLCF%=h?3y^w370~qEv>0#LT=By}Z;C1rt33 zJwsy?=IAO02IlRaE{-7;aaU(=%w;eXI9xaD&HhB813G-GjykbaJMX!5-)jG3gJkit zGlzO&Zy0hLmn9z8Idh{`cJm+;{P3gR@$2uOp<64by5#8`ei3^8S*Xy?jXaCPV`qnZ zJ~?L86IYrWr#eykv_aL?5v=G7Ki|gXd3P4CX?bFO~@IedV@(msQE7j<`}_n95pZx~$)IarH1W k=IkI(<&caw<^6BwSFCq6pFChJ0_JlDPgg&ebxsLQ0D0E>TL1t6 diff --git a/hexworld.sln b/hexworld.sln index ded023d..7f56b50 100644 --- a/hexworld.sln +++ b/hexworld.sln @@ -1,11 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26127.3 +VisualStudioVersion = 15.0.26206.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "hexworld", "hexworld\hexworld.csproj", "{AD9ED057-FB47-44CB-8839-22924B409706}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WhatTheTexture", "WhatTheTexture\WhatTheTexture.csproj", "{E7B84735-45AA-439A-A64B-2AF248447660}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InstanceTiles", "InstanceTiles\InstanceTiles.csproj", "{282D9C70-9531-4960-A84B-E314D68DABFF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ Global {AD9ED057-FB47-44CB-8839-22924B409706}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD9ED057-FB47-44CB-8839-22924B409706}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD9ED057-FB47-44CB-8839-22924B409706}.Release|Any CPU.Build.0 = Release|Any CPU - {E7B84735-45AA-439A-A64B-2AF248447660}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7B84735-45AA-439A-A64B-2AF248447660}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7B84735-45AA-439A-A64B-2AF248447660}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7B84735-45AA-439A-A64B-2AF248447660}.Release|Any CPU.Build.0 = Release|Any CPU + {282D9C70-9531-4960-A84B-E314D68DABFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {282D9C70-9531-4960-A84B-E314D68DABFF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {282D9C70-9531-4960-A84B-E314D68DABFF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {282D9C70-9531-4960-A84B-E314D68DABFF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/hexworld/App.config b/hexworld/App.config index 88fa402..bae5d6d 100644 --- a/hexworld/App.config +++ b/hexworld/App.config @@ -1,6 +1,6 @@ - + - + - \ No newline at end of file + diff --git a/hexworld/Cube.cs b/hexworld/Cube.cs deleted file mode 100644 index 6dfbbba..0000000 --- a/hexworld/Cube.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using OpenTK; - -namespace hexworld -{ - [StructLayout(LayoutKind.Sequential)] - public struct Cube - { - public Vector3 Position; - public Vector3 Color; - - public Cube(Vector3 position, Vector3 color) - { - Position = position; - Color = color; - } - } -} diff --git a/hexworld/Game.cs b/hexworld/Game.cs new file mode 100644 index 0000000..76a2e2a --- /dev/null +++ b/hexworld/Game.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OpenTK; +using OpenTK.Graphics.OpenGL4; +using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat; + +namespace hexworld +{ + public struct Vert + { + public static readonly int SizeInBytes = sizeof(float) * 5; + + public Vector3 Point; + public Vector2 TexCoord; + + public Vert(Vector3 point, Vector2 texCoord) + { + Point = point; + TexCoord = texCoord; + } + + public Vert(float px, float py, float pz, float tx, float ty) + : this(new Vector3(px, py, pz), new Vector2(tx, ty)) + { + } + } + + public class HexWindow : GameWindow + { + 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), + // -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), + // +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), + // -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), + // +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), + // -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), + }; + + private Matrix4 _view = Matrix4.Identity; + private Matrix4 _proj = Matrix4.Identity; + + private int _pgm; + private int _texLoc; + private int _tex2Loc; + + public HexWindow(int width, int height) + : base(width, height) + { + Width = width; + Height = height; + X = (DisplayDevice.Default.Width - Width) / 2; + Y = (DisplayDevice.Default.Height - Height) / 2; + } + + protected override void OnUpdateFrame(FrameEventArgs e) + { + base.OnUpdateFrame(e); + + const float s = 200f; + _view = Matrix4.LookAt(10 * Vector3.One, Vector3.Zero, Vector3.UnitZ); + _proj = Matrix4.CreateOrthographic(Width / s, Height / s, 0, 100); + } + + protected override void OnLoad(EventArgs e) + { + 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 vs = GL.CreateShader(ShaderType.VertexShader); + GL.ShaderSource(vs, File.ReadAllText("s.vs.glsl")); + GL.CompileShader(vs); + Console.Out.WriteLine("vs:" + GL.GetShaderInfoLog(vs)); + + var fs = GL.CreateShader(ShaderType.FragmentShader); + GL.ShaderSource(fs, File.ReadAllText("s.fs.glsl")); + GL.CompileShader(fs); + Console.Out.WriteLine("fs: " + GL.GetShaderInfoLog(fs)); + + _pgm = GL.CreateProgram(); + GL.AttachShader(_pgm, vs); + GL.AttachShader(_pgm, fs); + GL.LinkProgram(_pgm); + Console.Out.WriteLine("pgm: " + GL.GetProgramInfoLog(_pgm)); + + GL.BindBuffer(BufferTarget.ArrayBuffer, vertsVbo); + 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); + + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + + 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); + } + + protected override void OnRenderFrame(FrameEventArgs e) + { + base.OnRenderFrame(e); + + GL.Viewport(ClientRectangle); + 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); + + GL.UniformMatrix4(GL.GetUniformLocation(_pgm, "view"), false, ref _view); + GL.UniformMatrix4(GL.GetUniformLocation(_pgm, "proj"), false, ref _proj); + + GL.DrawArrays(PrimitiveType.Triangles, 0, _verts.Length); + + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, 0); + + SwapBuffers(); + } + } +} \ No newline at end of file diff --git a/hexworld/Program.cs b/hexworld/Program.cs index f3ce35c..c4946bc 100644 --- a/hexworld/Program.cs +++ b/hexworld/Program.cs @@ -1,203 +1,17 @@ using System; -using System.IO; -using OpenTK; -using OpenTK.Graphics.OpenGL; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace hexworld { - internal class Game : GameWindow + public class Program { - #region Constructors - - public Game() - : this(1920, 1080) - { - } - - public Game(int width, int height) - : base(width, height) - { - Width = width; - Height = height; - X = (DisplayDevice.Default.Width - Width) / 2; - Y = (DisplayDevice.Default.Height - Height) / 2; - } - - #endregion - - #region Shaders - - private int _pgmId; - private int _vsId; - private int _fsId; - - #region Handles - - #endregion - - private void LoadShader(string filename, ShaderType type, int program, out int address) - { - address = GL.CreateShader(type); - using (var sr = new StreamReader(filename)) - { - GL.ShaderSource(address, sr.ReadToEnd()); - } - GL.CompileShader(address); - GL.AttachShader(program, address); - Console.WriteLine(GL.GetShaderInfoLog(address)); - } - - #endregion - - #region Buffers - - private int _vboPosition; - private int _cubeVbo; - private int _ibo; - - - #endregion - - #region Data - - private float[] _vertdata; - private Cube[] _cubes; - private int[] _indices; - - private Matrix4 _view; - private Matrix4 _projection; - - #endregion - - private void InitProgram() - { - _pgmId = GL.CreateProgram(); - - LoadShader("vs.glsl", ShaderType.VertexShader, _pgmId, out _vsId); - LoadShader("fs.glsl", ShaderType.FragmentShader, _pgmId, out _fsId); - - GL.LinkProgram(_pgmId); - Console.WriteLine(GL.GetProgramInfoLog(_pgmId)); - - GL.GenBuffers(1, out _vboPosition); - GL.BindBuffer(BufferTarget.ArrayBuffer, _vboPosition); - GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_vertdata.Length * sizeof(float)), _vertdata, - BufferUsageHint.StaticDraw); - GL.EnableVertexAttribArray(0); - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); - - GL.GenBuffers(1, out _cubeVbo); - GL.BindBuffer(BufferTarget.ArrayBuffer, _cubeVbo); - GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_cubes.Length * sizeof(float) * 6), _cubes, - BufferUsageHint.StaticDraw); - GL.EnableVertexAttribArray(1); - GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 0); - GL.VertexAttribDivisor(1, 1); - - GL.EnableVertexAttribArray(2); - GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), 3 * sizeof(float)); - GL.VertexAttribDivisor(2, 1); - - GL.GenBuffers(1, out _ibo); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ibo); - GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (_indices.Length * sizeof(int)), _indices, - BufferUsageHint.StaticDraw); - } - - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - - _vertdata = new[] - { - -.5f, -.5f, -.5f, - -.5f, -.5f, .5f, - -.5f, .5f, -.5f, - -.5f, .5f, .5f, - .5f, -.5f, -.5f, - .5f, -.5f, .5f, - .5f, .5f, -.5f, - .5f, .5f, .5f, - }; - - _indices = new[] - { - 0, 1, 2, 1, 2, 3, - 4, 5, 6, 5, 6, 7, - 0, 1, 4, 1, 4, 5, - 2, 3, 6, 3, 6, 7, - 0, 2, 4, 2, 4, 6, - 1, 3, 5, 3, 5, 7 - }; - - _cubes = new[] - { - new Cube(new Vector3(2, 2, 0), new Vector3(0.9f, 0.1f, 0.1f)), - new Cube(new Vector3(2, 1, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(2, 0, 0), new Vector3(0.1f, 0.9f, 0.1f)), - new Cube(new Vector3(2, -1, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(2, -2, 0), new Vector3(0.9f, 0.1f, 0.1f)), - new Cube(new Vector3(1, 2, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(1, -2, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(0, 2, 0), new Vector3(0.1f, 0.1f, 0.9f)), - new Cube(new Vector3(0, -2, 0), new Vector3(0.1f, 0.1f, 0.9f)), - new Cube(new Vector3(-1, 2, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(-1, -2, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(-2, 2, 0), new Vector3(0.9f, 0.1f, 0.1f)), - new Cube(new Vector3(-2, 1, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(-2, 0, 0), new Vector3(0.1f, 0.9f, 0.1f)), - new Cube(new Vector3(-2, -1, 0), new Vector3(0.1f, 0.1f, 0.1f)), - new Cube(new Vector3(-2, -2, 0), new Vector3(0.9f, 0.1f, 0.1f)), - }; - - InitProgram(); - - _view = _projection = Matrix4.Identity; - } - - protected override void OnRenderFrame(FrameEventArgs e) - { - base.OnRenderFrame(e); - GL.Viewport(ClientRectangle); - - GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - GL.Enable(EnableCap.DepthTest); - - - GL.DrawElementsInstanced(PrimitiveType.Triangles, _indices.Length, DrawElementsType.UnsignedInt, IntPtr.Zero, - _cubes.Length); - - GL.Flush(); - SwapBuffers(); - } - - protected override void OnUpdateFrame(FrameEventArgs e) - { - base.OnUpdateFrame(e); - - _view = Matrix4.LookAt(Vector3.Zero, -Vector3.One, Vector3.UnitZ); - - GL.UniformMatrix4(0, false, ref _view); - GL.UniformMatrix4(1, false, ref _projection); - - GL.UseProgram(_pgmId); - - GL.BindBuffer(BufferTarget.ArrayBuffer, 0); - } - - protected override void OnResize(EventArgs e) - { - base.OnResize(e); - - float size = 100; - _projection = Matrix4.CreateOrthographic(Width / size, Height / size, -50, 50); - } - public static void Main(string[] args) { - Game gw; - using (gw = new Game()) + using (var gw = new HexWindow(1920, 1080)) { gw.Run(); } diff --git a/hexworld/fs.glsl b/hexworld/fs.glsl deleted file mode 100644 index 1ba171f..0000000 --- a/hexworld/fs.glsl +++ /dev/null @@ -1,10 +0,0 @@ -#version 440 - -in vec4 color; -out vec4 outputColor; - -void -main() -{ - outputColor = color; -} \ No newline at end of file diff --git a/hexworld/hexworld.csproj b/hexworld/hexworld.csproj index d2f1510..fe96bd2 100644 --- a/hexworld/hexworld.csproj +++ b/hexworld/hexworld.csproj @@ -8,9 +8,10 @@ Exe hexworld hexworld - v4.5.2 + v4.6.1 512 true + AnyCPU @@ -49,20 +50,18 @@ - + - - Always - - - - + + Always + + Always @@ -71,5 +70,10 @@ Always + + + Always + + \ No newline at end of file diff --git a/hexworld/s.fs.glsl b/hexworld/s.fs.glsl new file mode 100644 index 0000000..40028a0 --- /dev/null +++ b/hexworld/s.fs.glsl @@ -0,0 +1,10 @@ +#version 440 + +in vec2 vTexCoord; + +uniform sampler2D tex; + +void main () +{ + gl_FragColor = texture(tex, vTexCoord) + vec4(.1); +} \ No newline at end of file diff --git a/hexworld/s.vs.glsl b/hexworld/s.vs.glsl new file mode 100644 index 0000000..39134a3 --- /dev/null +++ b/hexworld/s.vs.glsl @@ -0,0 +1,15 @@ +#version 440 + +in vec3 pos; +in vec2 texCoord; + +out vec2 vTexCoord; + +layout (location=1) uniform mat4 view; +layout (location=2) uniform mat4 proj; + +void main () +{ + gl_Position = proj*view*vec4(pos, 1); + vTexCoord = texCoord; +} \ No newline at end of file diff --git a/hexworld/tex.png b/hexworld/tex.png index 75eb35703622a3408b575acaf97cd2622dde9d33..21b5b4d4993878f69409e7b681dbe4c39bf70d6d 100644 GIT binary patch delta 5222 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 literal 18932 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 <(0fW-nvTv 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