Culling, rendering improvements and optimizations, block removing test.

This commit is contained in:
2025-09-02 22:43:35 +02:00
parent a9cab195b6
commit 00713db79e
16 changed files with 390 additions and 210 deletions

View File

@@ -2,8 +2,11 @@
{ {
public enum Blocks : byte public enum Blocks : byte
{ {
Air = 0, Air,
Stone = 1, Stone,
Dirt,
OakPlanks,
Grass
} }
public enum Orientation : uint public enum Orientation : uint
@@ -16,8 +19,58 @@
South = 5, // - Z South = 5, // - Z
} }
public enum Texture : uint public class BlockDefinition
{ {
Stone = 1 public Blocks BlockType;
public Textures[] FaceTextures;
public BlockDefinition(Blocks type, Textures singleTexture)
{
BlockType = type;
FaceTextures = new Voxel.Textures[6];
for (int i = 0; i < 6; i++) FaceTextures[i] = singleTexture;
}
public BlockDefinition(
Blocks type,
Textures west,
Textures east,
Textures top,
Textures bottom,
Textures north,
Textures south
)
{
BlockType = type;
FaceTextures = new Textures[]
{
west, east, top, bottom, north, south
};
}
}
public static class BlockDefinitions
{
public static readonly Dictionary<Blocks, BlockDefinition> Blocks;
static BlockDefinitions()
{
Blocks = new Dictionary<Blocks, BlockDefinition>
{
{ Voxel.Blocks.Stone, new BlockDefinition(Voxel.Blocks.Stone, Voxel.Textures.Stone) },
{ Voxel.Blocks.Dirt, new BlockDefinition(Voxel.Blocks.Dirt, Voxel.Textures.Dirt) },
{ Voxel.Blocks.OakPlanks, new BlockDefinition(Voxel.Blocks.OakPlanks, Voxel.Textures.OakPlanks) },
{ Voxel.Blocks.Grass, new BlockDefinition(
Voxel.Blocks.Grass,
Voxel.Textures.GrassSide, // West
Voxel.Textures.GrassSide, // East
Voxel.Textures.GrassTop, // Top
Voxel.Textures.Dirt, // Bottom
Voxel.Textures.GrassSide, // North
Voxel.Textures.GrassSide // South
)},
};
}
} }
} }

View File

@@ -4,11 +4,11 @@ namespace Voxel
{ {
static class Camera static class Camera
{ {
public static Vector3 Position; public static Vector3 Position = new Vector3(-8, 16, -8);
public static float Pitch = 0f; public static float Pitch = -22.5f;
public static float Yaw = -90f; public static float Yaw = 45f;
public static float FOV = 70f; public static float FOV = 60f;
public static float Speed = 5f; public static float Speed = 5f;
public static float ShiftSpeed = 20f; public static float ShiftSpeed = 20f;
@@ -56,18 +56,21 @@ namespace Voxel
public static void UpdateMouse(Vector2 delta) public static void UpdateMouse(Vector2 delta)
{ {
float fov = MathHelper.DegreesToRadians(60f);
float aspectRatio = 800f / 600f;
float near = 0.1f;
float far = 100f;
projection = Matrix4.CreatePerspectiveFieldOfView(fov, aspectRatio, near, far);
float sensitivity = 0.1f; float sensitivity = 0.1f;
Yaw += delta.X * sensitivity; Yaw += delta.X * sensitivity;
Pitch -= delta.Y * sensitivity; Pitch -= delta.Y * sensitivity;
Pitch = MathHelper.Clamp(Pitch, -89f, 89f); Pitch = MathHelper.Clamp(Pitch, -89f, 89f);
} }
public static void UpdateProjection(int width, int height)
{
float fov = MathHelper.DegreesToRadians(FOV);
float aspectRatio = width / (float)height;
float near = 0.1f;
float far = 1000f;
projection = Matrix4.CreatePerspectiveFieldOfView(fov, aspectRatio, near, far);
}
} }
} }

121
Chunk.cs
View File

@@ -8,7 +8,7 @@
public readonly int PositionY; public readonly int PositionY;
private Dictionary<ushort, BlockData> _blockData; private Dictionary<ushort, BlockData> _blockData;
private byte[] _blocks; private Blocks[] _blocks;
public Chunk(int positionX, int positionY) public Chunk(int positionX, int positionY)
{ {
@@ -16,18 +16,23 @@
PositionY = positionY; PositionY = positionY;
_blockData = new Dictionary<ushort, BlockData>(); _blockData = new Dictionary<ushort, BlockData>();
_blocks = new byte[Size * Size * Height]; _blocks = new Blocks[Size * Size * Height];
Initialize(); Initialize();
} }
public void SetBlock(int x, int y, int z, byte blockId) public void SetBlock(int x, int y, int z, Blocks block)
{ {
int i = GetBlockIndex(x, y, z); int i = GetBlockIndex(x, y, z);
_blocks[i] = blockId; _blocks[i] = block;
} }
public byte GetBlock(int x, int y, int z) public void SetBlockIndex(int i, Blocks block)
{
_blocks[i] = block;
}
public Blocks GetBlock(int x, int y, int z)
{ {
int i = GetBlockIndex(x, y, z); int i = GetBlockIndex(x, y, z);
return _blocks[i]; return _blocks[i];
@@ -40,23 +45,9 @@
private void Initialize() private void Initialize()
{ {
for (int x = 0; x < Size; x++) Random rng = new Random();
{ for (int i = 0; i < Size * Size * 16; i++)
for (int z = 0; z < Size; z++) _blocks[i] = (Blocks)rng.Next(5);
{
for (int y = 0; y < Size; y++)
{
byte blockId = 1;
SetBlock(x, y, z, blockId);
Console.WriteLine(
"Set block "
+ x.ToString() + ", "
+ y.ToString() + ", "
+ z.ToString() + " "
);
}
}
}
} }
// todo // todo
@@ -71,60 +62,25 @@
private int GetBlockIndex(int x, int y, int z) private int GetBlockIndex(int x, int y, int z)
{ {
return x + y * Size + z * Size * Size; return x + z * Size + y * Size * Size;
} }
public List<FaceData> GetFaces() private static readonly (int dx, int dy, int dz)[] Offsets = new (int, int, int)[6]
{ {
List<FaceData> list = new List<FaceData>(); ( 1, 0, 0), // +X
(-1, 0, 0), // -X
( 0, 1, 0), // +Y
( 0, -1, 0), // -Y
( 0, 0, 1), // +Z
( 0, 0, -1) // -Z
};
for (byte i = 0; i < 6; i++)
public ChunkMesh GetChunkMesh()
{ {
FaceData faceData = new FaceData(); ChunkMesh chunkMesh = new ChunkMesh(Size * Size * Height / 2);
faceData.Facing = (Orientation)i; // offsets table
list.Add(faceData);
}
for (byte i = 0; i < 6; i++)
{
FaceData faceData = new FaceData();
faceData.Facing = (Orientation)i;
faceData.X = 1;
list.Add(faceData);
}
for (byte i = 0; i < 6; i++)
{
FaceData faceData = new FaceData();
faceData.Facing = (Orientation)i;
faceData.X = 1;
faceData.Y = 1;
faceData.Z = 1;
list.Add(faceData);
}
for (byte i = 0; i < 6; i++)
{
FaceData faceData = new FaceData();
faceData.Facing = (Orientation)i;
faceData.X = 1;
faceData.Y = 2;
faceData.Z = 1;
list.Add(faceData);
}
for (int x = 0; x < Size; x++) for (int x = 0; x < Size; x++)
{ {
@@ -132,23 +88,40 @@
{ {
for (int y = 0; y < Height; y++) for (int y = 0; y < Height; y++)
{ {
for (byte i = 0; i < 6; i++) for (byte face = 0; face < 6; face++)
{ {
int indexBase = y * Size * Size + z * Size + x;
Blocks block = _blocks[indexBase];
if (block == Blocks.Air) continue; // ignore if air
int nx = x + Offsets[face].dx;
int ny = y + Offsets[face].dy;
int nz = z + Offsets[face].dz;
// check neighbor, ignore if at chunk edge
if (nx >= 0 && nx < Size &&
ny >= 0 && ny < Height &&
nz >= 0 && nz < Size &&
_blocks[GetBlockIndex(nx, ny, nz)] != 0)
continue;
FaceData faceData = new FaceData(); FaceData faceData = new FaceData();
faceData.Facing = (Orientation)i; faceData.Facing = (Orientation)face;
faceData.Texture = BlockDefinitions.Blocks[block].FaceTextures[face];
faceData.X = (byte)x; faceData.X = (byte)x;
faceData.Y = (byte)y; faceData.Y = (byte)y;
faceData.Z = (byte)z; faceData.Z = (byte)z;
//list.Add(faceData); chunkMesh.Faces.Add(faceData);
} }
} }
} }
} }
return list; return chunkMesh;
} }
} }
} }

View File

@@ -1,17 +1,18 @@
namespace Voxel using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Voxel
{ {
public class ChunkMesh public class ChunkMesh
{ {
private List<FaceData> _faces; public List<FaceData> Faces;
public ChunkMesh(Chunk chunk) public ChunkMesh(int maxBlocks)
{ {
_faces = new List<FaceData>(); Faces = new List<FaceData>(maxBlocks * 6);
}
private void MeshBlock(int i)
{
} }
} }
} }

View File

@@ -1,12 +0,0 @@
namespace Voxel
{
static class ChunkMesher
{
static ChunkMesh MeshChunk(Chunk chunk)
{
ChunkMesh chunkMesh = new ChunkMesh(chunk);
return chunkMesh;
}
}
}

View File

@@ -2,22 +2,24 @@
namespace Voxel namespace Voxel
{ {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FaceData public struct FaceData
{ {
public Orientation Facing; public Orientation Facing;
public uint X, Y, Z; public byte X, Y, Z;
public Texture Texture; public Textures Texture;
public byte LightLevel;
public uint[] Pack() public byte[] Pack()
{ {
return new uint[] return new byte[]
{ {
X, X,
Y, Y,
Z, Z,
(uint)Facing, (byte)Facing,
(uint)Texture (byte)Texture,
LightLevel,
0,0 // two bits empty
}; };
} }
} }

View File

@@ -8,12 +8,15 @@ internal class Program
int sizeY = 600; int sizeY = 600;
string title = "Game"; string title = "Game";
Window window = new Window(sizeX, sizeY, title);
Chunk chunk = new Chunk(0, 0); Chunk chunk = new Chunk(0, 0);
var faces = chunk.GetFaces(); ChunkMesh chunkMesh = chunk.GetChunkMesh();
Renderer.AddFaces(faces); Renderer.AddFaces(chunkMesh.Faces);
window.Chunk = chunk;
Window window = new Window(sizeX, sizeY, title);
window.Run(); window.Run();
} }
} }

View File

@@ -8,13 +8,19 @@ namespace Voxel
private static int _vao; private static int _vao;
private static List<FaceData> _faces = new List<FaceData>(); private static List<FaceData> _faces = new List<FaceData>();
private static Shader _shader; private static Shader _shader;
private static Texture _texture;
private static bool _needsUpdate = false; private static bool _needsUpdate = false;
public static void OnLoad() static Renderer()
{ {
string vertexPath = "Shaders/shader.vert"; string vertexPath = "Shaders/shader.vert";
string fragmentPath = "Shaders/shader.frag"; string fragmentPath = "Shaders/shader.frag";
string texturePath = "atlas.png";
_shader = new Shader(vertexPath, fragmentPath); _shader = new Shader(vertexPath, fragmentPath);
_texture = new Texture(texturePath);
_shader.SetInt("uTexture", 0);
_ssbo = GL.GenBuffer(); _ssbo = GL.GenBuffer();
_vao = GL.GenVertexArray(); _vao = GL.GenVertexArray();
@@ -32,9 +38,8 @@ namespace Voxel
if (_needsUpdate) if (_needsUpdate)
{ {
_needsUpdate = false; _needsUpdate = false;
Console.WriteLine("Update buffer"); byte[] data = _faces.SelectMany(f => f.Pack()).ToArray();
uint[] data = _faces.SelectMany(f => f.Pack()).ToArray(); GL.BufferData(BufferTarget.ShaderStorageBuffer, data.Length, data, BufferUsageHint.StaticRead);
GL.BufferData(BufferTarget.ShaderStorageBuffer, data.Length * sizeof(uint), data, BufferUsageHint.StaticRead);
} }
_shader.Use(); _shader.Use();
@@ -51,5 +56,10 @@ namespace Voxel
_faces.AddRange(faces); _faces.AddRange(faces);
_needsUpdate = true; _needsUpdate = true;
} }
public static void ClearFaces()
{
_faces.Clear();
}
} }
} }

View File

@@ -67,6 +67,17 @@ namespace Voxel
GL.UniformMatrix4(location, false, ref matrix); GL.UniformMatrix4(location, false, ref matrix);
} }
public void SetInt(string name, int value)
{
int location = GL.GetUniformLocation(_handle, name);
if (location == -1)
{
Console.WriteLine($"Uniform '{name}' not found in shader.");
return;
}
GL.Uniform1(location, value);
}
public void Use() public void Use()
{ {
GL.UseProgram(_handle); GL.UseProgram(_handle);

View File

@@ -1,9 +1,13 @@
#version 430 core #version 430 core
out vec4 FragColor; out vec4 FragColor;
in vec3 fragColor; in vec2 fragUV;
in float lighting;
uniform sampler2D uTexture;
void main() void main()
{ {
FragColor = vec4(fragColor, 1.0); vec4 texColor = texture(uTexture, fragUV);
FragColor = vec4(texColor.rgb * lighting, texColor.a);
} }

View File

@@ -6,101 +6,108 @@ struct FaceData {
uint z; uint z;
uint facing; // 0=+X,1=-X,2=+Y,3=-Y,4=+Z,5=-Z uint facing; // 0=+X,1=-X,2=+Y,3=-Y,4=+Z,5=-Z
uint texture; uint texture;
uint lightLevel;
}; };
layout(std430, binding = 0) buffer FaceBuffer { layout(std430, binding = 0) buffer FaceBuffer {
FaceData faces[]; uint faces[];
}; };
out vec3 fragColor; uniform mat4 view;
uniform mat4 projection;
vec3 getVertexOffset(uint facing, uint vertIndex) { out vec2 fragUV;
if (facing == 0u) { // +X out float lighting;
vec3 offsets[6] = vec3[6](
const float lightMult[6] = float[6](0.6, 0.6, 1.0, 0.5, 0.8, 0.8);
const vec3 offsets[6][6] = vec3[6][6](
vec3[6]( // +X
vec3(0.5, -0.5, -0.5), vec3(0.5, -0.5, -0.5),
vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5),
vec3(0.5, -0.5, 0.5), vec3(0.5, -0.5, 0.5),
vec3(0.5, 0.5, 0.5), vec3(0.5, 0.5, 0.5),
vec3(0.5, -0.5, -0.5), vec3(0.5, -0.5, -0.5),
vec3(0.5, 0.5, -0.5) vec3(0.5, 0.5, -0.5)
); ),
return offsets[vertIndex]; vec3[6]( // -X
} else if (facing == 1u) { // -X
vec3 offsets[6] = vec3[6](
vec3(-0.5, -0.5, 0.5), vec3(-0.5, -0.5, 0.5),
vec3(-0.5, 0.5, -0.5), vec3(-0.5, 0.5, -0.5),
vec3(-0.5, -0.5, -0.5), vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, -0.5), vec3(-0.5, 0.5, -0.5),
vec3(-0.5, -0.5, 0.5), vec3(-0.5, -0.5, 0.5),
vec3(-0.5, 0.5, 0.5) vec3(-0.5, 0.5, 0.5)
); ),
return offsets[vertIndex]; vec3[6]( // +Y
} else if (facing == 2u) { // +Y (top)
vec3 offsets[6] = vec3[6](
vec3(-0.5, 0.5, -0.5), vec3(-0.5, 0.5, -0.5),
vec3( 0.5, 0.5, 0.5), vec3( 0.5, 0.5, 0.5),
vec3( 0.5, 0.5, -0.5), vec3( 0.5, 0.5, -0.5),
vec3( 0.5, 0.5, 0.5), vec3( 0.5, 0.5, 0.5),
vec3(-0.5, 0.5, -0.5), vec3(-0.5, 0.5, -0.5),
vec3(-0.5, 0.5, 0.5) vec3(-0.5, 0.5, 0.5)
); ),
return offsets[vertIndex]; vec3[6](
} else if (facing == 3u) { // -Y (bottom)
vec3 offsets[6] = vec3[6](
vec3(-0.5, -0.5, 0.5), vec3(-0.5, -0.5, 0.5),
vec3( 0.5, -0.5, -0.5), vec3( 0.5, -0.5, -0.5),
vec3( 0.5, -0.5, 0.5), vec3( 0.5, -0.5, 0.5),
vec3( 0.5, -0.5, -0.5), vec3( 0.5, -0.5, -0.5),
vec3(-0.5, -0.5, 0.5), vec3(-0.5, -0.5, 0.5),
vec3(-0.5, -0.5, -0.5) vec3(-0.5, -0.5, -0.5)
); ),
return offsets[vertIndex]; vec3[6]( // +Z
} else if (facing == 4u) { // +Z (front)
vec3 offsets[6] = vec3[6](
vec3(-0.5, -0.5, 0.5),
vec3( 0.5, -0.5, 0.5), vec3( 0.5, -0.5, 0.5),
vec3( 0.5, 0.5, 0.5),
vec3( 0.5, 0.5, 0.5),
vec3(-0.5, 0.5, 0.5), vec3(-0.5, 0.5, 0.5),
vec3(-0.5, -0.5, 0.5) vec3(-0.5, -0.5, 0.5),
); vec3(-0.5, 0.5, 0.5),
return offsets[vertIndex]; vec3( 0.5, -0.5, 0.5),
} else if (facing == 5u) { // -Z (back) vec3( 0.5, 0.5, 0.5)
vec3 offsets[6] = vec3[6]( ),
vec3( 0.5, -0.5, -0.5), vec3[6]( // -Z
vec3(-0.5, -0.5, -0.5), vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, -0.5),
vec3(-0.5, 0.5, -0.5),
vec3( 0.5, 0.5, -0.5), vec3( 0.5, 0.5, -0.5),
vec3( 0.5, -0.5, -0.5) vec3( 0.5, -0.5, -0.5),
vec3( 0.5, 0.5, -0.5),
vec3(-0.5, -0.5, -0.5),
vec3(-0.5, 0.5, -0.5)
)
); );
return offsets[vertIndex];
}
}
uniform mat4 view; const vec2 uvs[6] = vec2[6](vec2(0,0), vec2(1,1), vec2(1,0), vec2(1,1), vec2(0,0), vec2(0,1));
uniform mat4 projection;
void main() void main()
{ {
float[6] lightMult = float[6]( uint faceIndex = gl_VertexID / 6u;
0.6, uint vertIndex = gl_VertexID % 6u;
0.6,
1.0,
0.5,
0.8,
0.8
);
uint faceIndex = gl_VertexID / 6; uint start = faceIndex * 2u; // 2 byte per face
uint vertIndex = gl_VertexID % 6;
FaceData f = faces[faceIndex]; uint u0 = faces[start]; // data in uint 0
vec3 basePos = vec3(f.x, f.y, f.z); uint u1 = faces[start + 1]; // data in uint 1
vec4 worldPos = vec4(basePos + getVertexOffset(f.facing, vertIndex), 1.0);
// extract values from bits
uint x = u0 & 0xFFu;
uint y = (u0 >> 8) & 0xFFu;
uint z = (u0 >> 16) & 0xFFu;
uint facing = (u0 >> 24) & 0xFFu;
uint texture = u1 & 0xFFu;
uint lightLevel = (u1 >> 8) & 0xFFu;
fragColor = vec3(1.0, 1.0, 1.0) * lightMult[f.facing]; vec3 basePos = vec3(x, y, z);
vec4 worldPos = vec4(basePos + offsets[facing][vertIndex], 1.0);
float light = float(lightLevel) / 255.0; // use later for caves and stuff
// UV mapping
uint col = texture & 15u; // texture % 16
uint row = texture >> 4; // texture / 16
row = 15u - row; // invert row so 0 is top
// convert to float after int math, divide by 16
vec2 uv = uvs[vertIndex] * 0.0625;
uv.x += float(col) * 0.0625;
uv.y += float(row) * 0.0625;
fragUV = uv;
lighting = lightMult[facing];
gl_Position = projection * view * worldPos; gl_Position = projection * view * worldPos;
} }

43
Texture.cs Normal file
View File

@@ -0,0 +1,43 @@
using OpenTK.Graphics.OpenGL4;
using StbImageSharp;
namespace Voxel
{
public class Texture
{
private int _handle;
private string _path;
public Texture(string path)
{
_handle = GL.GenTexture();
_path = path;
LoadFromFile();
}
private void LoadFromFile()
{
StbImage.stbi_set_flip_vertically_on_load(1);
ImageResult image = ImageResult.FromStream(File.OpenRead(_path), ColorComponents.RedGreenBlueAlpha);
GL.BindTexture(TextureTarget.Texture2D, _handle);
GL.TexImage2D(
TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
image.Width, image.Height, 0,
PixelFormat.Rgba, PixelType.UnsignedByte, image.Data
);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
}
public void Bind(TextureUnit unit = TextureUnit.Texture0)
{
GL.ActiveTexture(unit);
GL.BindTexture(TextureTarget.Texture2D, _handle);
}
}
}

44
Textures.cs Normal file
View File

@@ -0,0 +1,44 @@
namespace Voxel
{
public enum Textures : uint
{
GrassTop,
Stone,
Dirt,
GrassSide,
OakPlanks,
SmoothStoneSlab,
SmoothStone,
Bricks,
TntSide,
TntTop,
TntBottom,
Cobweb,
Rose,
Dandelion,
Water,
OakSapling,
Cobblestone,
Bedrock,
Sand,
Gravel,
OakSide,
OakTop,
IronBlock,
GoldBlock,
DiamondBlock,
EmeraldBlock,
RedstoneBlock,
none0,
RedMushroom,
BrownMushroom,
JungleSapling,
none1,
GoldOre,
IronOre,
CoalOre,
Bookshelf,
MossyCobblestone,
Obsidian,
}
}

View File

@@ -9,9 +9,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="OpenTK" Version="4.9.4" /> <PackageReference Include="OpenTK" Version="4.9.4" />
<PackageReference Include="StbImageSharp" Version="2.30.15" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="atlas.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Shaders\shader.frag"> <None Update="Shaders\shader.frag">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>

View File

@@ -11,6 +11,11 @@ namespace Voxel
public uint frames = 0; public uint frames = 0;
public double timeElapsed = 0; public double timeElapsed = 0;
// testing
public Chunk Chunk;
private Dictionary<int, bool> _cache = new Dictionary<int, bool>();
private bool chunkEmpty = false;
protected override void OnUpdateFrame(FrameEventArgs e) protected override void OnUpdateFrame(FrameEventArgs e)
{ {
base.OnUpdateFrame(e); base.OnUpdateFrame(e);
@@ -19,6 +24,31 @@ namespace Voxel
{ {
Close(); Close();
} }
RemoveRandomBlocks();
}
private void RemoveRandomBlocks()
{
if (Chunk != null && !chunkEmpty)
{
Random rng = new Random();
int GetNum()
{
int max = 4096;
int num = rng.Next(max);
if (_cache.ContainsKey(num)) return GetNum();
_cache[num] = true;
if (_cache.Count == max) chunkEmpty = true;
return num;
}
Chunk.SetBlockIndex(GetNum(), Blocks.Air);
}
Renderer.ClearFaces();
Renderer.AddFaces(Chunk.GetChunkMesh().Faces);
} }
protected override void OnRenderFrame(FrameEventArgs e) protected override void OnRenderFrame(FrameEventArgs e)
@@ -46,6 +76,8 @@ namespace Voxel
{ {
base.OnFramebufferResize(e); base.OnFramebufferResize(e);
Camera.UpdateProjection(e.Width, e.Height);
GL.Viewport(0, 0, e.Width, e.Height); GL.Viewport(0, 0, e.Width, e.Height);
} }
@@ -53,15 +85,17 @@ namespace Voxel
{ {
base.OnLoad(); base.OnLoad();
Renderer.OnLoad();
GL.ClearColor(0.72f, 0.88f, 0.97f, 1f); GL.ClearColor(0.72f, 0.88f, 0.97f, 1f);
GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.CullFace);
GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.DepthTest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
CursorState = CursorState.Grabbed; CursorState = CursorState.Grabbed;
VSync = VSyncMode.On; VSync = VSyncMode.On;
Camera.UpdateProjection(Width, Height);
} }
protected override void OnMouseMove(MouseMoveEventArgs e) protected override void OnMouseMove(MouseMoveEventArgs e)

BIN
atlas.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 87 KiB