using System; using System.IO; using OpenTK.Graphics.OpenGL4; using OpenTK; namespace nhengine { public class SquaredMap { private int width, height; private double[] heightMap; private int[] tileTypes; /* GL shared resources */ private int vao, cao, nao, ebo; private int bufVertices; private float[] vertices; private float[] colors, normals; private int[] elements; private ShaderProgram shaderProgram; public SquaredMap(int width,int height) { this.width = width; this.height = height; this.heightMap = new double[getVertexIndex(width,height) + 1]; this.tileTypes = new int[getTileIndex(width,height) + 1]; shaderProgram = new ShaderProgram( new FileStream("shader/simple_vertex.shader",FileMode.Open), new FileStream("shader/simple_fragment.shader",FileMode.Open) ); prepareGL(); computeGL(); dumpGL(); } private void prepareGL(){ vao = GL.GenVertexArray(); cao = GL.GenBuffer(); nao = GL.GenBuffer(); ebo = GL.GenBuffer(); bufVertices = GL.GenBuffer(); } public void computeGL(){ int b; if (vertices == null){ vertices = new float[heightMap.Length * 3]; } if (elements == null){ elements = new int[width * height * 6]; } if (colors == null){ colors = new float[heightMap.Length * 3]; normals = new float[colors.Length]; } Random rand = new Random(); for (int x = 0; x <= width;x++) { for (int y = 0; y <= height;y++){ b = 3 * getVertexIndex(x, y); vertices[b + 0] = 128 * x; vertices[b + 1] = 128 * y; float h = (float)rand.NextDouble(); vertices[b + 2] = (float)(256 * (h * h)); colors[b + 0] = 0.3f + 0.7f * (float)vertices[b + 2] / 256.0f; colors[b + 1] = 0.2f + 0.8f * (float)vertices[b + 2] / 256.0f; colors[b + 2] = 0.4f + 0.6f * (float)vertices[b + 2] / 256.0f; } } for (int x = 0; x < width;x++) { for (int y = 0; y < height;y++){ b = 6 * getTileIndex(x, y); elements[b + 0] = x + (y * (width + 1)); elements[b + 1] = x + (y * (width + 1)) + 1; elements[b + 2] = x + ((y + 1) * (width + 1)); elements[b + 3] = x + ((y + 1) * (width + 1)); elements[b + 4] = x + (y * (width + 1)) + 1; elements[b + 5] = x + ((y + 1) * (width + 1)) + 1; } } GL.BindVertexArray(vao); GL.BindBuffer(BufferTarget.ArrayBuffer, bufVertices); GL.BufferData(BufferTarget.ArrayBuffer, 4 * vertices.Length, vertices, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); GL.BindBuffer(BufferTarget.ArrayBuffer, cao); GL.BufferData(BufferTarget.ArrayBuffer, 4 * colors.Length, colors, BufferUsageHint.StaticDraw); GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0); GL.EnableVertexAttribArray(0); GL.EnableVertexAttribArray(1); GL.BindBuffer(BufferTarget.ElementArrayBuffer,ebo); GL.BufferData(BufferTarget.ElementArrayBuffer, 4 * elements.Length, elements, BufferUsageHint.StaticDraw); GL.BindVertexArray(0); } void dumpGL(){ Console.WriteLine("Vertices:"); for (int x = 0; x < 8;x++){ Console.WriteLine("{0}", vertices[x]); } } private int getTileIndex(int x, int y) { return x + (y * this.width); } private int getVertexIndex(int x,int y){ return x + (y * (this.width + 1)); } private int getTileType(int x, int y) { int ind = getTileIndex(x, y); if ((ind < 0) || (ind > tileTypes.Length)) { return 0; } return this.tileTypes[ind]; } private int getTileType(int ind) { if ((ind < 0) || (ind > tileTypes.Length)) { return 0; } return this.tileTypes[ind]; } private double getHeight(int ind) { if ((ind < 0) || (ind > heightMap.Length)) { return 0; } return this.heightMap[ind]; } public void paint(GLCamera camera){ Matrix4 pmat = camera.Matrix; GL.UseProgram(shaderProgram.ID); int pm = GL.GetUniformLocation(shaderProgram.ID, "proj_matrix"); GL.UniformMatrix4(pm, false, ref pmat); GL.BindVertexArray(vao); GL.DrawElements(BeginMode.Triangles, elements.Length, DrawElementsType.UnsignedInt, 0); GL.BindVertexArray(0); } } }