diff --git a/hexworld/HexRender.cs b/hexworld/HexRender.cs index 2bcdba2..2c5f89b 100644 --- a/hexworld/HexRender.cs +++ b/hexworld/HexRender.cs @@ -7,61 +7,124 @@ using OpenTK.Graphics.OpenGL4; namespace hexworld { + public struct Vertex + { + 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 Texture tex1; + private Texture grass; + private Texture stone; private Texture tex2; private Matrix4 view; private Matrix4 proj; - private readonly float[] verts = + private readonly Vertex[] cubeVerts = { - // +X - +.5f, +.5f, -.5f, 1.0f, 0.5f, - +.5f, +.5f, +.5f, 1.0f, 0.0f, - +.5f, -.5f, +.5f, 0.5f, 0.0f, - +.5f, -.5f, +.5f, 0.5f, 0.0f, - +.5f, -.5f, -.5f, 0.5f, 0.5f, - +.5f, +.5f, -.5f, 1.0f, 0.5f, + // +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 - -.5f, +.5f, +.5f, 0.5f, 0.0f, - -.5f, +.5f, -.5f, 0.5f, 0.5f, - -.5f, -.5f, -.5f, 1.0f, 0.5f, - -.5f, -.5f, -.5f, 1.0f, 0.5f, - -.5f, -.5f, +.5f, 1.0f, 0.0f, - -.5f, +.5f, +.5f, 0.5f, 0.0f, + 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 - +.5f, +.5f, -.5f, 0.5f, 0.5f, - -.5f, +.5f, -.5f, 1.0f, 0.5f, - -.5f, +.5f, +.5f, 1.0f, 0.0f, - -.5f, +.5f, +.5f, 1.0f, 0.0f, - +.5f, +.5f, +.5f, 0.5f, 0.0f, - +.5f, +.5f, -.5f, 0.5f, 0.5f, + 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 - +.5f, -.5f, +.5f, 1.0f, 0.0f, - -.5f, -.5f, +.5f, 0.5f, 0.0f, - -.5f, -.5f, -.5f, 0.5f, 0.5f, - -.5f, -.5f, -.5f, 0.5f, 0.5f, - +.5f, -.5f, -.5f, 1.0f, 0.5f, - +.5f, -.5f, +.5f, 1.0f, 0.0f, + 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 - +.5f, +.5f, +.5f, 0.5f, 0.0f, - -.5f, +.5f, +.5f, 0.0f, 0.0f, - -.5f, -.5f, +.5f, 0.0f, 0.5f, - -.5f, -.5f, +.5f, 0.0f, 0.5f, - +.5f, -.5f, +.5f, 0.5f, 0.5f, - +.5f, +.5f, +.5f, 0.5f, 0.0f, + 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 - +.5f, +.5f, -.5f, 0.5f, 0.5f, - -.5f, +.5f, -.5f, 0.0f, 0.5f, - -.5f, -.5f, -.5f, 0.0f, 1.0f, - -.5f, -.5f, -.5f, 0.0f, 1.0f, - +.5f, -.5f, -.5f, 0.5f, 1.0f, - +.5f, +.5f, -.5f, 0.5f, 0.5f, + 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 = + { + // Cubes + 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)), + // Planes + 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)), + }; + + private VBO tileVbo; + private VBO cubeVbo; + public HexRender(int width, int height) : base(width, height) { Width = width; @@ -70,20 +133,35 @@ namespace hexworld Y = (DisplayDevice.Default.Height - Height) / 2; } + private Random rand = new Random(); + protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); view = Matrix4.LookAt(10 * Vector3.One, Vector3.Zero, Vector3.UnitZ); proj = Matrix4.CreateOrthographic(Width / 100f, Height / 100f, 0, 20); + + for (var i = 0; i < 16; i++) + { + tiles[i].Position.Z += (float) ((rand.NextDouble() - .5) * e.Time); + } + +// tileVbo.Data(tiles, BufferUsageHint.DynamicDraw); + tileVbo.Bind(); + GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr) (0), (IntPtr) (16 * 3 * sizeof(float)), tiles); + VBO.Unbind(); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); - var vbo = new VBO(); - vbo.Data(verts); + cubeVbo = new VBO(); + cubeVbo.Data(cubeVerts, BufferUsageHint.StaticDraw); + + tileVbo = new VBO(); + tileVbo.Data(tiles, BufferUsageHint.DynamicDraw); var vs = new Shader(ShaderType.VertexShader) { @@ -105,17 +183,34 @@ namespace hexworld pgm.Link(); Console.Out.WriteLine(pgm.Log); - vbo.Bind(); - GL.EnableVertexAttribArray(pgm.GetAttribute("pos")); - GL.VertexAttribPointer(pgm.GetAttribute("pos"), 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), + var pos = pgm.GetAttribute("locpos"); + var crd = pgm.GetAttribute("coord"); + 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.EnableVertexAttribArray(pgm.GetAttribute("coord")); - GL.VertexAttribPointer(pgm.GetAttribute("coord"), 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), + 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(); - tex1 = Texture.FromBitmap(new Bitmap("tex.png")); - tex2 = Texture.FromBitmap(new Bitmap("tex2.png")); + grass = Texture.FromBitmap(new Bitmap("grass.png")); + stone = Texture.FromBitmap(new Bitmap("stone.png")); } protected override void OnRenderFrame(FrameEventArgs e) @@ -127,20 +222,22 @@ namespace hexworld GL.Enable(EnableCap.DepthTest); pgm.Use(); - tex1.Bind(0); - tex2.Bind(1); + + grass.Bind(0); + stone.Bind(1); GL.Uniform1(pgm.GetUniform("tex"), 0); - view = Matrix4.CreateTranslation(1,-1,0) * view; GL.UniformMatrix4(pgm.GetUniform("view"), false, ref view); GL.UniformMatrix4(pgm.GetUniform("proj"), false, ref proj); - GL.DrawArrays(PrimitiveType.Triangles, 0, 36); + GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 0, 36, 16, 0); GL.Uniform1(pgm.GetUniform("tex"), 1); - view = Matrix4.CreateTranslation(-2,2,0) * view; GL.UniformMatrix4(pgm.GetUniform("view"), false, ref view); - GL.DrawArrays(PrimitiveType.Triangles, 0, 36); + GL.UniformMatrix4(pgm.GetUniform("proj"), false, ref proj); + +// GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 36, 6, 5, 16); + GL.DrawArraysInstancedBaseInstance(PrimitiveType.Triangles, 0, 36, 5, 16); SwapBuffers(); } diff --git a/hexworld/grass.png b/hexworld/grass.png new file mode 100644 index 0000000..fe2e4dd Binary files /dev/null and b/hexworld/grass.png differ diff --git a/hexworld/hexworld.csproj b/hexworld/hexworld.csproj index 439710c..a20381a 100644 --- a/hexworld/hexworld.csproj +++ b/hexworld/hexworld.csproj @@ -74,12 +74,10 @@ - + Always - - - + Always diff --git a/hexworld/s.fs.glsl b/hexworld/s.fs.glsl index eedf250..67733e3 100644 --- a/hexworld/s.fs.glsl +++ b/hexworld/s.fs.glsl @@ -1,10 +1,12 @@ #version 440 in vec2 vcoord; +in float light; uniform sampler2D tex; void main () { - gl_FragColor = texture(tex, vcoord); + vec4 color = light * texture(tex, vcoord); + gl_FragColor = clamp(color, 0, 1); } \ No newline at end of file diff --git a/hexworld/s.vs.glsl b/hexworld/s.vs.glsl index 8c6ac6e..a3bb41c 100644 --- a/hexworld/s.vs.glsl +++ b/hexworld/s.vs.glsl @@ -1,15 +1,22 @@ #version 440 -in vec3 pos; +in vec3 locpos; +in vec3 glbpos; in vec2 coord; +in vec3 norm; out vec2 vcoord; +out float light; uniform mat4 view; uniform mat4 proj; void main () { - gl_Position = proj*view*vec4(pos, 1); + mat4 pv = proj * view; + vec3 position = glbpos + locpos; + gl_Position = pv * vec4(position, 1); vcoord = coord; + + light = dot(vec3(0, 0, 1), norm) / 2 + .5; } \ No newline at end of file diff --git a/hexworld/stone.png b/hexworld/stone.png new file mode 100644 index 0000000..3d44249 Binary files /dev/null and b/hexworld/stone.png differ diff --git a/hexworld/tex.png b/hexworld/tex.png deleted file mode 100644 index 21b5b4d..0000000 Binary files a/hexworld/tex.png and /dev/null differ diff --git a/hexworld/tex2.png b/hexworld/tex2.png deleted file mode 100644 index 2d3ddb5..0000000 Binary files a/hexworld/tex2.png and /dev/null differ