├── ep 10 ├── Camera.cs ├── Game.cs ├── Graphics │ ├── IBO.cs │ ├── ShaderProgram.cs │ ├── Texture.cs │ ├── VAO.cs │ └── VBO.cs ├── Program.cs ├── Shaders │ ├── Default.frag │ └── Default.vert ├── Textures │ └── atlas.png └── World │ ├── Block.cs │ ├── BlockData.cs │ ├── Chunk.cs │ └── TextureData.cs ├── ep 2 ├── Game.cs └── Program.cs ├── ep 3 ├── Game.cs └── Program.cs ├── ep 4 ├── Game.cs └── Program.cs ├── ep 5 ├── Game.cs └── Program.cs ├── ep 6 ├── Camera.cs ├── Game.cs └── Program.cs ├── ep 7 ├── Camera.cs ├── Game.cs ├── Graphics │ ├── IBO.cs │ ├── ShaderProgram.cs │ ├── Texture.cs │ ├── VAO.cs │ └── VBO.cs └── Program.cs ├── ep 8 ├── Camera.cs ├── Game.cs ├── Graphics │ ├── IBO.cs │ ├── ShaderProgram.cs │ ├── Texture.cs │ ├── VAO.cs │ └── VBO.cs ├── Program.cs ├── Shaders │ ├── Default.frag │ └── Default.vert └── World │ ├── Block.cs │ ├── BlockData.cs │ └── Chunk.cs └── ep 9 ├── Camera.cs ├── Game.cs ├── Graphics ├── IBO.cs ├── ShaderProgram.cs ├── Texture.cs ├── VAO.cs └── VBO.cs ├── Program.cs ├── Shaders ├── Default.frag └── Default.vert └── World ├── Block.cs ├── BlockData.cs └── Chunk.cs /ep 10/Camera.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Windowing.Common; 3 | using OpenTK.Windowing.GraphicsLibraryFramework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj 11 | { 12 | internal class Camera 13 | { 14 | // CONSTANTS 15 | private float SPEED = 8f; 16 | private float SCREENWIDTH; 17 | private float SCREENHEIGHT; 18 | private float SENSITIVITY = 360f; 19 | 20 | // position vars 21 | public Vector3 position; 22 | 23 | Vector3 up = Vector3.UnitY; 24 | Vector3 front = -Vector3.UnitZ; 25 | Vector3 right = Vector3.UnitX; 26 | 27 | // --- view rotations --- 28 | private float pitch; 29 | private float yaw = -90.0f; 30 | 31 | private bool firstMove = true; 32 | public Vector2 lastPos; 33 | public Camera(float width, float height, Vector3 position) { 34 | SCREENWIDTH = width; 35 | SCREENHEIGHT = height; 36 | this.position = position; 37 | } 38 | 39 | public Matrix4 GetViewMatrix() { 40 | return Matrix4.LookAt(position, position + front, up); 41 | } 42 | public Matrix4 GetProjectionMatrix() { 43 | return Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), SCREENWIDTH / SCREENHEIGHT, 0.1f, 100.0f); 44 | } 45 | 46 | private void UpdateVectors() 47 | { 48 | if (pitch > 89.0f) 49 | { 50 | pitch = 89.0f; 51 | } 52 | if (pitch < -89.0f) 53 | { 54 | pitch = -89.0f; 55 | } 56 | 57 | 58 | front.X = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Cos(MathHelper.DegreesToRadians(yaw)); 59 | front.Y = MathF.Sin(MathHelper.DegreesToRadians(pitch)); 60 | front.Z = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Sin(MathHelper.DegreesToRadians(yaw)); 61 | 62 | front = Vector3.Normalize(front); 63 | 64 | right = Vector3.Normalize(Vector3.Cross(front, Vector3.UnitY)); 65 | up = Vector3.Normalize(Vector3.Cross(right, front)); 66 | } 67 | 68 | public void InputController(KeyboardState input, MouseState mouse, FrameEventArgs e) { 69 | 70 | if (input.IsKeyDown(Keys.W)) 71 | { 72 | position += front * SPEED * (float)e.Time; 73 | } 74 | if (input.IsKeyDown(Keys.A)) 75 | { 76 | position -= right * SPEED * (float)e.Time; 77 | } 78 | if (input.IsKeyDown(Keys.S)) 79 | { 80 | position -= front * SPEED * (float)e.Time; 81 | } 82 | if (input.IsKeyDown(Keys.D)) 83 | { 84 | position += right * SPEED * (float)e.Time; 85 | } 86 | 87 | if (input.IsKeyDown(Keys.Space)) 88 | { 89 | position.Y += SPEED * (float)e.Time; 90 | } 91 | if (input.IsKeyDown(Keys.LeftShift)) 92 | { 93 | position.Y -= SPEED * (float)e.Time; 94 | } 95 | 96 | if (firstMove) 97 | { 98 | lastPos = new Vector2(mouse.X, mouse.Y); 99 | firstMove = false; 100 | } else 101 | { 102 | var deltaX = mouse.X - lastPos.X; 103 | var deltaY = mouse.Y - lastPos.Y; 104 | lastPos = new Vector2(mouse.X, mouse.Y); 105 | 106 | yaw += deltaX * SENSITIVITY * (float)e.Time; 107 | pitch -= deltaY * SENSITIVITY * (float)e.Time; 108 | } 109 | UpdateVectors(); 110 | } 111 | public void Update(KeyboardState input, MouseState mouse, FrameEventArgs e) { 112 | InputController(input, mouse, e); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ep 10/Game.cs: -------------------------------------------------------------------------------- 1 |  2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | using OpenTK.Windowing.GraphicsLibraryFramework; 14 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 15 | using Minecraft_Clone_Tutorial_Series_videoproj.World; 16 | 17 | namespace Minecraft_Clone_Tutorial_Series_videoproj 18 | { 19 | // Game class that inherets from the Game Window Class 20 | internal class Game : GameWindow 21 | { 22 | // set of vertices to draw the triangle with (x,y,z) for each vertex 23 | 24 | Chunk chunk; 25 | ShaderProgram program; 26 | 27 | // camera 28 | Camera camera; 29 | 30 | // transformation variables 31 | float yRot = 0f; 32 | 33 | // width and height of screen 34 | int width, height; 35 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 36 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 37 | { 38 | this.width = width; 39 | this.height = height; 40 | 41 | // center window 42 | CenterWindow(new Vector2i(width, height)); 43 | } 44 | // called whenever window is resized 45 | protected override void OnResize(ResizeEventArgs e) 46 | { 47 | base.OnResize(e); 48 | GL.Viewport(0,0, e.Width, e.Height); 49 | this.width = e.Width; 50 | this.height = e.Height; 51 | } 52 | 53 | // called once when game is started 54 | protected override void OnLoad() 55 | { 56 | base.OnLoad(); 57 | 58 | chunk = new Chunk(new Vector3(0, 0, 0)); 59 | program = new ShaderProgram("Default.vert", "Default.frag"); 60 | 61 | GL.Enable(EnableCap.DepthTest); 62 | 63 | GL.FrontFace(FrontFaceDirection.Cw); 64 | GL.Enable(EnableCap.CullFace); 65 | GL.CullFace(CullFaceMode.Back); 66 | 67 | camera = new Camera(width, height, Vector3.Zero); 68 | CursorState = CursorState.Grabbed; 69 | } 70 | // called once when game is closed 71 | protected override void OnUnload() 72 | { 73 | base.OnUnload(); 74 | 75 | chunk.Delete(); 76 | // Delete, VAO, VBO, Shader Program 77 | 78 | } 79 | // called every frame. All rendering happens here 80 | protected override void OnRenderFrame(FrameEventArgs args) 81 | { 82 | // Set the color to fill the screen with 83 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 84 | // Fill the screen with the color 85 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 86 | 87 | 88 | 89 | // transformation matrices 90 | Matrix4 model = Matrix4.Identity; 91 | Matrix4 view = camera.GetViewMatrix(); 92 | Matrix4 projection = camera.GetProjectionMatrix(); 93 | 94 | 95 | int modelLocation = GL.GetUniformLocation(program.ID, "model"); 96 | int viewLocation = GL.GetUniformLocation(program.ID, "view"); 97 | int projectionLocation = GL.GetUniformLocation(program.ID, "projection"); 98 | 99 | GL.UniformMatrix4(modelLocation, true, ref model); 100 | GL.UniformMatrix4(viewLocation, true, ref view); 101 | GL.UniformMatrix4(projectionLocation, true, ref projection); 102 | 103 | chunk.Render(program); 104 | 105 | 106 | // swap the buffers 107 | Context.SwapBuffers(); 108 | 109 | base.OnRenderFrame(args); 110 | } 111 | // called every frame. All updating happens here 112 | protected override void OnUpdateFrame(FrameEventArgs args) 113 | { 114 | MouseState mouse = MouseState; 115 | KeyboardState input = KeyboardState; 116 | 117 | base.OnUpdateFrame(args); 118 | camera.Update(input, mouse, args); 119 | } 120 | 121 | // Function to load a text file and return its contents as a string 122 | 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ep 10/Graphics/IBO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class IBO 11 | { 12 | public int ID; 13 | public IBO(List data) 14 | { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ElementArrayBuffer, data.Count * sizeof(uint), data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public void Bind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); } 20 | public void Unbind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); } 21 | public void Delete() { GL.DeleteBuffer(ID); } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ep 10/Graphics/ShaderProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class ShaderProgram 11 | { 12 | public int ID; 13 | public ShaderProgram(string vertexShaderFilepath, string fragmentShaderFilepath) { 14 | // create the shader program 15 | ID = GL.CreateProgram(); 16 | 17 | // create the vertex shader 18 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 19 | // add the source code from "Default.vert" in the Shaders file 20 | GL.ShaderSource(vertexShader, LoadShaderSource(vertexShaderFilepath)); 21 | // Compile the Shader 22 | GL.CompileShader(vertexShader); 23 | 24 | // Same as vertex shader 25 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 26 | GL.ShaderSource(fragmentShader, LoadShaderSource(fragmentShaderFilepath)); 27 | GL.CompileShader(fragmentShader); 28 | 29 | // Attach the shaders to the shader program 30 | GL.AttachShader(ID, vertexShader); 31 | GL.AttachShader(ID, fragmentShader); 32 | 33 | // Link the program to OpenGL 34 | GL.LinkProgram(ID); 35 | 36 | // delete the shaders 37 | GL.DeleteShader(vertexShader); 38 | GL.DeleteShader(fragmentShader); 39 | } 40 | 41 | public void Bind() { GL.UseProgram(ID); } 42 | public void Unbind() { GL.UseProgram(0); } 43 | public void Delete() { GL.DeleteShader(ID); } 44 | 45 | public static string LoadShaderSource(string filePath) 46 | { 47 | string shaderSource = ""; 48 | 49 | try 50 | { 51 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 52 | { 53 | shaderSource = reader.ReadToEnd(); 54 | } 55 | } 56 | catch (Exception e) 57 | { 58 | Console.WriteLine("Failed to load shader source file: " + e.Message); 59 | } 60 | 61 | return shaderSource; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ep 10/Graphics/Texture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | using StbImageSharp; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class Texture 12 | { 13 | public int ID; 14 | 15 | public Texture(String filepath) 16 | { 17 | ID = GL.GenTexture(); 18 | 19 | GL.ActiveTexture(TextureUnit.Texture0); 20 | GL.BindTexture(TextureTarget.Texture2D, ID); 21 | 22 | // texture parameters 23 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 24 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 25 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 26 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 27 | 28 | StbImage.stbi_set_flip_vertically_on_load(1); 29 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/" + filepath), ColorComponents.RedGreenBlueAlpha); 30 | 31 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 32 | // unbind the texture 33 | Unbind(); 34 | } 35 | 36 | public void Bind() { GL.BindTexture(TextureTarget.Texture2D, ID); } 37 | public void Unbind() { GL.BindTexture(TextureTarget.Texture2D, 0); } 38 | public void Delete() { GL.DeleteTexture(ID); } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ep 10/Graphics/VAO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class VAO 11 | { 12 | public int ID; 13 | public VAO() { 14 | ID = GL.GenVertexArray(); 15 | GL.BindVertexArray(ID); 16 | } 17 | public void LinkToVAO(int location, int size, VBO vbo) 18 | { 19 | Bind(); 20 | vbo.Bind(); 21 | GL.VertexAttribPointer(location, size, VertexAttribPointerType.Float, false, 0, 0); 22 | GL.EnableVertexAttribArray(location); 23 | Unbind(); 24 | } 25 | public void Bind() { GL.BindVertexArray(ID); } 26 | public void Unbind() { GL.BindVertexArray(0); } 27 | public void Delete() { GL.DeleteVertexArray(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 10/Graphics/VBO.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Graphics.OpenGL4; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class VBO 12 | { 13 | public int ID; 14 | public VBO(List data) { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector3.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public VBO(List data) { 20 | ID = GL.GenBuffer(); 21 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 22 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector2.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 23 | } 24 | 25 | public void Bind() { GL.BindBuffer(BufferTarget.ArrayBuffer, ID); } 26 | public void Unbind() { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } 27 | public void Delete() { GL.DeleteBuffer(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 10/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(1280, 720)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 10/Shaders/Default.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 texCoord; 4 | 5 | out vec4 FragColor; 6 | 7 | uniform sampler2D texture0; 8 | 9 | void main() 10 | { 11 | FragColor = texture(texture0, texCoord); 12 | } -------------------------------------------------------------------------------- /ep 10/Shaders/Default.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 aPosition; // vertex coordinates 3 | layout (location = 1) in vec2 aTexCoord; // texture coordinates 4 | 5 | out vec2 texCoord; 6 | 7 | // uniform variables 8 | uniform mat4 model; 9 | uniform mat4 view; 10 | uniform mat4 projection; 11 | 12 | void main() 13 | { 14 | gl_Position = vec4(aPosition, 1.0) * model * view * projection; // coordinates 15 | texCoord = aTexCoord; 16 | } -------------------------------------------------------------------------------- /ep 10/Textures/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vimichael/OpenTK-Minecraft-Clone-Tutorial-Series-Code/6fb9998babe8e46f67564c2478f43a3fa73e112b/ep 10/Textures/atlas.png -------------------------------------------------------------------------------- /ep 10/World/Block.cs: -------------------------------------------------------------------------------- 1 | using MinecraftClone.World; 2 | using OpenTK.Mathematics; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Security.Cryptography.X509Certificates; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 11 | { 12 | internal class Block 13 | { 14 | public Vector3 position; 15 | public BlockType type; 16 | 17 | public Dictionary faces; 18 | 19 | public Dictionary> blockUV = new Dictionary>() 20 | { 21 | {Faces.FRONT, new List() }, 22 | {Faces.BACK, new List() }, 23 | {Faces.LEFT, new List() }, 24 | {Faces.RIGHT, new List() }, 25 | {Faces.TOP, new List() }, 26 | {Faces.BOTTOM, new List() }, 27 | }; 28 | 29 | public Dictionary> GetUVsFromCoordinates(Dictionary coords) 30 | { 31 | Dictionary > faceData = new Dictionary>(); 32 | 33 | foreach (var faceCoord in coords) 34 | { 35 | faceData[faceCoord.Key] = new List() 36 | { 37 | new Vector2((faceCoord.Value.X+1f)/16f, (faceCoord.Value.Y+1f)/16f), 38 | new Vector2(faceCoord.Value.X/16f, (faceCoord.Value.Y+1f)/16f), 39 | new Vector2(faceCoord.Value.X/16f, faceCoord.Value.Y/16f), 40 | new Vector2((faceCoord.Value.X+1f)/16f, faceCoord.Value.Y/16f), 41 | }; 42 | } 43 | 44 | return faceData; 45 | } 46 | 47 | public Block(Vector3 position, BlockType blockType = BlockType.AIR) { 48 | type = blockType; 49 | this.position = position; 50 | 51 | if (blockType != BlockType.AIR) 52 | { 53 | blockUV = GetUVsFromCoordinates(TextureData.blockTypeUVCoord[blockType]); 54 | } 55 | 56 | faces = new Dictionary 57 | { 58 | {Faces.FRONT, new FaceData { 59 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.FRONT]), 60 | uv = blockUV[Faces.FRONT] 61 | } }, 62 | {Faces.BACK, new FaceData { 63 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BACK]), 64 | uv = blockUV[Faces.BACK] 65 | } }, 66 | {Faces.LEFT, new FaceData { 67 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.LEFT]), 68 | uv = blockUV[Faces.LEFT] 69 | } }, 70 | {Faces.RIGHT, new FaceData { 71 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.RIGHT]), 72 | uv = blockUV[Faces.RIGHT] 73 | } }, 74 | {Faces.TOP, new FaceData { 75 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.TOP]), 76 | uv = blockUV[Faces.TOP] 77 | } }, 78 | {Faces.BOTTOM, new FaceData { 79 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BOTTOM]), 80 | uv = blockUV[Faces.BOTTOM] 81 | } }, 82 | 83 | }; 84 | } 85 | public List AddTransformedVertices(List vertices) { 86 | List transformedVertices = new List(); 87 | foreach (var vert in vertices) { 88 | transformedVertices.Add(vert + position); 89 | } 90 | return transformedVertices; 91 | } 92 | public FaceData GetFace(Faces face) { 93 | return faces[face]; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ep 10/World/BlockData.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 9 | { 10 | public enum BlockType 11 | { 12 | DIRT, 13 | GRASS, 14 | AIR 15 | } 16 | public enum Faces 17 | { 18 | FRONT, 19 | BACK, 20 | LEFT, 21 | RIGHT, 22 | TOP, 23 | BOTTOM 24 | } 25 | 26 | public struct FaceData 27 | { 28 | public List vertices; 29 | public List uv; 30 | } 31 | 32 | public struct FaceDataRaw 33 | { 34 | public static readonly Dictionary> rawVertexData = new Dictionary> 35 | { 36 | {Faces.FRONT, new List() 37 | { 38 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 39 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 40 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 41 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 42 | } }, 43 | {Faces.BACK, new List() 44 | { 45 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 46 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 47 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 48 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 49 | } }, 50 | {Faces.LEFT, new List() 51 | { 52 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 53 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 54 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 55 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 56 | } }, 57 | {Faces.RIGHT, new List() 58 | { 59 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 60 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 61 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 62 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 63 | } }, 64 | {Faces.TOP, new List() 65 | { 66 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 67 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 68 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 69 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 70 | } }, 71 | {Faces.BOTTOM, new List() 72 | { 73 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 74 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 75 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 76 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 77 | } }, 78 | }; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /ep 10/World/Chunk.cs: -------------------------------------------------------------------------------- 1 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 2 | using OpenTK.Mathematics; 3 | using OpenTK.Graphics.OpenGL4; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 11 | { 12 | internal class Chunk 13 | { 14 | public List chunkVerts; 15 | public List chunkUVs; 16 | public List chunkIndices; 17 | 18 | const sbyte SIZE = 16; 19 | const short HEIGHT = 384; 20 | public Vector3 position; 21 | 22 | public uint indexCount; 23 | 24 | VAO chunkVAO; 25 | VBO chunkVertexVBO; 26 | VBO chunkUVVBO; 27 | IBO chunkIBO; 28 | 29 | Texture texture; 30 | Block[,,] chunkBlocks = new Block[SIZE, HEIGHT, SIZE]; 31 | public Chunk(Vector3 postition) 32 | { 33 | this.position = postition; 34 | 35 | chunkVerts = new List(); 36 | chunkUVs = new List(); 37 | chunkIndices = new List(); 38 | 39 | float[,] heightmap = GenChunk(); 40 | GenBlocks(heightmap); 41 | GenFaces(heightmap); 42 | BuildChunk(); 43 | } 44 | 45 | public float[,] GenChunk() { 46 | float[,] heightmap = new float[SIZE, SIZE]; 47 | 48 | SimplexNoise.Noise.Seed = 123456; 49 | for (int x = 0; x < SIZE; x++) 50 | { 51 | for (int z = 0; z < SIZE; z++) 52 | { 53 | heightmap[x, z] = SimplexNoise.Noise.CalcPixel2D(x, z, 0.01f); 54 | } 55 | } 56 | 57 | return heightmap; 58 | } 59 | public void GenBlocks(float[,] heightmap) { 60 | for (int x = 0; x < SIZE; x++) 61 | { 62 | for (int z = 0; z < SIZE; z++) 63 | { 64 | int columnHeight = (int)(heightmap[x, z] / 10); 65 | for (int y = 0; y < HEIGHT; y++) 66 | { 67 | BlockType type = BlockType.AIR; 68 | if (y < columnHeight - 1) 69 | { 70 | type = BlockType.DIRT; 71 | } 72 | if (y == columnHeight - 1) 73 | { 74 | type = BlockType.GRASS; 75 | } 76 | 77 | chunkBlocks[x, y, z] = new Block(new Vector3(x, y, z), type); 78 | 79 | } 80 | } 81 | } 82 | } 83 | public void GenFaces(float[,] heightmap) 84 | { 85 | for ( int x = 0; x < SIZE; x++) 86 | { 87 | for ( int z = 0; z < SIZE; z++) 88 | { 89 | for ( int y = 0; y < HEIGHT; y++) 90 | { 91 | int numFaces = 0; 92 | 93 | if (chunkBlocks[x, y, z].type != BlockType.AIR) 94 | { 95 | // Left Faces 96 | if (x > 0) 97 | { 98 | if (chunkBlocks[x - 1, y, z].type == BlockType.AIR) 99 | { 100 | IntegrateFace(chunkBlocks[x, y, z], Faces.LEFT); 101 | numFaces++; 102 | } 103 | } 104 | else 105 | { 106 | IntegrateFace(chunkBlocks[x, y, z], Faces.LEFT); 107 | numFaces++; 108 | } 109 | 110 | // Right Faces 111 | if (x < SIZE - 1) 112 | { 113 | if (chunkBlocks[x + 1, y, z].type == BlockType.AIR) 114 | { 115 | IntegrateFace(chunkBlocks[x, y, z], Faces.RIGHT); 116 | numFaces++; 117 | } 118 | } 119 | else 120 | { 121 | IntegrateFace(chunkBlocks[x, y, z], Faces.RIGHT); 122 | numFaces++; 123 | } 124 | 125 | // Top Faces 126 | if (y < HEIGHT - 1) 127 | { 128 | if (chunkBlocks[x, y + 1, z].type == BlockType.AIR) 129 | { 130 | IntegrateFace(chunkBlocks[x, y, z], Faces.TOP); 131 | numFaces++; 132 | } 133 | } 134 | else 135 | { 136 | IntegrateFace(chunkBlocks[x, y, z], Faces.TOP); 137 | numFaces++; 138 | } 139 | 140 | // Bottom Faces 141 | if (y > 0) 142 | { 143 | if (chunkBlocks[x, y - 1, z].type == BlockType.AIR) 144 | { 145 | IntegrateFace(chunkBlocks[x, y, z], Faces.BOTTOM); 146 | numFaces++; 147 | } 148 | } 149 | else 150 | { 151 | IntegrateFace(chunkBlocks[x, y, z], Faces.BOTTOM); 152 | numFaces++; 153 | } 154 | 155 | // Front Faces 156 | if (z < SIZE - 1) 157 | { 158 | if (chunkBlocks[x, y, z + 1].type == BlockType.AIR) 159 | { 160 | IntegrateFace(chunkBlocks[x, y, z], Faces.FRONT); 161 | numFaces++; 162 | } 163 | } 164 | else 165 | { 166 | IntegrateFace(chunkBlocks[x, y, z], Faces.FRONT); 167 | numFaces++; 168 | } 169 | 170 | // Back Faces 171 | if (z > 0) 172 | { 173 | if (chunkBlocks[x, y, z - 1].type == BlockType.AIR) 174 | { 175 | IntegrateFace(chunkBlocks[x, y, z], Faces.BACK); 176 | numFaces++; 177 | } 178 | } 179 | else 180 | { 181 | IntegrateFace(chunkBlocks[x, y, z], Faces.BACK); 182 | numFaces++; 183 | } 184 | 185 | AddIndices(numFaces); 186 | } 187 | } 188 | } 189 | } 190 | } 191 | 192 | public void IntegrateFace(Block block, Faces face) 193 | { 194 | var faceData = block.GetFace(face); 195 | chunkVerts.AddRange(faceData.vertices); 196 | chunkUVs.AddRange(faceData.uv); 197 | } 198 | 199 | public void AddIndices(int amtFaces) 200 | { 201 | for(int i = 0; i < amtFaces; i++) 202 | { 203 | chunkIndices.Add(0 + indexCount); 204 | chunkIndices.Add(1 + indexCount); 205 | chunkIndices.Add(2 + indexCount); 206 | chunkIndices.Add(2 + indexCount); 207 | chunkIndices.Add(3 + indexCount); 208 | chunkIndices.Add(0 + indexCount); 209 | 210 | indexCount += 4; 211 | } 212 | } 213 | public void BuildChunk() { 214 | chunkVAO = new VAO(); 215 | chunkVAO.Bind(); 216 | 217 | chunkVertexVBO = new VBO(chunkVerts); 218 | chunkVertexVBO.Bind(); 219 | chunkVAO.LinkToVAO(0, 3, chunkVertexVBO); 220 | 221 | chunkUVVBO = new VBO(chunkUVs); 222 | chunkUVVBO.Bind(); 223 | chunkVAO.LinkToVAO(1, 2, chunkUVVBO); 224 | 225 | chunkIBO = new IBO(chunkIndices); 226 | 227 | texture = new Texture("atlas.PNG"); 228 | } // take data and process it for rendering 229 | public void Render(ShaderProgram program) // drawing the chunk 230 | { 231 | program.Bind(); 232 | chunkVAO.Bind(); 233 | chunkIBO.Bind(); 234 | texture.Bind(); 235 | GL.DrawElements(PrimitiveType.Triangles, chunkIndices.Count, DrawElementsType.UnsignedInt, 0); 236 | } 237 | 238 | public void Delete() 239 | { 240 | chunkVAO.Delete(); 241 | chunkVertexVBO.Delete(); 242 | chunkUVVBO.Delete(); 243 | chunkIBO.Delete(); 244 | texture.Delete(); 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /ep 10/World/TextureData.cs: -------------------------------------------------------------------------------- 1 | using Minecraft_Clone_Tutorial_Series_videoproj.World; 2 | using OpenTK.Mathematics; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace MinecraftClone.World 10 | { 11 | internal static class TextureData 12 | { 13 | public static Dictionary> blockTypeUVCoord = new Dictionary>() 14 | { 15 | {BlockType.DIRT, new Dictionary() 16 | { 17 | {Faces.FRONT, new Vector2(2f, 15f) }, 18 | {Faces.LEFT, new Vector2(2f, 15f) }, 19 | {Faces.RIGHT, new Vector2(2f, 15f) }, 20 | {Faces.BACK, new Vector2(2f, 15f) }, 21 | {Faces.TOP, new Vector2(2f, 15f) }, 22 | {Faces.BOTTOM, new Vector2(2f, 15f) }, 23 | } 24 | }, 25 | {BlockType.GRASS, new Dictionary() 26 | { 27 | {Faces.FRONT, new Vector2(3f, 15f) }, 28 | {Faces.LEFT, new Vector2(3f, 15f) }, 29 | {Faces.RIGHT, new Vector2(3f, 15f) }, 30 | {Faces.BACK, new Vector2(3f, 15f) }, 31 | {Faces.TOP, new Vector2(7f, 13f) }, 32 | {Faces.BOTTOM, new Vector2(3f, 15f) }, 33 | } 34 | } 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /ep 2/Game.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Windowing.Desktop; 2 | using OpenTK.Mathematics; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj 10 | { 11 | internal class Game : GameWindow 12 | { 13 | // width and height of screen 14 | int width, height; 15 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 16 | { 17 | this.width = width; 18 | this.height = height; 19 | 20 | // center window 21 | CenterWindow(new Vector2i(width, height)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ep 2/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(500, 500)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 3/Game.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Windowing.Desktop; 2 | using OpenTK.Mathematics; 3 | using OpenTK.Graphics; 4 | using OpenTK.Windowing.Common; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using OpenTK.Windowing.Common; 11 | using OpenTK.Graphics.OpenGL4; 12 | 13 | namespace Minecraft_Clone_Tutorial_Series_videoproj 14 | { 15 | // Game class that inherets from the Game Window Class 16 | internal class Game : GameWindow 17 | { 18 | // set of vertices to draw the triangle with (x,y,z) for each vertex 19 | float[] vertices = 20 | { 21 | 0f, 0.5f, 0f, // top vertex 22 | -0.5f, -0.5f, 0f, // bottom left 23 | 0.5f, -0.5f, 0f // bottom right 24 | }; 25 | 26 | // Render Pipeline vars 27 | int vao; 28 | int shaderProgram; 29 | int vbo; 30 | 31 | // width and height of screen 32 | int width, height; 33 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 34 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 35 | { 36 | this.width = width; 37 | this.height = height; 38 | 39 | // center window 40 | CenterWindow(new Vector2i(width, height)); 41 | } 42 | // called whenever window is resized 43 | protected override void OnResize(ResizeEventArgs e) 44 | { 45 | base.OnResize(e); 46 | GL.Viewport(0,0, e.Width, e.Height); 47 | this.width = e.Width; 48 | this.height = e.Height; 49 | } 50 | 51 | // called once when game is started 52 | protected override void OnLoad() 53 | { 54 | base.OnLoad(); 55 | 56 | // generate the vbo 57 | vao = GL.GenVertexArray(); 58 | 59 | // generate a buffer 60 | vbo = GL.GenBuffer(); 61 | // bind the buffer as an array buffer 62 | GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); 63 | // Store data in the vbo 64 | GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length*sizeof(float), vertices, BufferUsageHint.StaticDraw); 65 | 66 | // bind the vao 67 | GL.BindVertexArray(vao); 68 | // point slot (0) of the VAO to the currently bound VBO (vbo) 69 | GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 70 | // enable the slot 71 | GL.EnableVertexArrayAttrib(vao, 0); 72 | 73 | // unbind the vbo and vao respectively 74 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 75 | GL.BindVertexArray(0); 76 | 77 | // create the shader program 78 | shaderProgram = GL.CreateProgram(); 79 | 80 | // create the vertex shader 81 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 82 | // add the source code from "Default.vert" in the Shaders file 83 | GL.ShaderSource(vertexShader, LoadShaderSource("Default.vert")); 84 | // Compile the Shader 85 | GL.CompileShader(vertexShader); 86 | 87 | // Same as vertex shader 88 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 89 | GL.ShaderSource(fragmentShader, LoadShaderSource("Default.frag")); 90 | GL.CompileShader(fragmentShader); 91 | 92 | // Attach the shaders to the shader program 93 | GL.AttachShader(shaderProgram, vertexShader); 94 | GL.AttachShader(shaderProgram, fragmentShader); 95 | 96 | // Link the program to OpenGL 97 | GL.LinkProgram(shaderProgram); 98 | 99 | // delete the shaders 100 | GL.DeleteShader(vertexShader); 101 | GL.DeleteShader(fragmentShader); 102 | 103 | } 104 | // called once when game is closed 105 | protected override void OnUnload() 106 | { 107 | base.OnUnload(); 108 | 109 | // Delete, VAO, VBO, Shader Program 110 | GL.DeleteVertexArray(vao); 111 | GL.DeleteBuffer(vbo); 112 | GL.DeleteProgram(shaderProgram); 113 | } 114 | // called every frame. All rendering happens here 115 | protected override void OnRenderFrame(FrameEventArgs args) 116 | { 117 | // Set the color to fill the screen with 118 | GL.ClearColor(0.6f, 0.3f, 1f, 1f); 119 | // Fill the screen with the color 120 | GL.Clear(ClearBufferMask.ColorBufferBit); 121 | 122 | 123 | // draw our triangle 124 | GL.UseProgram(shaderProgram); // bind vao 125 | GL.BindVertexArray(vao); // use shader program 126 | GL.DrawArrays(PrimitiveType.Triangles, 0, 3); // draw the triangle | args = Primitive type, first vertex, last vertex 127 | 128 | 129 | // swap the buffers 130 | Context.SwapBuffers(); 131 | 132 | base.OnRenderFrame(args); 133 | } 134 | // called every frame. All updating happens here 135 | protected override void OnUpdateFrame(FrameEventArgs args) 136 | { 137 | base.OnUpdateFrame(args); 138 | } 139 | 140 | // Function to load a text file and return its contents as a string 141 | public static string LoadShaderSource(string filePath) 142 | { 143 | string shaderSource = ""; 144 | 145 | try 146 | { 147 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 148 | { 149 | shaderSource = reader.ReadToEnd(); 150 | } 151 | } 152 | catch (Exception e) 153 | { 154 | Console.WriteLine("Failed to load shader source file: " + e.Message); 155 | } 156 | 157 | return shaderSource; 158 | } 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /ep 3/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(500, 500)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 4/Game.cs: -------------------------------------------------------------------------------- 1 | using StbImageSharp; 2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | 14 | namespace Minecraft_Clone_Tutorial_Series_videoproj 15 | { 16 | // Game class that inherets from the Game Window Class 17 | internal class Game : GameWindow 18 | { 19 | // set of vertices to draw the triangle with (x,y,z) for each vertex 20 | float[] vertices = 21 | { 22 | -0.5f, 0.5f, 0f, // top left vertex - 0 23 | 0.5f, 0.5f, 0f, // top right vertex - 1 24 | 0.5f, -0.5f, 0f, // bottom right - 2 25 | -0.5f, -0.5f, 0f // bottom left - 3 26 | }; 27 | 28 | float[] texCoords = 29 | { 30 | 0f, 1f, 31 | 1f, 1f, 32 | 1f, 0f, 33 | 0f, 0f 34 | }; 35 | 36 | uint[] indices = 37 | { 38 | // top triangle 39 | 0, 1, 2, 40 | // bottom triangle 41 | 2, 3, 0 42 | }; 43 | 44 | // Render Pipeline vars 45 | int vao; 46 | int shaderProgram; 47 | int vbo; 48 | int textureVBO; 49 | int ebo; 50 | int textureID; 51 | 52 | // width and height of screen 53 | int width, height; 54 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 55 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 56 | { 57 | this.width = width; 58 | this.height = height; 59 | 60 | // center window 61 | CenterWindow(new Vector2i(width, height)); 62 | } 63 | // called whenever window is resized 64 | protected override void OnResize(ResizeEventArgs e) 65 | { 66 | base.OnResize(e); 67 | GL.Viewport(0,0, e.Width, e.Height); 68 | this.width = e.Width; 69 | this.height = e.Height; 70 | } 71 | 72 | // called once when game is started 73 | protected override void OnLoad() 74 | { 75 | base.OnLoad(); 76 | 77 | // generate the vbo 78 | vao = GL.GenVertexArray(); 79 | 80 | // bind the vao 81 | GL.BindVertexArray(vao); 82 | 83 | // --- Vertices VBO --- 84 | 85 | // generate a buffer 86 | vbo = GL.GenBuffer(); 87 | // bind the buffer as an array buffer 88 | GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); 89 | // Store data in the vbo 90 | GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length*sizeof(float), vertices, BufferUsageHint.StaticDraw); 91 | 92 | 93 | // put the vertex VBO in slot 0 of our VAO 94 | 95 | // point slot (0) of the VAO to the currently bound VBO (vbo) 96 | GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 97 | // enable the slot 98 | GL.EnableVertexArrayAttrib(vao, 0); 99 | 100 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 101 | 102 | // --- Texture VBO --- 103 | 104 | textureVBO = GL.GenBuffer(); 105 | GL.BindBuffer(BufferTarget.ArrayBuffer, textureVBO); 106 | GL.BufferData(BufferTarget.ArrayBuffer, texCoords.Length * sizeof(float), texCoords, BufferUsageHint.StaticDraw); 107 | 108 | 109 | // put the texture VBO in slot 1 of our VAO 110 | 111 | // point slot (1) of the VAO to the currently bound VBO (vbo) 112 | GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0); 113 | // enable the slot 114 | GL.EnableVertexArrayAttrib(vao, 1); 115 | 116 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 117 | 118 | // unbind the vbo and vao respectively 119 | 120 | GL.BindVertexArray(0); 121 | 122 | 123 | ebo = GL.GenBuffer(); 124 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 125 | GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length*sizeof(uint), indices, BufferUsageHint.StaticDraw); 126 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 127 | 128 | 129 | // create the shader program 130 | shaderProgram = GL.CreateProgram(); 131 | 132 | // create the vertex shader 133 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 134 | // add the source code from "Default.vert" in the Shaders file 135 | GL.ShaderSource(vertexShader, LoadShaderSource("Default.vert")); 136 | // Compile the Shader 137 | GL.CompileShader(vertexShader); 138 | 139 | // Same as vertex shader 140 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 141 | GL.ShaderSource(fragmentShader, LoadShaderSource("Default.frag")); 142 | GL.CompileShader(fragmentShader); 143 | 144 | // Attach the shaders to the shader program 145 | GL.AttachShader(shaderProgram, vertexShader); 146 | GL.AttachShader(shaderProgram, fragmentShader); 147 | 148 | // Link the program to OpenGL 149 | GL.LinkProgram(shaderProgram); 150 | 151 | // delete the shaders 152 | GL.DeleteShader(vertexShader); 153 | GL.DeleteShader(fragmentShader); 154 | 155 | // --- TEXTURES --- 156 | textureID = GL.GenTexture(); 157 | // activate the texture in the unit 158 | GL.ActiveTexture(TextureUnit.Texture0); 159 | GL.BindTexture(TextureTarget.Texture2D, textureID); 160 | 161 | // texture parameters 162 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 163 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 164 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 165 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 166 | 167 | // load image 168 | StbImage.stbi_set_flip_vertically_on_load(1); 169 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/dirtTex.PNG"), ColorComponents.RedGreenBlueAlpha); 170 | 171 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 172 | // unbind the texture 173 | GL.BindTexture(TextureTarget.Texture2D, 0); 174 | } 175 | // called once when game is closed 176 | protected override void OnUnload() 177 | { 178 | base.OnUnload(); 179 | 180 | // Delete, VAO, VBO, Shader Program 181 | GL.DeleteVertexArray(vao); 182 | GL.DeleteBuffer(vbo); 183 | GL.DeleteBuffer(ebo); 184 | GL.DeleteTexture(textureID); 185 | GL.DeleteProgram(shaderProgram); 186 | } 187 | // called every frame. All rendering happens here 188 | protected override void OnRenderFrame(FrameEventArgs args) 189 | { 190 | // Set the color to fill the screen with 191 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 192 | // Fill the screen with the color 193 | GL.Clear(ClearBufferMask.ColorBufferBit); 194 | 195 | 196 | // draw our triangle 197 | GL.UseProgram(shaderProgram); // bind vao 198 | GL.BindVertexArray(vao); // use shader program 199 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 200 | 201 | GL.BindTexture(TextureTarget.Texture2D, textureID); 202 | 203 | GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); 204 | //GL.DrawArrays(PrimitiveType.Triangles, 0, 3); // draw the triangle | args = Primitive type, first vertex, last vertex 205 | 206 | 207 | // swap the buffers 208 | Context.SwapBuffers(); 209 | 210 | base.OnRenderFrame(args); 211 | } 212 | // called every frame. All updating happens here 213 | protected override void OnUpdateFrame(FrameEventArgs args) 214 | { 215 | base.OnUpdateFrame(args); 216 | } 217 | 218 | // Function to load a text file and return its contents as a string 219 | public static string LoadShaderSource(string filePath) 220 | { 221 | string shaderSource = ""; 222 | 223 | try 224 | { 225 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 226 | { 227 | shaderSource = reader.ReadToEnd(); 228 | } 229 | } 230 | catch (Exception e) 231 | { 232 | Console.WriteLine("Failed to load shader source file: " + e.Message); 233 | } 234 | 235 | return shaderSource; 236 | } 237 | 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /ep 4/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(500, 500)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 5/Game.cs: -------------------------------------------------------------------------------- 1 | using StbImageSharp; 2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | 14 | namespace Minecraft_Clone_Tutorial_Series_videoproj 15 | { 16 | // Game class that inherets from the Game Window Class 17 | internal class Game : GameWindow 18 | { 19 | // set of vertices to draw the triangle with (x,y,z) for each vertex 20 | 21 | List vertices = new List() 22 | { 23 | // front face 24 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 25 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 26 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 27 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 28 | // right face 29 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 30 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 31 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 32 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 33 | // back face 34 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 35 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 36 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 37 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 38 | // left face 39 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 40 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 41 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 42 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 43 | // top face 44 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 45 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 46 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 47 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 48 | // bottom face 49 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 50 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 51 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 52 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 53 | }; 54 | 55 | List texCoords = new List() 56 | { 57 | new Vector2(0f, 1f), 58 | new Vector2(1f, 1f), 59 | new Vector2(1f, 0f), 60 | new Vector2(0f, 0f), 61 | 62 | new Vector2(0f, 1f), 63 | new Vector2(1f, 1f), 64 | new Vector2(1f, 0f), 65 | new Vector2(0f, 0f), 66 | 67 | new Vector2(0f, 1f), 68 | new Vector2(1f, 1f), 69 | new Vector2(1f, 0f), 70 | new Vector2(0f, 0f), 71 | 72 | new Vector2(0f, 1f), 73 | new Vector2(1f, 1f), 74 | new Vector2(1f, 0f), 75 | new Vector2(0f, 0f), 76 | 77 | new Vector2(0f, 1f), 78 | new Vector2(1f, 1f), 79 | new Vector2(1f, 0f), 80 | new Vector2(0f, 0f), 81 | 82 | new Vector2(0f, 1f), 83 | new Vector2(1f, 1f), 84 | new Vector2(1f, 0f), 85 | new Vector2(0f, 0f), 86 | }; 87 | 88 | uint[] indices = 89 | { 90 | // first face 91 | // top triangle 92 | 0, 1, 2, 93 | // bottom triangle 94 | 2, 3, 0, 95 | 96 | 4, 5, 6, 97 | 6, 7, 4, 98 | 99 | 8, 9, 10, 100 | 10, 11, 8, 101 | 102 | 12, 13, 14, 103 | 14, 15, 12, 104 | 105 | 16, 17, 18, 106 | 18, 19, 16, 107 | 108 | 20, 21, 22, 109 | 22, 23, 20 110 | }; 111 | 112 | // Render Pipeline vars 113 | int vao; 114 | int shaderProgram; 115 | int vbo; 116 | int textureVBO; 117 | int ebo; 118 | int textureID; 119 | 120 | 121 | // transformation variables 122 | float yRot = 0f; 123 | 124 | // width and height of screen 125 | int width, height; 126 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 127 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 128 | { 129 | this.width = width; 130 | this.height = height; 131 | 132 | // center window 133 | CenterWindow(new Vector2i(width, height)); 134 | } 135 | // called whenever window is resized 136 | protected override void OnResize(ResizeEventArgs e) 137 | { 138 | base.OnResize(e); 139 | GL.Viewport(0,0, e.Width, e.Height); 140 | this.width = e.Width; 141 | this.height = e.Height; 142 | } 143 | 144 | // called once when game is started 145 | protected override void OnLoad() 146 | { 147 | base.OnLoad(); 148 | 149 | // generate the vbo 150 | vao = GL.GenVertexArray(); 151 | 152 | // bind the vao 153 | GL.BindVertexArray(vao); 154 | 155 | // --- Vertices VBO --- 156 | 157 | // generate a buffer 158 | vbo = GL.GenBuffer(); 159 | // bind the buffer as an array buffer 160 | GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); 161 | // Store data in the vbo 162 | GL.BufferData(BufferTarget.ArrayBuffer, vertices.Count * Vector3.SizeInBytes, vertices.ToArray(), BufferUsageHint.StaticDraw); 163 | 164 | 165 | // put the vertex VBO in slot 0 of our VAO 166 | 167 | // point slot (0) of the VAO to the currently bound VBO (vbo) 168 | GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 169 | // enable the slot 170 | GL.EnableVertexArrayAttrib(vao, 0); 171 | 172 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 173 | 174 | // --- Texture VBO --- 175 | 176 | textureVBO = GL.GenBuffer(); 177 | GL.BindBuffer(BufferTarget.ArrayBuffer, textureVBO); 178 | GL.BufferData(BufferTarget.ArrayBuffer, texCoords.Count * Vector2.SizeInBytes, texCoords.ToArray(), BufferUsageHint.StaticDraw); 179 | 180 | 181 | // put the texture VBO in slot 1 of our VAO 182 | 183 | // point slot (1) of the VAO to the currently bound VBO (vbo) 184 | GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0); 185 | // enable the slot 186 | GL.EnableVertexArrayAttrib(vao, 1); 187 | 188 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 189 | 190 | // unbind the vbo and vao respectively 191 | 192 | GL.BindVertexArray(0); 193 | 194 | 195 | ebo = GL.GenBuffer(); 196 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 197 | GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length*sizeof(uint), indices, BufferUsageHint.StaticDraw); 198 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 199 | 200 | 201 | // create the shader program 202 | shaderProgram = GL.CreateProgram(); 203 | 204 | // create the vertex shader 205 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 206 | // add the source code from "Default.vert" in the Shaders file 207 | GL.ShaderSource(vertexShader, LoadShaderSource("Default.vert")); 208 | // Compile the Shader 209 | GL.CompileShader(vertexShader); 210 | 211 | // Same as vertex shader 212 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 213 | GL.ShaderSource(fragmentShader, LoadShaderSource("Default.frag")); 214 | GL.CompileShader(fragmentShader); 215 | 216 | // Attach the shaders to the shader program 217 | GL.AttachShader(shaderProgram, vertexShader); 218 | GL.AttachShader(shaderProgram, fragmentShader); 219 | 220 | // Link the program to OpenGL 221 | GL.LinkProgram(shaderProgram); 222 | 223 | // delete the shaders 224 | GL.DeleteShader(vertexShader); 225 | GL.DeleteShader(fragmentShader); 226 | 227 | // --- TEXTURES --- 228 | textureID = GL.GenTexture(); 229 | // activate the texture in the unit 230 | GL.ActiveTexture(TextureUnit.Texture0); 231 | GL.BindTexture(TextureTarget.Texture2D, textureID); 232 | 233 | // texture parameters 234 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 235 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 236 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 237 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 238 | 239 | // load image 240 | StbImage.stbi_set_flip_vertically_on_load(1); 241 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/dirtTex.PNG"), ColorComponents.RedGreenBlueAlpha); 242 | 243 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 244 | // unbind the texture 245 | GL.BindTexture(TextureTarget.Texture2D, 0); 246 | 247 | GL.Enable(EnableCap.DepthTest); 248 | } 249 | // called once when game is closed 250 | protected override void OnUnload() 251 | { 252 | base.OnUnload(); 253 | 254 | // Delete, VAO, VBO, Shader Program 255 | GL.DeleteVertexArray(vao); 256 | GL.DeleteBuffer(vbo); 257 | GL.DeleteBuffer(ebo); 258 | GL.DeleteTexture(textureID); 259 | GL.DeleteProgram(shaderProgram); 260 | } 261 | // called every frame. All rendering happens here 262 | protected override void OnRenderFrame(FrameEventArgs args) 263 | { 264 | // Set the color to fill the screen with 265 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 266 | // Fill the screen with the color 267 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 268 | 269 | // draw our triangle 270 | GL.UseProgram(shaderProgram); // bind vao 271 | GL.BindVertexArray(vao); // use shader program 272 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 273 | 274 | GL.BindTexture(TextureTarget.Texture2D, textureID); 275 | 276 | 277 | // transformation matrices 278 | Matrix4 model = Matrix4.Identity; 279 | Matrix4 view = Matrix4.Identity; 280 | Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60.0f), width/height, 0.1f, 100.0f); 281 | 282 | 283 | model = Matrix4.CreateRotationY(yRot); 284 | yRot += 0.001f; 285 | 286 | Matrix4 translation = Matrix4.CreateTranslation(0f, 0f, -3f); 287 | 288 | model *= translation; 289 | 290 | int modelLocation = GL.GetUniformLocation(shaderProgram, "model"); 291 | int viewLocation = GL.GetUniformLocation(shaderProgram, "view"); 292 | int projectionLocation = GL.GetUniformLocation(shaderProgram, "projection"); 293 | 294 | GL.UniformMatrix4(modelLocation, true, ref model); 295 | GL.UniformMatrix4(viewLocation, true, ref view); 296 | GL.UniformMatrix4(projectionLocation, true, ref projection); 297 | 298 | GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); 299 | //GL.DrawArrays(PrimitiveType.Triangles, 0, 3); // draw the triangle | args = Primitive type, first vertex, last vertex 300 | 301 | 302 | // swap the buffers 303 | Context.SwapBuffers(); 304 | 305 | base.OnRenderFrame(args); 306 | } 307 | // called every frame. All updating happens here 308 | protected override void OnUpdateFrame(FrameEventArgs args) 309 | { 310 | base.OnUpdateFrame(args); 311 | } 312 | 313 | // Function to load a text file and return its contents as a string 314 | public static string LoadShaderSource(string filePath) 315 | { 316 | string shaderSource = ""; 317 | 318 | try 319 | { 320 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 321 | { 322 | shaderSource = reader.ReadToEnd(); 323 | } 324 | } 325 | catch (Exception e) 326 | { 327 | Console.WriteLine("Failed to load shader source file: " + e.Message); 328 | } 329 | 330 | return shaderSource; 331 | } 332 | 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /ep 5/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(500, 500)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 6/Camera.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Windowing.Common; 3 | using OpenTK.Windowing.GraphicsLibraryFramework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj 11 | { 12 | internal class Camera 13 | { 14 | // CONSTANTS 15 | private float SPEED = 8f; 16 | private float SCREENWIDTH; 17 | private float SCREENHEIGHT; 18 | private float SENSITIVITY = 180f; 19 | 20 | // position vars 21 | public Vector3 position; 22 | 23 | Vector3 up = Vector3.UnitY; 24 | Vector3 front = -Vector3.UnitZ; 25 | Vector3 right = Vector3.UnitX; 26 | 27 | // --- view rotations --- 28 | private float pitch; 29 | private float yaw = -90.0f; 30 | 31 | private bool firstMove = true; 32 | public Vector2 lastPos; 33 | public Camera(float width, float height, Vector3 position) { 34 | SCREENWIDTH = width; 35 | SCREENHEIGHT = height; 36 | this.position = position; 37 | } 38 | 39 | public Matrix4 GetViewMatrix() { 40 | return Matrix4.LookAt(position, position + front, up); 41 | } 42 | public Matrix4 GetProjectionMatrix() { 43 | return Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), SCREENWIDTH / SCREENHEIGHT, 0.1f, 100.0f); 44 | } 45 | 46 | private void UpdateVectors() 47 | { 48 | if (pitch > 89.0f) 49 | { 50 | pitch = 89.0f; 51 | } 52 | if (pitch < -89.0f) 53 | { 54 | pitch = -89.0f; 55 | } 56 | 57 | 58 | front.X = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Cos(MathHelper.DegreesToRadians(yaw)); 59 | front.Y = MathF.Sin(MathHelper.DegreesToRadians(pitch)); 60 | front.Z = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Sin(MathHelper.DegreesToRadians(yaw)); 61 | 62 | front = Vector3.Normalize(front); 63 | 64 | right = Vector3.Normalize(Vector3.Cross(front, Vector3.UnitY)); 65 | up = Vector3.Normalize(Vector3.Cross(right, front)); 66 | } 67 | 68 | public void InputController(KeyboardState input, MouseState mouse, FrameEventArgs e) { 69 | 70 | if (input.IsKeyDown(Keys.W)) 71 | { 72 | position += front * SPEED * (float)e.Time; 73 | } 74 | if (input.IsKeyDown(Keys.A)) 75 | { 76 | position -= right * SPEED * (float)e.Time; 77 | } 78 | if (input.IsKeyDown(Keys.S)) 79 | { 80 | position -= front * SPEED * (float)e.Time; 81 | } 82 | if (input.IsKeyDown(Keys.D)) 83 | { 84 | position += right * SPEED * (float)e.Time; 85 | } 86 | 87 | if (input.IsKeyDown(Keys.Space)) 88 | { 89 | position.Y += SPEED * (float)e.Time; 90 | } 91 | if (input.IsKeyDown(Keys.LeftShift)) 92 | { 93 | position.Y -= SPEED * (float)e.Time; 94 | } 95 | 96 | if (firstMove) 97 | { 98 | lastPos = new Vector2(mouse.X, mouse.Y); 99 | firstMove = false; 100 | } else 101 | { 102 | var deltaX = mouse.X - lastPos.X; 103 | var deltaY = mouse.Y - lastPos.Y; 104 | lastPos = new Vector2(mouse.X, mouse.Y); 105 | 106 | yaw += deltaX * SENSITIVITY * (float)e.Time; 107 | pitch -= deltaY * SENSITIVITY * (float)e.Time; 108 | } 109 | UpdateVectors(); 110 | } 111 | public void Update(KeyboardState input, MouseState mouse, FrameEventArgs e) { 112 | InputController(input, mouse, e); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ep 6/Game.cs: -------------------------------------------------------------------------------- 1 | using StbImageSharp; 2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | using OpenTK.Windowing.GraphicsLibraryFramework; 14 | 15 | namespace Minecraft_Clone_Tutorial_Series_videoproj 16 | { 17 | // Game class that inherets from the Game Window Class 18 | internal class Game : GameWindow 19 | { 20 | // set of vertices to draw the triangle with (x,y,z) for each vertex 21 | 22 | List vertices = new List() 23 | { 24 | // front face 25 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 26 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 27 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 28 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 29 | // right face 30 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 31 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 32 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 33 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 34 | // back face 35 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 36 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 37 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 38 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 39 | // left face 40 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 41 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 42 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 43 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 44 | // top face 45 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 46 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 47 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 48 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 49 | // bottom face 50 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 51 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 52 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 53 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 54 | }; 55 | 56 | List texCoords = new List() 57 | { 58 | new Vector2(0f, 1f), 59 | new Vector2(1f, 1f), 60 | new Vector2(1f, 0f), 61 | new Vector2(0f, 0f), 62 | 63 | new Vector2(0f, 1f), 64 | new Vector2(1f, 1f), 65 | new Vector2(1f, 0f), 66 | new Vector2(0f, 0f), 67 | 68 | new Vector2(0f, 1f), 69 | new Vector2(1f, 1f), 70 | new Vector2(1f, 0f), 71 | new Vector2(0f, 0f), 72 | 73 | new Vector2(0f, 1f), 74 | new Vector2(1f, 1f), 75 | new Vector2(1f, 0f), 76 | new Vector2(0f, 0f), 77 | 78 | new Vector2(0f, 1f), 79 | new Vector2(1f, 1f), 80 | new Vector2(1f, 0f), 81 | new Vector2(0f, 0f), 82 | 83 | new Vector2(0f, 1f), 84 | new Vector2(1f, 1f), 85 | new Vector2(1f, 0f), 86 | new Vector2(0f, 0f), 87 | }; 88 | 89 | uint[] indices = 90 | { 91 | // first face 92 | // top triangle 93 | 0, 1, 2, 94 | // bottom triangle 95 | 2, 3, 0, 96 | 97 | 4, 5, 6, 98 | 6, 7, 4, 99 | 100 | 8, 9, 10, 101 | 10, 11, 8, 102 | 103 | 12, 13, 14, 104 | 14, 15, 12, 105 | 106 | 16, 17, 18, 107 | 18, 19, 16, 108 | 109 | 20, 21, 22, 110 | 22, 23, 20 111 | }; 112 | 113 | // Render Pipeline vars 114 | int vao; 115 | int shaderProgram; 116 | int vbo; 117 | int textureVBO; 118 | int ebo; 119 | int textureID; 120 | 121 | // camera 122 | Camera camera; 123 | 124 | // transformation variables 125 | float yRot = 0f; 126 | 127 | // width and height of screen 128 | int width, height; 129 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 130 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 131 | { 132 | this.width = width; 133 | this.height = height; 134 | 135 | // center window 136 | CenterWindow(new Vector2i(width, height)); 137 | } 138 | // called whenever window is resized 139 | protected override void OnResize(ResizeEventArgs e) 140 | { 141 | base.OnResize(e); 142 | GL.Viewport(0,0, e.Width, e.Height); 143 | this.width = e.Width; 144 | this.height = e.Height; 145 | } 146 | 147 | // called once when game is started 148 | protected override void OnLoad() 149 | { 150 | base.OnLoad(); 151 | 152 | // generate the vbo 153 | vao = GL.GenVertexArray(); 154 | 155 | // bind the vao 156 | GL.BindVertexArray(vao); 157 | 158 | // --- Vertices VBO --- 159 | 160 | // generate a buffer 161 | vbo = GL.GenBuffer(); 162 | // bind the buffer as an array buffer 163 | GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); 164 | // Store data in the vbo 165 | GL.BufferData(BufferTarget.ArrayBuffer, vertices.Count * Vector3.SizeInBytes, vertices.ToArray(), BufferUsageHint.StaticDraw); 166 | 167 | 168 | // put the vertex VBO in slot 0 of our VAO 169 | 170 | // point slot (0) of the VAO to the currently bound VBO (vbo) 171 | GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); 172 | // enable the slot 173 | GL.EnableVertexArrayAttrib(vao, 0); 174 | 175 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 176 | 177 | // --- Texture VBO --- 178 | 179 | textureVBO = GL.GenBuffer(); 180 | GL.BindBuffer(BufferTarget.ArrayBuffer, textureVBO); 181 | GL.BufferData(BufferTarget.ArrayBuffer, texCoords.Count * Vector2.SizeInBytes, texCoords.ToArray(), BufferUsageHint.StaticDraw); 182 | 183 | 184 | // put the texture VBO in slot 1 of our VAO 185 | 186 | // point slot (1) of the VAO to the currently bound VBO (vbo) 187 | GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 0, 0); 188 | // enable the slot 189 | GL.EnableVertexArrayAttrib(vao, 1); 190 | 191 | GL.BindBuffer(BufferTarget.ArrayBuffer, 0); 192 | 193 | // unbind the vbo and vao respectively 194 | 195 | GL.BindVertexArray(0); 196 | 197 | 198 | ebo = GL.GenBuffer(); 199 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 200 | GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length*sizeof(uint), indices, BufferUsageHint.StaticDraw); 201 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); 202 | 203 | 204 | // create the shader program 205 | shaderProgram = GL.CreateProgram(); 206 | 207 | // create the vertex shader 208 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 209 | // add the source code from "Default.vert" in the Shaders file 210 | GL.ShaderSource(vertexShader, LoadShaderSource("Default.vert")); 211 | // Compile the Shader 212 | GL.CompileShader(vertexShader); 213 | 214 | // Same as vertex shader 215 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 216 | GL.ShaderSource(fragmentShader, LoadShaderSource("Default.frag")); 217 | GL.CompileShader(fragmentShader); 218 | 219 | // Attach the shaders to the shader program 220 | GL.AttachShader(shaderProgram, vertexShader); 221 | GL.AttachShader(shaderProgram, fragmentShader); 222 | 223 | // Link the program to OpenGL 224 | GL.LinkProgram(shaderProgram); 225 | 226 | // delete the shaders 227 | GL.DeleteShader(vertexShader); 228 | GL.DeleteShader(fragmentShader); 229 | 230 | // --- TEXTURES --- 231 | textureID = GL.GenTexture(); 232 | // activate the texture in the unit 233 | GL.ActiveTexture(TextureUnit.Texture0); 234 | GL.BindTexture(TextureTarget.Texture2D, textureID); 235 | 236 | // texture parameters 237 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 238 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 239 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 240 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 241 | 242 | // load image 243 | StbImage.stbi_set_flip_vertically_on_load(1); 244 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/dirtTex.PNG"), ColorComponents.RedGreenBlueAlpha); 245 | 246 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 247 | // unbind the texture 248 | GL.BindTexture(TextureTarget.Texture2D, 0); 249 | 250 | GL.Enable(EnableCap.DepthTest); 251 | 252 | camera = new Camera(width, height, Vector3.Zero); 253 | CursorState = CursorState.Grabbed; 254 | } 255 | // called once when game is closed 256 | protected override void OnUnload() 257 | { 258 | base.OnUnload(); 259 | 260 | // Delete, VAO, VBO, Shader Program 261 | GL.DeleteVertexArray(vao); 262 | GL.DeleteBuffer(vbo); 263 | GL.DeleteBuffer(ebo); 264 | GL.DeleteTexture(textureID); 265 | GL.DeleteProgram(shaderProgram); 266 | } 267 | // called every frame. All rendering happens here 268 | protected override void OnRenderFrame(FrameEventArgs args) 269 | { 270 | // Set the color to fill the screen with 271 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 272 | // Fill the screen with the color 273 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 274 | 275 | // draw our triangle 276 | GL.UseProgram(shaderProgram); // bind vao 277 | GL.BindVertexArray(vao); // use shader program 278 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); 279 | 280 | GL.BindTexture(TextureTarget.Texture2D, textureID); 281 | 282 | 283 | // transformation matrices 284 | Matrix4 model = Matrix4.Identity; 285 | Matrix4 view = camera.GetViewMatrix(); 286 | Matrix4 projection = camera.GetProjectionMatrix(); 287 | 288 | 289 | model = Matrix4.CreateRotationY(yRot); 290 | yRot += 0.001f; 291 | 292 | Matrix4 translation = Matrix4.CreateTranslation(0f, 0f, -3f); 293 | 294 | model *= translation; 295 | 296 | int modelLocation = GL.GetUniformLocation(shaderProgram, "model"); 297 | int viewLocation = GL.GetUniformLocation(shaderProgram, "view"); 298 | int projectionLocation = GL.GetUniformLocation(shaderProgram, "projection"); 299 | 300 | GL.UniformMatrix4(modelLocation, true, ref model); 301 | GL.UniformMatrix4(viewLocation, true, ref view); 302 | GL.UniformMatrix4(projectionLocation, true, ref projection); 303 | 304 | GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); 305 | //GL.DrawArrays(PrimitiveType.Triangles, 0, 3); // draw the triangle | args = Primitive type, first vertex, last vertex 306 | 307 | 308 | // swap the buffers 309 | Context.SwapBuffers(); 310 | 311 | base.OnRenderFrame(args); 312 | } 313 | // called every frame. All updating happens here 314 | protected override void OnUpdateFrame(FrameEventArgs args) 315 | { 316 | MouseState mouse = MouseState; 317 | KeyboardState input = KeyboardState; 318 | 319 | base.OnUpdateFrame(args); 320 | camera.Update(input, mouse, args); 321 | } 322 | 323 | // Function to load a text file and return its contents as a string 324 | public static string LoadShaderSource(string filePath) 325 | { 326 | string shaderSource = ""; 327 | 328 | try 329 | { 330 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 331 | { 332 | shaderSource = reader.ReadToEnd(); 333 | } 334 | } 335 | catch (Exception e) 336 | { 337 | Console.WriteLine("Failed to load shader source file: " + e.Message); 338 | } 339 | 340 | return shaderSource; 341 | } 342 | 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /ep 6/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(1280, 720)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 7/Camera.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Windowing.Common; 3 | using OpenTK.Windowing.GraphicsLibraryFramework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj 11 | { 12 | internal class Camera 13 | { 14 | // CONSTANTS 15 | private float SPEED = 8f; 16 | private float SCREENWIDTH; 17 | private float SCREENHEIGHT; 18 | private float SENSITIVITY = 180f; 19 | 20 | // position vars 21 | public Vector3 position; 22 | 23 | Vector3 up = Vector3.UnitY; 24 | Vector3 front = -Vector3.UnitZ; 25 | Vector3 right = Vector3.UnitX; 26 | 27 | // --- view rotations --- 28 | private float pitch; 29 | private float yaw = -90.0f; 30 | 31 | private bool firstMove = true; 32 | public Vector2 lastPos; 33 | public Camera(float width, float height, Vector3 position) { 34 | SCREENWIDTH = width; 35 | SCREENHEIGHT = height; 36 | this.position = position; 37 | } 38 | 39 | public Matrix4 GetViewMatrix() { 40 | return Matrix4.LookAt(position, position + front, up); 41 | } 42 | public Matrix4 GetProjectionMatrix() { 43 | return Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), SCREENWIDTH / SCREENHEIGHT, 0.1f, 100.0f); 44 | } 45 | 46 | private void UpdateVectors() 47 | { 48 | if (pitch > 89.0f) 49 | { 50 | pitch = 89.0f; 51 | } 52 | if (pitch < -89.0f) 53 | { 54 | pitch = -89.0f; 55 | } 56 | 57 | 58 | front.X = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Cos(MathHelper.DegreesToRadians(yaw)); 59 | front.Y = MathF.Sin(MathHelper.DegreesToRadians(pitch)); 60 | front.Z = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Sin(MathHelper.DegreesToRadians(yaw)); 61 | 62 | front = Vector3.Normalize(front); 63 | 64 | right = Vector3.Normalize(Vector3.Cross(front, Vector3.UnitY)); 65 | up = Vector3.Normalize(Vector3.Cross(right, front)); 66 | } 67 | 68 | public void InputController(KeyboardState input, MouseState mouse, FrameEventArgs e) { 69 | 70 | if (input.IsKeyDown(Keys.W)) 71 | { 72 | position += front * SPEED * (float)e.Time; 73 | } 74 | if (input.IsKeyDown(Keys.A)) 75 | { 76 | position -= right * SPEED * (float)e.Time; 77 | } 78 | if (input.IsKeyDown(Keys.S)) 79 | { 80 | position -= front * SPEED * (float)e.Time; 81 | } 82 | if (input.IsKeyDown(Keys.D)) 83 | { 84 | position += right * SPEED * (float)e.Time; 85 | } 86 | 87 | if (input.IsKeyDown(Keys.Space)) 88 | { 89 | position.Y += SPEED * (float)e.Time; 90 | } 91 | if (input.IsKeyDown(Keys.LeftShift)) 92 | { 93 | position.Y -= SPEED * (float)e.Time; 94 | } 95 | 96 | if (firstMove) 97 | { 98 | lastPos = new Vector2(mouse.X, mouse.Y); 99 | firstMove = false; 100 | } else 101 | { 102 | var deltaX = mouse.X - lastPos.X; 103 | var deltaY = mouse.Y - lastPos.Y; 104 | lastPos = new Vector2(mouse.X, mouse.Y); 105 | 106 | yaw += deltaX * SENSITIVITY * (float)e.Time; 107 | pitch -= deltaY * SENSITIVITY * (float)e.Time; 108 | } 109 | UpdateVectors(); 110 | } 111 | public void Update(KeyboardState input, MouseState mouse, FrameEventArgs e) { 112 | InputController(input, mouse, e); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ep 7/Game.cs: -------------------------------------------------------------------------------- 1 |  2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | using OpenTK.Windowing.GraphicsLibraryFramework; 14 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 15 | 16 | namespace Minecraft_Clone_Tutorial_Series_videoproj 17 | { 18 | // Game class that inherets from the Game Window Class 19 | internal class Game : GameWindow 20 | { 21 | // set of vertices to draw the triangle with (x,y,z) for each vertex 22 | 23 | List vertices = new List() 24 | { 25 | // front face 26 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 27 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 28 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 29 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 30 | // right face 31 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 32 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 33 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 34 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 35 | // back face 36 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 37 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 38 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 39 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 40 | // left face 41 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 42 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 43 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 44 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 45 | // top face 46 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 47 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 48 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 49 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 50 | // bottom face 51 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 52 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 53 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 54 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 55 | }; 56 | 57 | List texCoords = new List() 58 | { 59 | new Vector2(0f, 1f), 60 | new Vector2(1f, 1f), 61 | new Vector2(1f, 0f), 62 | new Vector2(0f, 0f), 63 | 64 | new Vector2(0f, 1f), 65 | new Vector2(1f, 1f), 66 | new Vector2(1f, 0f), 67 | new Vector2(0f, 0f), 68 | 69 | new Vector2(0f, 1f), 70 | new Vector2(1f, 1f), 71 | new Vector2(1f, 0f), 72 | new Vector2(0f, 0f), 73 | 74 | new Vector2(0f, 1f), 75 | new Vector2(1f, 1f), 76 | new Vector2(1f, 0f), 77 | new Vector2(0f, 0f), 78 | 79 | new Vector2(0f, 1f), 80 | new Vector2(1f, 1f), 81 | new Vector2(1f, 0f), 82 | new Vector2(0f, 0f), 83 | 84 | new Vector2(0f, 1f), 85 | new Vector2(1f, 1f), 86 | new Vector2(1f, 0f), 87 | new Vector2(0f, 0f), 88 | }; 89 | 90 | List indices = new List 91 | { 92 | // first face 93 | // top triangle 94 | 0, 1, 2, 95 | // bottom triangle 96 | 2, 3, 0, 97 | 98 | 4, 5, 6, 99 | 6, 7, 4, 100 | 101 | 8, 9, 10, 102 | 10, 11, 8, 103 | 104 | 12, 13, 14, 105 | 14, 15, 12, 106 | 107 | 16, 17, 18, 108 | 18, 19, 16, 109 | 110 | 20, 21, 22, 111 | 22, 23, 20 112 | }; 113 | 114 | // Render Pipeline vars 115 | VAO vao; 116 | IBO ibo; 117 | ShaderProgram program; 118 | Texture texture; 119 | 120 | // camera 121 | Camera camera; 122 | 123 | // transformation variables 124 | float yRot = 0f; 125 | 126 | // width and height of screen 127 | int width, height; 128 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 129 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 130 | { 131 | this.width = width; 132 | this.height = height; 133 | 134 | // center window 135 | CenterWindow(new Vector2i(width, height)); 136 | } 137 | // called whenever window is resized 138 | protected override void OnResize(ResizeEventArgs e) 139 | { 140 | base.OnResize(e); 141 | GL.Viewport(0,0, e.Width, e.Height); 142 | this.width = e.Width; 143 | this.height = e.Height; 144 | } 145 | 146 | // called once when game is started 147 | protected override void OnLoad() 148 | { 149 | base.OnLoad(); 150 | 151 | vao = new VAO(); 152 | 153 | VBO vbo = new VBO(vertices); 154 | vao.LinkToVAO(0, 3, vbo); 155 | VBO uvVBO = new VBO(texCoords); 156 | vao.LinkToVAO(1, 2, uvVBO); 157 | 158 | ibo = new IBO(indices); 159 | 160 | program = new ShaderProgram("Default.vert", "Default.frag"); 161 | 162 | texture = new Texture("dirtTex.PNG"); 163 | 164 | 165 | GL.Enable(EnableCap.DepthTest); 166 | 167 | camera = new Camera(width, height, Vector3.Zero); 168 | CursorState = CursorState.Grabbed; 169 | } 170 | // called once when game is closed 171 | protected override void OnUnload() 172 | { 173 | base.OnUnload(); 174 | 175 | vao.Delete(); 176 | ibo.Delete(); 177 | texture.Delete(); 178 | program.Delete(); 179 | // Delete, VAO, VBO, Shader Program 180 | 181 | } 182 | // called every frame. All rendering happens here 183 | protected override void OnRenderFrame(FrameEventArgs args) 184 | { 185 | // Set the color to fill the screen with 186 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 187 | // Fill the screen with the color 188 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 189 | 190 | 191 | program.Bind(); 192 | vao.Bind(); 193 | texture.Bind(); 194 | ibo.Bind(); 195 | 196 | // transformation matrices 197 | Matrix4 model = Matrix4.Identity; 198 | Matrix4 view = camera.GetViewMatrix(); 199 | Matrix4 projection = camera.GetProjectionMatrix(); 200 | 201 | 202 | model = Matrix4.CreateRotationY(yRot); 203 | yRot += 0.001f; 204 | 205 | Matrix4 translation = Matrix4.CreateTranslation(0f, 0f, -3f); 206 | 207 | model *= translation; 208 | 209 | int modelLocation = GL.GetUniformLocation(program.ID, "model"); 210 | int viewLocation = GL.GetUniformLocation(program.ID, "view"); 211 | int projectionLocation = GL.GetUniformLocation(program.ID, "projection"); 212 | 213 | GL.UniformMatrix4(modelLocation, true, ref model); 214 | GL.UniformMatrix4(viewLocation, true, ref view); 215 | GL.UniformMatrix4(projectionLocation, true, ref projection); 216 | 217 | GL.DrawElements(PrimitiveType.Triangles, indices.Count, DrawElementsType.UnsignedInt, 0); 218 | 219 | model += Matrix4.CreateTranslation(new Vector3(2f, 0f, 0f)); 220 | GL.UniformMatrix4(modelLocation, true, ref model); 221 | GL.DrawElements(PrimitiveType.Triangles, indices.Count, DrawElementsType.UnsignedInt, 0); 222 | //GL.DrawArrays(PrimitiveType.Triangles, 0, 3); // draw the triangle | args = Primitive type, first vertex, last vertex 223 | 224 | 225 | // swap the buffers 226 | Context.SwapBuffers(); 227 | 228 | base.OnRenderFrame(args); 229 | } 230 | // called every frame. All updating happens here 231 | protected override void OnUpdateFrame(FrameEventArgs args) 232 | { 233 | MouseState mouse = MouseState; 234 | KeyboardState input = KeyboardState; 235 | 236 | base.OnUpdateFrame(args); 237 | camera.Update(input, mouse, args); 238 | } 239 | 240 | // Function to load a text file and return its contents as a string 241 | 242 | 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /ep 7/Graphics/IBO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class IBO 11 | { 12 | public int ID; 13 | public IBO(List data) 14 | { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ElementArrayBuffer, data.Count * sizeof(uint), data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public void Bind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); } 20 | public void Unbind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); } 21 | public void Delete() { GL.DeleteBuffer(ID); } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ep 7/Graphics/ShaderProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class ShaderProgram 11 | { 12 | public int ID; 13 | public ShaderProgram(string vertexShaderFilepath, string fragmentShaderFilepath) { 14 | // create the shader program 15 | ID = GL.CreateProgram(); 16 | 17 | // create the vertex shader 18 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 19 | // add the source code from "Default.vert" in the Shaders file 20 | GL.ShaderSource(vertexShader, LoadShaderSource(vertexShaderFilepath)); 21 | // Compile the Shader 22 | GL.CompileShader(vertexShader); 23 | 24 | // Same as vertex shader 25 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 26 | GL.ShaderSource(fragmentShader, LoadShaderSource(fragmentShaderFilepath)); 27 | GL.CompileShader(fragmentShader); 28 | 29 | // Attach the shaders to the shader program 30 | GL.AttachShader(ID, vertexShader); 31 | GL.AttachShader(ID, fragmentShader); 32 | 33 | // Link the program to OpenGL 34 | GL.LinkProgram(ID); 35 | 36 | // delete the shaders 37 | GL.DeleteShader(vertexShader); 38 | GL.DeleteShader(fragmentShader); 39 | } 40 | 41 | public void Bind() { GL.UseProgram(ID); } 42 | public void Unbind() { GL.UseProgram(0); } 43 | public void Delete() { GL.DeleteShader(ID); } 44 | 45 | public static string LoadShaderSource(string filePath) 46 | { 47 | string shaderSource = ""; 48 | 49 | try 50 | { 51 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 52 | { 53 | shaderSource = reader.ReadToEnd(); 54 | } 55 | } 56 | catch (Exception e) 57 | { 58 | Console.WriteLine("Failed to load shader source file: " + e.Message); 59 | } 60 | 61 | return shaderSource; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ep 7/Graphics/Texture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | using StbImageSharp; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class Texture 12 | { 13 | public int ID; 14 | 15 | public Texture(String filepath) 16 | { 17 | ID = GL.GenTexture(); 18 | 19 | GL.ActiveTexture(TextureUnit.Texture0); 20 | GL.BindTexture(TextureTarget.Texture2D, ID); 21 | 22 | // texture parameters 23 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 24 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 25 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 26 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 27 | 28 | StbImage.stbi_set_flip_vertically_on_load(1); 29 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/" + filepath), ColorComponents.RedGreenBlueAlpha); 30 | 31 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 32 | // unbind the texture 33 | Unbind(); 34 | } 35 | 36 | public void Bind() { GL.BindTexture(TextureTarget.Texture2D, ID); } 37 | public void Unbind() { GL.BindTexture(TextureTarget.Texture2D, 0); } 38 | public void Delete() { GL.DeleteTexture(ID); } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ep 7/Graphics/VAO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class VAO 11 | { 12 | public int ID; 13 | public VAO() { 14 | ID = GL.GenVertexArray(); 15 | GL.BindVertexArray(ID); 16 | } 17 | public void LinkToVAO(int location, int size, VBO vbo) 18 | { 19 | Bind(); 20 | vbo.Bind(); 21 | GL.VertexAttribPointer(location, size, VertexAttribPointerType.Float, false, 0, 0); 22 | GL.EnableVertexAttribArray(location); 23 | Unbind(); 24 | } 25 | public void Bind() { GL.BindVertexArray(ID); } 26 | public void Unbind() { GL.BindVertexArray(0); } 27 | public void Delete() { GL.DeleteVertexArray(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 7/Graphics/VBO.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Graphics.OpenGL4; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class VBO 12 | { 13 | public int ID; 14 | public VBO(List data) { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector3.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public VBO(List data) { 20 | ID = GL.GenBuffer(); 21 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 22 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector2.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 23 | } 24 | 25 | public void Bind() { GL.BindBuffer(BufferTarget.ArrayBuffer, ID); } 26 | public void Unbind() { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } 27 | public void Delete() { GL.DeleteBuffer(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 7/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(1280, 720)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 8/Camera.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Windowing.Common; 3 | using OpenTK.Windowing.GraphicsLibraryFramework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj 11 | { 12 | internal class Camera 13 | { 14 | // CONSTANTS 15 | private float SPEED = 8f; 16 | private float SCREENWIDTH; 17 | private float SCREENHEIGHT; 18 | private float SENSITIVITY = 180f; 19 | 20 | // position vars 21 | public Vector3 position; 22 | 23 | Vector3 up = Vector3.UnitY; 24 | Vector3 front = -Vector3.UnitZ; 25 | Vector3 right = Vector3.UnitX; 26 | 27 | // --- view rotations --- 28 | private float pitch; 29 | private float yaw = -90.0f; 30 | 31 | private bool firstMove = true; 32 | public Vector2 lastPos; 33 | public Camera(float width, float height, Vector3 position) { 34 | SCREENWIDTH = width; 35 | SCREENHEIGHT = height; 36 | this.position = position; 37 | } 38 | 39 | public Matrix4 GetViewMatrix() { 40 | return Matrix4.LookAt(position, position + front, up); 41 | } 42 | public Matrix4 GetProjectionMatrix() { 43 | return Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), SCREENWIDTH / SCREENHEIGHT, 0.1f, 100.0f); 44 | } 45 | 46 | private void UpdateVectors() 47 | { 48 | if (pitch > 89.0f) 49 | { 50 | pitch = 89.0f; 51 | } 52 | if (pitch < -89.0f) 53 | { 54 | pitch = -89.0f; 55 | } 56 | 57 | 58 | front.X = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Cos(MathHelper.DegreesToRadians(yaw)); 59 | front.Y = MathF.Sin(MathHelper.DegreesToRadians(pitch)); 60 | front.Z = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Sin(MathHelper.DegreesToRadians(yaw)); 61 | 62 | front = Vector3.Normalize(front); 63 | 64 | right = Vector3.Normalize(Vector3.Cross(front, Vector3.UnitY)); 65 | up = Vector3.Normalize(Vector3.Cross(right, front)); 66 | } 67 | 68 | public void InputController(KeyboardState input, MouseState mouse, FrameEventArgs e) { 69 | 70 | if (input.IsKeyDown(Keys.W)) 71 | { 72 | position += front * SPEED * (float)e.Time; 73 | } 74 | if (input.IsKeyDown(Keys.A)) 75 | { 76 | position -= right * SPEED * (float)e.Time; 77 | } 78 | if (input.IsKeyDown(Keys.S)) 79 | { 80 | position -= front * SPEED * (float)e.Time; 81 | } 82 | if (input.IsKeyDown(Keys.D)) 83 | { 84 | position += right * SPEED * (float)e.Time; 85 | } 86 | 87 | if (input.IsKeyDown(Keys.Space)) 88 | { 89 | position.Y += SPEED * (float)e.Time; 90 | } 91 | if (input.IsKeyDown(Keys.LeftShift)) 92 | { 93 | position.Y -= SPEED * (float)e.Time; 94 | } 95 | 96 | if (firstMove) 97 | { 98 | lastPos = new Vector2(mouse.X, mouse.Y); 99 | firstMove = false; 100 | } else 101 | { 102 | var deltaX = mouse.X - lastPos.X; 103 | var deltaY = mouse.Y - lastPos.Y; 104 | lastPos = new Vector2(mouse.X, mouse.Y); 105 | 106 | yaw += deltaX * SENSITIVITY * (float)e.Time; 107 | pitch -= deltaY * SENSITIVITY * (float)e.Time; 108 | } 109 | UpdateVectors(); 110 | } 111 | public void Update(KeyboardState input, MouseState mouse, FrameEventArgs e) { 112 | InputController(input, mouse, e); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ep 8/Game.cs: -------------------------------------------------------------------------------- 1 |  2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | using OpenTK.Windowing.GraphicsLibraryFramework; 14 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 15 | using Minecraft_Clone_Tutorial_Series_videoproj.World; 16 | 17 | namespace Minecraft_Clone_Tutorial_Series_videoproj 18 | { 19 | // Game class that inherets from the Game Window Class 20 | internal class Game : GameWindow 21 | { 22 | // set of vertices to draw the triangle with (x,y,z) for each vertex 23 | 24 | Chunk chunk; 25 | ShaderProgram program; 26 | 27 | // camera 28 | Camera camera; 29 | 30 | // transformation variables 31 | float yRot = 0f; 32 | 33 | // width and height of screen 34 | int width, height; 35 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 36 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 37 | { 38 | this.width = width; 39 | this.height = height; 40 | 41 | // center window 42 | CenterWindow(new Vector2i(width, height)); 43 | } 44 | // called whenever window is resized 45 | protected override void OnResize(ResizeEventArgs e) 46 | { 47 | base.OnResize(e); 48 | GL.Viewport(0,0, e.Width, e.Height); 49 | this.width = e.Width; 50 | this.height = e.Height; 51 | } 52 | 53 | // called once when game is started 54 | protected override void OnLoad() 55 | { 56 | base.OnLoad(); 57 | 58 | chunk = new Chunk(new Vector3(0, 0, 0)); 59 | program = new ShaderProgram("Default.vert", "Default.frag"); 60 | 61 | GL.Enable(EnableCap.DepthTest); 62 | 63 | camera = new Camera(width, height, Vector3.Zero); 64 | CursorState = CursorState.Grabbed; 65 | } 66 | // called once when game is closed 67 | protected override void OnUnload() 68 | { 69 | base.OnUnload(); 70 | 71 | chunk.Delete(); 72 | // Delete, VAO, VBO, Shader Program 73 | 74 | } 75 | // called every frame. All rendering happens here 76 | protected override void OnRenderFrame(FrameEventArgs args) 77 | { 78 | // Set the color to fill the screen with 79 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 80 | // Fill the screen with the color 81 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 82 | 83 | 84 | 85 | // transformation matrices 86 | Matrix4 model = Matrix4.Identity; 87 | Matrix4 view = camera.GetViewMatrix(); 88 | Matrix4 projection = camera.GetProjectionMatrix(); 89 | 90 | 91 | int modelLocation = GL.GetUniformLocation(program.ID, "model"); 92 | int viewLocation = GL.GetUniformLocation(program.ID, "view"); 93 | int projectionLocation = GL.GetUniformLocation(program.ID, "projection"); 94 | 95 | GL.UniformMatrix4(modelLocation, true, ref model); 96 | GL.UniformMatrix4(viewLocation, true, ref view); 97 | GL.UniformMatrix4(projectionLocation, true, ref projection); 98 | 99 | chunk.Render(program); 100 | 101 | 102 | // swap the buffers 103 | Context.SwapBuffers(); 104 | 105 | base.OnRenderFrame(args); 106 | } 107 | // called every frame. All updating happens here 108 | protected override void OnUpdateFrame(FrameEventArgs args) 109 | { 110 | MouseState mouse = MouseState; 111 | KeyboardState input = KeyboardState; 112 | 113 | base.OnUpdateFrame(args); 114 | camera.Update(input, mouse, args); 115 | } 116 | 117 | // Function to load a text file and return its contents as a string 118 | 119 | 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /ep 8/Graphics/IBO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class IBO 11 | { 12 | public int ID; 13 | public IBO(List data) 14 | { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ElementArrayBuffer, data.Count * sizeof(uint), data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public void Bind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); } 20 | public void Unbind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); } 21 | public void Delete() { GL.DeleteBuffer(ID); } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ep 8/Graphics/ShaderProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class ShaderProgram 11 | { 12 | public int ID; 13 | public ShaderProgram(string vertexShaderFilepath, string fragmentShaderFilepath) { 14 | // create the shader program 15 | ID = GL.CreateProgram(); 16 | 17 | // create the vertex shader 18 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 19 | // add the source code from "Default.vert" in the Shaders file 20 | GL.ShaderSource(vertexShader, LoadShaderSource(vertexShaderFilepath)); 21 | // Compile the Shader 22 | GL.CompileShader(vertexShader); 23 | 24 | // Same as vertex shader 25 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 26 | GL.ShaderSource(fragmentShader, LoadShaderSource(fragmentShaderFilepath)); 27 | GL.CompileShader(fragmentShader); 28 | 29 | // Attach the shaders to the shader program 30 | GL.AttachShader(ID, vertexShader); 31 | GL.AttachShader(ID, fragmentShader); 32 | 33 | // Link the program to OpenGL 34 | GL.LinkProgram(ID); 35 | 36 | // delete the shaders 37 | GL.DeleteShader(vertexShader); 38 | GL.DeleteShader(fragmentShader); 39 | } 40 | 41 | public void Bind() { GL.UseProgram(ID); } 42 | public void Unbind() { GL.UseProgram(0); } 43 | public void Delete() { GL.DeleteShader(ID); } 44 | 45 | public static string LoadShaderSource(string filePath) 46 | { 47 | string shaderSource = ""; 48 | 49 | try 50 | { 51 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 52 | { 53 | shaderSource = reader.ReadToEnd(); 54 | } 55 | } 56 | catch (Exception e) 57 | { 58 | Console.WriteLine("Failed to load shader source file: " + e.Message); 59 | } 60 | 61 | return shaderSource; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ep 8/Graphics/Texture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | using StbImageSharp; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class Texture 12 | { 13 | public int ID; 14 | 15 | public Texture(String filepath) 16 | { 17 | ID = GL.GenTexture(); 18 | 19 | GL.ActiveTexture(TextureUnit.Texture0); 20 | GL.BindTexture(TextureTarget.Texture2D, ID); 21 | 22 | // texture parameters 23 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 24 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 25 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 26 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 27 | 28 | StbImage.stbi_set_flip_vertically_on_load(1); 29 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/" + filepath), ColorComponents.RedGreenBlueAlpha); 30 | 31 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 32 | // unbind the texture 33 | Unbind(); 34 | } 35 | 36 | public void Bind() { GL.BindTexture(TextureTarget.Texture2D, ID); } 37 | public void Unbind() { GL.BindTexture(TextureTarget.Texture2D, 0); } 38 | public void Delete() { GL.DeleteTexture(ID); } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ep 8/Graphics/VAO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class VAO 11 | { 12 | public int ID; 13 | public VAO() { 14 | ID = GL.GenVertexArray(); 15 | GL.BindVertexArray(ID); 16 | } 17 | public void LinkToVAO(int location, int size, VBO vbo) 18 | { 19 | Bind(); 20 | vbo.Bind(); 21 | GL.VertexAttribPointer(location, size, VertexAttribPointerType.Float, false, 0, 0); 22 | GL.EnableVertexAttribArray(location); 23 | Unbind(); 24 | } 25 | public void Bind() { GL.BindVertexArray(ID); } 26 | public void Unbind() { GL.BindVertexArray(0); } 27 | public void Delete() { GL.DeleteVertexArray(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 8/Graphics/VBO.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Graphics.OpenGL4; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class VBO 12 | { 13 | public int ID; 14 | public VBO(List data) { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector3.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public VBO(List data) { 20 | ID = GL.GenBuffer(); 21 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 22 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector2.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 23 | } 24 | 25 | public void Bind() { GL.BindBuffer(BufferTarget.ArrayBuffer, ID); } 26 | public void Unbind() { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } 27 | public void Delete() { GL.DeleteBuffer(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 8/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(1280, 720)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 8/Shaders/Default.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 texCoord; 4 | 5 | out vec4 FragColor; 6 | 7 | uniform sampler2D texture0; 8 | 9 | void main() 10 | { 11 | FragColor = texture(texture0, texCoord); 12 | } -------------------------------------------------------------------------------- /ep 8/Shaders/Default.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 aPosition; // vertex coordinates 3 | layout (location = 1) in vec2 aTexCoord; // texture coordinates 4 | 5 | out vec2 texCoord; 6 | 7 | // uniform variables 8 | uniform mat4 model; 9 | uniform mat4 view; 10 | uniform mat4 projection; 11 | 12 | void main() 13 | { 14 | gl_Position = vec4(aPosition, 1.0) * model * view * projection; // coordinates 15 | texCoord = aTexCoord; 16 | } -------------------------------------------------------------------------------- /ep 8/World/Block.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 9 | { 10 | internal class Block 11 | { 12 | public Vector3 position; 13 | 14 | public Dictionary faces; 15 | 16 | public List dirtUV = new List 17 | { 18 | new Vector2(0f, 1f), 19 | new Vector2(1f, 1f), 20 | new Vector2(1f, 0f), 21 | new Vector2(0f, 0f), 22 | }; 23 | public Block(Vector3 position) { 24 | this.position = position; 25 | 26 | faces = new Dictionary 27 | { 28 | {Faces.FRONT, new FaceData { 29 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.FRONT]), 30 | uv = dirtUV 31 | } }, 32 | {Faces.BACK, new FaceData { 33 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BACK]), 34 | uv = dirtUV 35 | } }, 36 | {Faces.LEFT, new FaceData { 37 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.LEFT]), 38 | uv = dirtUV 39 | } }, 40 | {Faces.RIGHT, new FaceData { 41 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.RIGHT]), 42 | uv = dirtUV 43 | } }, 44 | {Faces.TOP, new FaceData { 45 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.TOP]), 46 | uv = dirtUV 47 | } }, 48 | {Faces.BOTTOM, new FaceData { 49 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BOTTOM]), 50 | uv = dirtUV 51 | } }, 52 | 53 | }; 54 | } 55 | public List AddTransformedVertices(List vertices) { 56 | List transformedVertices = new List(); 57 | foreach (var vert in vertices) { 58 | transformedVertices.Add(vert + position); 59 | } 60 | return transformedVertices; 61 | } 62 | public FaceData GetFace(Faces face) { 63 | return faces[face]; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ep 8/World/BlockData.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 9 | { 10 | public enum Faces 11 | { 12 | FRONT, 13 | BACK, 14 | LEFT, 15 | RIGHT, 16 | TOP, 17 | BOTTOM 18 | } 19 | 20 | public struct FaceData 21 | { 22 | public List vertices; 23 | public List uv; 24 | } 25 | 26 | public struct FaceDataRaw 27 | { 28 | public static readonly Dictionary> rawVertexData = new Dictionary> 29 | { 30 | {Faces.FRONT, new List() 31 | { 32 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 33 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 34 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 35 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 36 | } }, 37 | {Faces.BACK, new List() 38 | { 39 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 40 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 41 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 42 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 43 | } }, 44 | {Faces.LEFT, new List() 45 | { 46 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 47 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 48 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 49 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 50 | } }, 51 | {Faces.RIGHT, new List() 52 | { 53 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 54 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 55 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 56 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 57 | } }, 58 | {Faces.TOP, new List() 59 | { 60 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 61 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 62 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 63 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 64 | } }, 65 | {Faces.BOTTOM, new List() 66 | { 67 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 68 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 69 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 70 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 71 | } }, 72 | }; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /ep 8/World/Chunk.cs: -------------------------------------------------------------------------------- 1 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 2 | using OpenTK.Mathematics; 3 | using OpenTK.Graphics.OpenGL4; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 11 | { 12 | internal class Chunk 13 | { 14 | public List chunkVerts; 15 | public List chunkUVs; 16 | public List chunkIndices; 17 | 18 | const int SIZE = 16; 19 | const int HEIGHT = 32; 20 | public Vector3 position; 21 | 22 | public uint indexCount; 23 | 24 | VAO chunkVAO; 25 | VBO chunkVertexVBO; 26 | VBO chunkUVVBO; 27 | IBO chunkIBO; 28 | 29 | Texture texture; 30 | public Chunk(Vector3 postition) 31 | { 32 | this.position = postition; 33 | 34 | chunkVerts = new List(); 35 | chunkUVs = new List(); 36 | chunkIndices = new List(); 37 | 38 | GenBlocks(); 39 | BuildChunk(); 40 | } 41 | 42 | public void GenChunk() { } // generate the data 43 | public void GenBlocks() { 44 | for(int i = 0; i < 3; i++) 45 | { 46 | Block block = new Block(new Vector3(i, 0, 0)); 47 | 48 | int faceCount = 0; 49 | 50 | if(i == 0) 51 | { 52 | var leftFaceData = block.GetFace(Faces.LEFT); 53 | chunkVerts.AddRange(leftFaceData.vertices); 54 | chunkUVs.AddRange(leftFaceData.uv); 55 | faceCount++; 56 | } 57 | if (i == 2) 58 | { 59 | var rightFaceData = block.GetFace(Faces.RIGHT); 60 | chunkVerts.AddRange(rightFaceData.vertices); 61 | chunkUVs.AddRange(rightFaceData.uv); 62 | faceCount++; 63 | } 64 | 65 | var frontFaceData = block.GetFace(Faces.FRONT); 66 | chunkVerts.AddRange(frontFaceData.vertices); 67 | chunkUVs.AddRange(frontFaceData.uv); 68 | 69 | var backFaceData = block.GetFace(Faces.BACK); 70 | chunkVerts.AddRange(backFaceData.vertices); 71 | chunkUVs.AddRange(backFaceData.uv); 72 | 73 | var topFaceData = block.GetFace(Faces.TOP); 74 | chunkVerts.AddRange(topFaceData.vertices); 75 | chunkUVs.AddRange(topFaceData.uv); 76 | 77 | var bottomFaceData = block.GetFace(Faces.BOTTOM); 78 | chunkVerts.AddRange(bottomFaceData.vertices); 79 | chunkUVs.AddRange(bottomFaceData.uv); 80 | 81 | faceCount += 4; 82 | 83 | AddIndices(faceCount); 84 | } 85 | } // generate the appropriate block faces given the data 86 | public void AddIndices(int amtFaces) 87 | { 88 | for(int i = 0; i < amtFaces; i++) 89 | { 90 | chunkIndices.Add(0 + indexCount); 91 | chunkIndices.Add(1 + indexCount); 92 | chunkIndices.Add(2 + indexCount); 93 | chunkIndices.Add(2 + indexCount); 94 | chunkIndices.Add(3 + indexCount); 95 | chunkIndices.Add(0 + indexCount); 96 | 97 | indexCount += 4; 98 | } 99 | } 100 | public void BuildChunk() { 101 | chunkVAO = new VAO(); 102 | chunkVAO.Bind(); 103 | 104 | chunkVertexVBO = new VBO(chunkVerts); 105 | chunkVertexVBO.Bind(); 106 | chunkVAO.LinkToVAO(0, 3, chunkVertexVBO); 107 | 108 | chunkUVVBO = new VBO(chunkUVs); 109 | chunkUVVBO.Bind(); 110 | chunkVAO.LinkToVAO(1, 2, chunkUVVBO); 111 | 112 | chunkIBO = new IBO(chunkIndices); 113 | 114 | texture = new Texture("dirtTex.PNG"); 115 | } // take data and process it for rendering 116 | public void Render(ShaderProgram program) // drawing the chunk 117 | { 118 | program.Bind(); 119 | chunkVAO.Bind(); 120 | chunkIBO.Bind(); 121 | texture.Bind(); 122 | GL.DrawElements(PrimitiveType.Triangles, chunkIndices.Count, DrawElementsType.UnsignedInt, 0); 123 | } 124 | 125 | public void Delete() 126 | { 127 | chunkVAO.Delete(); 128 | chunkVertexVBO.Delete(); 129 | chunkUVVBO.Delete(); 130 | chunkIBO.Delete(); 131 | texture.Delete(); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /ep 9/Camera.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Windowing.Common; 3 | using OpenTK.Windowing.GraphicsLibraryFramework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj 11 | { 12 | internal class Camera 13 | { 14 | // CONSTANTS 15 | private float SPEED = 8f; 16 | private float SCREENWIDTH; 17 | private float SCREENHEIGHT; 18 | private float SENSITIVITY = 180f; 19 | 20 | // position vars 21 | public Vector3 position; 22 | 23 | Vector3 up = Vector3.UnitY; 24 | Vector3 front = -Vector3.UnitZ; 25 | Vector3 right = Vector3.UnitX; 26 | 27 | // --- view rotations --- 28 | private float pitch; 29 | private float yaw = -90.0f; 30 | 31 | private bool firstMove = true; 32 | public Vector2 lastPos; 33 | public Camera(float width, float height, Vector3 position) { 34 | SCREENWIDTH = width; 35 | SCREENHEIGHT = height; 36 | this.position = position; 37 | } 38 | 39 | public Matrix4 GetViewMatrix() { 40 | return Matrix4.LookAt(position, position + front, up); 41 | } 42 | public Matrix4 GetProjectionMatrix() { 43 | return Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0f), SCREENWIDTH / SCREENHEIGHT, 0.1f, 100.0f); 44 | } 45 | 46 | private void UpdateVectors() 47 | { 48 | if (pitch > 89.0f) 49 | { 50 | pitch = 89.0f; 51 | } 52 | if (pitch < -89.0f) 53 | { 54 | pitch = -89.0f; 55 | } 56 | 57 | 58 | front.X = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Cos(MathHelper.DegreesToRadians(yaw)); 59 | front.Y = MathF.Sin(MathHelper.DegreesToRadians(pitch)); 60 | front.Z = MathF.Cos(MathHelper.DegreesToRadians(pitch)) * MathF.Sin(MathHelper.DegreesToRadians(yaw)); 61 | 62 | front = Vector3.Normalize(front); 63 | 64 | right = Vector3.Normalize(Vector3.Cross(front, Vector3.UnitY)); 65 | up = Vector3.Normalize(Vector3.Cross(right, front)); 66 | } 67 | 68 | public void InputController(KeyboardState input, MouseState mouse, FrameEventArgs e) { 69 | 70 | if (input.IsKeyDown(Keys.W)) 71 | { 72 | position += front * SPEED * (float)e.Time; 73 | } 74 | if (input.IsKeyDown(Keys.A)) 75 | { 76 | position -= right * SPEED * (float)e.Time; 77 | } 78 | if (input.IsKeyDown(Keys.S)) 79 | { 80 | position -= front * SPEED * (float)e.Time; 81 | } 82 | if (input.IsKeyDown(Keys.D)) 83 | { 84 | position += right * SPEED * (float)e.Time; 85 | } 86 | 87 | if (input.IsKeyDown(Keys.Space)) 88 | { 89 | position.Y += SPEED * (float)e.Time; 90 | } 91 | if (input.IsKeyDown(Keys.LeftShift)) 92 | { 93 | position.Y -= SPEED * (float)e.Time; 94 | } 95 | 96 | if (firstMove) 97 | { 98 | lastPos = new Vector2(mouse.X, mouse.Y); 99 | firstMove = false; 100 | } else 101 | { 102 | var deltaX = mouse.X - lastPos.X; 103 | var deltaY = mouse.Y - lastPos.Y; 104 | lastPos = new Vector2(mouse.X, mouse.Y); 105 | 106 | yaw += deltaX * SENSITIVITY * (float)e.Time; 107 | pitch -= deltaY * SENSITIVITY * (float)e.Time; 108 | } 109 | UpdateVectors(); 110 | } 111 | public void Update(KeyboardState input, MouseState mouse, FrameEventArgs e) { 112 | InputController(input, mouse, e); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /ep 9/Game.cs: -------------------------------------------------------------------------------- 1 |  2 | using OpenTK.Windowing.Desktop; 3 | using OpenTK.Mathematics; 4 | using OpenTK.Graphics; 5 | using OpenTK.Windowing.Common; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using OpenTK.Windowing.Common; 12 | using OpenTK.Graphics.OpenGL4; 13 | using OpenTK.Windowing.GraphicsLibraryFramework; 14 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 15 | using Minecraft_Clone_Tutorial_Series_videoproj.World; 16 | 17 | namespace Minecraft_Clone_Tutorial_Series_videoproj 18 | { 19 | // Game class that inherets from the Game Window Class 20 | internal class Game : GameWindow 21 | { 22 | // set of vertices to draw the triangle with (x,y,z) for each vertex 23 | 24 | Chunk chunk; 25 | ShaderProgram program; 26 | 27 | // camera 28 | Camera camera; 29 | 30 | // transformation variables 31 | float yRot = 0f; 32 | 33 | // width and height of screen 34 | int width, height; 35 | // Constructor that sets the width, height, and calls the base constructor (GameWindow's Constructor) with default args 36 | public Game(int width, int height) : base(GameWindowSettings.Default, NativeWindowSettings.Default) 37 | { 38 | this.width = width; 39 | this.height = height; 40 | 41 | // center window 42 | CenterWindow(new Vector2i(width, height)); 43 | } 44 | // called whenever window is resized 45 | protected override void OnResize(ResizeEventArgs e) 46 | { 47 | base.OnResize(e); 48 | GL.Viewport(0,0, e.Width, e.Height); 49 | this.width = e.Width; 50 | this.height = e.Height; 51 | } 52 | 53 | // called once when game is started 54 | protected override void OnLoad() 55 | { 56 | base.OnLoad(); 57 | 58 | chunk = new Chunk(new Vector3(0, 0, 0)); 59 | program = new ShaderProgram("Default.vert", "Default.frag"); 60 | 61 | GL.Enable(EnableCap.DepthTest); 62 | 63 | GL.FrontFace(FrontFaceDirection.Cw); 64 | GL.Enable(EnableCap.CullFace); 65 | GL.CullFace(CullFaceMode.Back); 66 | 67 | camera = new Camera(width, height, Vector3.Zero); 68 | CursorState = CursorState.Grabbed; 69 | } 70 | // called once when game is closed 71 | protected override void OnUnload() 72 | { 73 | base.OnUnload(); 74 | 75 | chunk.Delete(); 76 | // Delete, VAO, VBO, Shader Program 77 | 78 | } 79 | // called every frame. All rendering happens here 80 | protected override void OnRenderFrame(FrameEventArgs args) 81 | { 82 | // Set the color to fill the screen with 83 | GL.ClearColor(0.3f, 0.3f, 1f, 1f); 84 | // Fill the screen with the color 85 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); 86 | 87 | 88 | 89 | // transformation matrices 90 | Matrix4 model = Matrix4.Identity; 91 | Matrix4 view = camera.GetViewMatrix(); 92 | Matrix4 projection = camera.GetProjectionMatrix(); 93 | 94 | 95 | int modelLocation = GL.GetUniformLocation(program.ID, "model"); 96 | int viewLocation = GL.GetUniformLocation(program.ID, "view"); 97 | int projectionLocation = GL.GetUniformLocation(program.ID, "projection"); 98 | 99 | GL.UniformMatrix4(modelLocation, true, ref model); 100 | GL.UniformMatrix4(viewLocation, true, ref view); 101 | GL.UniformMatrix4(projectionLocation, true, ref projection); 102 | 103 | chunk.Render(program); 104 | 105 | 106 | // swap the buffers 107 | Context.SwapBuffers(); 108 | 109 | base.OnRenderFrame(args); 110 | } 111 | // called every frame. All updating happens here 112 | protected override void OnUpdateFrame(FrameEventArgs args) 113 | { 114 | MouseState mouse = MouseState; 115 | KeyboardState input = KeyboardState; 116 | 117 | base.OnUpdateFrame(args); 118 | camera.Update(input, mouse, args); 119 | } 120 | 121 | // Function to load a text file and return its contents as a string 122 | 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /ep 9/Graphics/IBO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class IBO 11 | { 12 | public int ID; 13 | public IBO(List data) 14 | { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ElementArrayBuffer, data.Count * sizeof(uint), data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public void Bind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID); } 20 | public void Unbind() { GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); } 21 | public void Delete() { GL.DeleteBuffer(ID); } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ep 9/Graphics/ShaderProgram.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class ShaderProgram 11 | { 12 | public int ID; 13 | public ShaderProgram(string vertexShaderFilepath, string fragmentShaderFilepath) { 14 | // create the shader program 15 | ID = GL.CreateProgram(); 16 | 17 | // create the vertex shader 18 | int vertexShader = GL.CreateShader(ShaderType.VertexShader); 19 | // add the source code from "Default.vert" in the Shaders file 20 | GL.ShaderSource(vertexShader, LoadShaderSource(vertexShaderFilepath)); 21 | // Compile the Shader 22 | GL.CompileShader(vertexShader); 23 | 24 | // Same as vertex shader 25 | int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); 26 | GL.ShaderSource(fragmentShader, LoadShaderSource(fragmentShaderFilepath)); 27 | GL.CompileShader(fragmentShader); 28 | 29 | // Attach the shaders to the shader program 30 | GL.AttachShader(ID, vertexShader); 31 | GL.AttachShader(ID, fragmentShader); 32 | 33 | // Link the program to OpenGL 34 | GL.LinkProgram(ID); 35 | 36 | // delete the shaders 37 | GL.DeleteShader(vertexShader); 38 | GL.DeleteShader(fragmentShader); 39 | } 40 | 41 | public void Bind() { GL.UseProgram(ID); } 42 | public void Unbind() { GL.UseProgram(0); } 43 | public void Delete() { GL.DeleteShader(ID); } 44 | 45 | public static string LoadShaderSource(string filePath) 46 | { 47 | string shaderSource = ""; 48 | 49 | try 50 | { 51 | using (StreamReader reader = new StreamReader("../../../Shaders/" + filePath)) 52 | { 53 | shaderSource = reader.ReadToEnd(); 54 | } 55 | } 56 | catch (Exception e) 57 | { 58 | Console.WriteLine("Failed to load shader source file: " + e.Message); 59 | } 60 | 61 | return shaderSource; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ep 9/Graphics/Texture.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | using StbImageSharp; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class Texture 12 | { 13 | public int ID; 14 | 15 | public Texture(String filepath) 16 | { 17 | ID = GL.GenTexture(); 18 | 19 | GL.ActiveTexture(TextureUnit.Texture0); 20 | GL.BindTexture(TextureTarget.Texture2D, ID); 21 | 22 | // texture parameters 23 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); 24 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); 25 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); 26 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); 27 | 28 | StbImage.stbi_set_flip_vertically_on_load(1); 29 | ImageResult dirtTexture = ImageResult.FromStream(File.OpenRead("../../../Textures/" + filepath), ColorComponents.RedGreenBlueAlpha); 30 | 31 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, dirtTexture.Width, dirtTexture.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, dirtTexture.Data); 32 | // unbind the texture 33 | Unbind(); 34 | } 35 | 36 | public void Bind() { GL.BindTexture(TextureTarget.Texture2D, ID); } 37 | public void Unbind() { GL.BindTexture(TextureTarget.Texture2D, 0); } 38 | public void Delete() { GL.DeleteTexture(ID); } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ep 9/Graphics/VAO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using OpenTK.Graphics.OpenGL4; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 9 | { 10 | internal class VAO 11 | { 12 | public int ID; 13 | public VAO() { 14 | ID = GL.GenVertexArray(); 15 | GL.BindVertexArray(ID); 16 | } 17 | public void LinkToVAO(int location, int size, VBO vbo) 18 | { 19 | Bind(); 20 | vbo.Bind(); 21 | GL.VertexAttribPointer(location, size, VertexAttribPointerType.Float, false, 0, 0); 22 | GL.EnableVertexAttribArray(location); 23 | Unbind(); 24 | } 25 | public void Bind() { GL.BindVertexArray(ID); } 26 | public void Unbind() { GL.BindVertexArray(0); } 27 | public void Delete() { GL.DeleteVertexArray(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 9/Graphics/VBO.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using OpenTK.Graphics.OpenGL4; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.Graphics 10 | { 11 | internal class VBO 12 | { 13 | public int ID; 14 | public VBO(List data) { 15 | ID = GL.GenBuffer(); 16 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 17 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector3.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 18 | } 19 | public VBO(List data) { 20 | ID = GL.GenBuffer(); 21 | GL.BindBuffer(BufferTarget.ArrayBuffer, ID); 22 | GL.BufferData(BufferTarget.ArrayBuffer, data.Count * Vector2.SizeInBytes, data.ToArray(), BufferUsageHint.StaticDraw); 23 | } 24 | 25 | public void Bind() { GL.BindBuffer(BufferTarget.ArrayBuffer, ID); } 26 | public void Unbind() { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); } 27 | public void Delete() { GL.DeleteBuffer(ID); } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ep 9/Program.cs: -------------------------------------------------------------------------------- 1 | namespace Minecraft_Clone_Tutorial_Series_videoproj 2 | { 3 | public class Program 4 | { 5 | // Entry point of the program 6 | static void Main(string[] args) 7 | { 8 | // Creates game object and disposes of it after leaving the scope 9 | using(Game game = new Game(1280, 720)) 10 | { 11 | // running the game 12 | game.Run(); 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ep 9/Shaders/Default.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 texCoord; 4 | 5 | out vec4 FragColor; 6 | 7 | uniform sampler2D texture0; 8 | 9 | void main() 10 | { 11 | FragColor = texture(texture0, texCoord); 12 | } -------------------------------------------------------------------------------- /ep 9/Shaders/Default.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | layout (location = 0) in vec3 aPosition; // vertex coordinates 3 | layout (location = 1) in vec2 aTexCoord; // texture coordinates 4 | 5 | out vec2 texCoord; 6 | 7 | // uniform variables 8 | uniform mat4 model; 9 | uniform mat4 view; 10 | uniform mat4 projection; 11 | 12 | void main() 13 | { 14 | gl_Position = vec4(aPosition, 1.0) * model * view * projection; // coordinates 15 | texCoord = aTexCoord; 16 | } -------------------------------------------------------------------------------- /ep 9/World/Block.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 10 | { 11 | internal class Block 12 | { 13 | public Vector3 position; 14 | public BlockType type; 15 | 16 | public Dictionary faces; 17 | 18 | public List dirtUV = new List 19 | { 20 | new Vector2(0f, 1f), 21 | new Vector2(1f, 1f), 22 | new Vector2(1f, 0f), 23 | new Vector2(0f, 0f), 24 | }; 25 | public Block(Vector3 position, BlockType blockType = BlockType.AIR) { 26 | type = blockType; 27 | this.position = position; 28 | 29 | faces = new Dictionary 30 | { 31 | {Faces.FRONT, new FaceData { 32 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.FRONT]), 33 | uv = dirtUV 34 | } }, 35 | {Faces.BACK, new FaceData { 36 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BACK]), 37 | uv = dirtUV 38 | } }, 39 | {Faces.LEFT, new FaceData { 40 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.LEFT]), 41 | uv = dirtUV 42 | } }, 43 | {Faces.RIGHT, new FaceData { 44 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.RIGHT]), 45 | uv = dirtUV 46 | } }, 47 | {Faces.TOP, new FaceData { 48 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.TOP]), 49 | uv = dirtUV 50 | } }, 51 | {Faces.BOTTOM, new FaceData { 52 | vertices = AddTransformedVertices(FaceDataRaw.rawVertexData[Faces.BOTTOM]), 53 | uv = dirtUV 54 | } }, 55 | 56 | }; 57 | } 58 | public List AddTransformedVertices(List vertices) { 59 | List transformedVertices = new List(); 60 | foreach (var vert in vertices) { 61 | transformedVertices.Add(vert + position); 62 | } 63 | return transformedVertices; 64 | } 65 | public FaceData GetFace(Faces face) { 66 | return faces[face]; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ep 9/World/BlockData.cs: -------------------------------------------------------------------------------- 1 | using OpenTK.Mathematics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 9 | { 10 | public enum BlockType 11 | { 12 | DIRT, 13 | AIR 14 | } 15 | public enum Faces 16 | { 17 | FRONT, 18 | BACK, 19 | LEFT, 20 | RIGHT, 21 | TOP, 22 | BOTTOM 23 | } 24 | 25 | public struct FaceData 26 | { 27 | public List vertices; 28 | public List uv; 29 | } 30 | 31 | public struct FaceDataRaw 32 | { 33 | public static readonly Dictionary> rawVertexData = new Dictionary> 34 | { 35 | {Faces.FRONT, new List() 36 | { 37 | new Vector3(-0.5f, 0.5f, 0.5f), // topleft vert 38 | new Vector3(0.5f, 0.5f, 0.5f), // topright vert 39 | new Vector3(0.5f, -0.5f, 0.5f), // bottomright vert 40 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomleft vert 41 | } }, 42 | {Faces.BACK, new List() 43 | { 44 | new Vector3(0.5f, 0.5f, -0.5f), // topleft vert 45 | new Vector3(-0.5f, 0.5f, -0.5f), // topright vert 46 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomright vert 47 | new Vector3(0.5f, -0.5f, -0.5f), // bottomleft vert 48 | } }, 49 | {Faces.LEFT, new List() 50 | { 51 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 52 | new Vector3(-0.5f, 0.5f, 0.5f), // topright vert 53 | new Vector3(-0.5f, -0.5f, 0.5f), // bottomright vert 54 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 55 | } }, 56 | {Faces.RIGHT, new List() 57 | { 58 | new Vector3(0.5f, 0.5f, 0.5f), // topleft vert 59 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 60 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 61 | new Vector3(0.5f, -0.5f, 0.5f), // bottomleft vert 62 | } }, 63 | {Faces.TOP, new List() 64 | { 65 | new Vector3(-0.5f, 0.5f, -0.5f), // topleft vert 66 | new Vector3(0.5f, 0.5f, -0.5f), // topright vert 67 | new Vector3(0.5f, 0.5f, 0.5f), // bottomright vert 68 | new Vector3(-0.5f, 0.5f, 0.5f), // bottomleft vert 69 | } }, 70 | {Faces.BOTTOM, new List() 71 | { 72 | new Vector3(-0.5f, -0.5f, 0.5f), // topleft vert 73 | new Vector3(0.5f, -0.5f, 0.5f), // topright vert 74 | new Vector3(0.5f, -0.5f, -0.5f), // bottomright vert 75 | new Vector3(-0.5f, -0.5f, -0.5f), // bottomleft vert 76 | } }, 77 | }; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /ep 9/World/Chunk.cs: -------------------------------------------------------------------------------- 1 | using Minecraft_Clone_Tutorial_Series_videoproj.Graphics; 2 | using OpenTK.Mathematics; 3 | using OpenTK.Graphics.OpenGL4; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Minecraft_Clone_Tutorial_Series_videoproj.World 11 | { 12 | internal class Chunk 13 | { 14 | public List chunkVerts; 15 | public List chunkUVs; 16 | public List chunkIndices; 17 | 18 | const sbyte SIZE = 16; 19 | const short HEIGHT = 384; 20 | public Vector3 position; 21 | 22 | public uint indexCount; 23 | 24 | VAO chunkVAO; 25 | VBO chunkVertexVBO; 26 | VBO chunkUVVBO; 27 | IBO chunkIBO; 28 | 29 | Texture texture; 30 | Block[,,] chunkBlocks = new Block[SIZE, HEIGHT, SIZE]; 31 | public Chunk(Vector3 postition) 32 | { 33 | this.position = postition; 34 | 35 | chunkVerts = new List(); 36 | chunkUVs = new List(); 37 | chunkIndices = new List(); 38 | 39 | float[,] heightmap = GenChunk(); 40 | GenBlocks(heightmap); 41 | GenFaces(heightmap); 42 | BuildChunk(); 43 | } 44 | 45 | public float[,] GenChunk() { 46 | float[,] heightmap = new float[SIZE, SIZE]; 47 | 48 | SimplexNoise.Noise.Seed = 123456; 49 | for (int x = 0; x < SIZE; x++) 50 | { 51 | for (int z = 0; z < SIZE; z++) 52 | { 53 | heightmap[x, z] = SimplexNoise.Noise.CalcPixel2D(x, z, 0.01f); 54 | } 55 | } 56 | 57 | return heightmap; 58 | } 59 | public void GenBlocks(float[,] heightmap) { 60 | for (int x = 0; x < SIZE; x++) 61 | { 62 | for (int z = 0; z < SIZE; z++) 63 | { 64 | int columnHeight = (int)(heightmap[x, z] / 10); 65 | for (int y = 0; y < HEIGHT; y++) 66 | { 67 | if (y < columnHeight) 68 | { 69 | chunkBlocks[x, y, z] = new Block(new Vector3(x, y, z), BlockType.DIRT); 70 | } 71 | else 72 | { 73 | chunkBlocks[x, y, z] = new Block(new Vector3(x, y, z), BlockType.AIR); 74 | } 75 | } 76 | } 77 | } 78 | } 79 | public void GenFaces(float[,] heightmap) 80 | { 81 | for ( int x = 0; x < SIZE; x++) 82 | { 83 | for ( int z = 0; z < SIZE; z++) 84 | { 85 | int columnHeight = (int)(heightmap[x, z] / 10); 86 | for ( int y = 0; y < columnHeight; y++) 87 | { 88 | int numFaces = 0; 89 | 90 | // Left Faces 91 | if (x > 0) 92 | { 93 | if (chunkBlocks[x-1, y, z].type == BlockType.AIR) 94 | { 95 | IntegrateFace(chunkBlocks[x,y,z], Faces.LEFT); 96 | numFaces++; 97 | } 98 | } else 99 | { 100 | IntegrateFace(chunkBlocks[x, y, z], Faces.LEFT); 101 | numFaces++; 102 | } 103 | 104 | // Right Faces 105 | if (x < SIZE-1) 106 | { 107 | if (chunkBlocks[x+1, y, z].type == BlockType.AIR) 108 | { 109 | IntegrateFace(chunkBlocks[x,y,z], Faces.RIGHT); 110 | numFaces++; 111 | } 112 | } else 113 | { 114 | IntegrateFace(chunkBlocks[x, y, z], Faces.RIGHT); 115 | numFaces++; 116 | } 117 | 118 | // Top Faces 119 | if (y < columnHeight-1) 120 | { 121 | if (chunkBlocks[x, y+1, z].type == BlockType.AIR) 122 | { 123 | IntegrateFace(chunkBlocks[x,y,z], Faces.TOP); 124 | numFaces++; 125 | } 126 | } else 127 | { 128 | IntegrateFace(chunkBlocks[x, y, z], Faces.TOP); 129 | numFaces++; 130 | } 131 | 132 | // Bottom Faces 133 | if (y > 0) 134 | { 135 | if (chunkBlocks[x, y-1, z].type == BlockType.AIR) 136 | { 137 | IntegrateFace(chunkBlocks[x,y,z], Faces.BOTTOM); 138 | numFaces++; 139 | } 140 | } else 141 | { 142 | IntegrateFace(chunkBlocks[x, y, z], Faces.BOTTOM); 143 | numFaces++; 144 | } 145 | 146 | // Front Faces 147 | if (z < SIZE -1) 148 | { 149 | if (chunkBlocks[x, y, z+1].type == BlockType.AIR) 150 | { 151 | IntegrateFace(chunkBlocks[x,y,z], Faces.FRONT); 152 | numFaces++; 153 | } 154 | } else 155 | { 156 | IntegrateFace(chunkBlocks[x, y, z], Faces.FRONT); 157 | numFaces++; 158 | } 159 | 160 | // Back Faces 161 | if (z > 0) 162 | { 163 | if (chunkBlocks[x, y, z-1].type == BlockType.AIR) 164 | { 165 | IntegrateFace(chunkBlocks[x,y,z], Faces.BACK); 166 | numFaces++; 167 | } 168 | } else 169 | { 170 | IntegrateFace(chunkBlocks[x, y, z], Faces.BACK); 171 | numFaces++; 172 | } 173 | 174 | AddIndices(numFaces); 175 | } 176 | } 177 | } 178 | } 179 | 180 | public void IntegrateFace(Block block, Faces face) 181 | { 182 | var faceData = block.GetFace(face); 183 | chunkVerts.AddRange(faceData.vertices); 184 | chunkUVs.AddRange(faceData.uv); 185 | } 186 | 187 | public void AddIndices(int amtFaces) 188 | { 189 | for(int i = 0; i < amtFaces; i++) 190 | { 191 | chunkIndices.Add(0 + indexCount); 192 | chunkIndices.Add(1 + indexCount); 193 | chunkIndices.Add(2 + indexCount); 194 | chunkIndices.Add(2 + indexCount); 195 | chunkIndices.Add(3 + indexCount); 196 | chunkIndices.Add(0 + indexCount); 197 | 198 | indexCount += 4; 199 | } 200 | } 201 | public void BuildChunk() { 202 | chunkVAO = new VAO(); 203 | chunkVAO.Bind(); 204 | 205 | chunkVertexVBO = new VBO(chunkVerts); 206 | chunkVertexVBO.Bind(); 207 | chunkVAO.LinkToVAO(0, 3, chunkVertexVBO); 208 | 209 | chunkUVVBO = new VBO(chunkUVs); 210 | chunkUVVBO.Bind(); 211 | chunkVAO.LinkToVAO(1, 2, chunkUVVBO); 212 | 213 | chunkIBO = new IBO(chunkIndices); 214 | 215 | texture = new Texture("dirtTex.PNG"); 216 | } // take data and process it for rendering 217 | public void Render(ShaderProgram program) // drawing the chunk 218 | { 219 | program.Bind(); 220 | chunkVAO.Bind(); 221 | chunkIBO.Bind(); 222 | texture.Bind(); 223 | GL.DrawElements(PrimitiveType.Triangles, chunkIndices.Count, DrawElementsType.UnsignedInt, 0); 224 | } 225 | 226 | public void Delete() 227 | { 228 | chunkVAO.Delete(); 229 | chunkVertexVBO.Delete(); 230 | chunkUVVBO.Delete(); 231 | chunkIBO.Delete(); 232 | texture.Delete(); 233 | } 234 | } 235 | } 236 | --------------------------------------------------------------------------------