added chunk rendering
This commit is contained in:
parent
20f38ad3a9
commit
3ba2d75cff
BIN
.attachments/chunk-render.png
Normal file
BIN
.attachments/chunk-render.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@ -23,6 +23,8 @@ add_executable(VoxelEngine
|
||||
src/World.cpp
|
||||
src/Mesh.h
|
||||
src/Mesh.cpp
|
||||
src/Chunk.h
|
||||
src/Chunk.cpp
|
||||
)
|
||||
|
||||
# --- Configure GLAD (from your src/ and include/ folders) ---
|
||||
|
||||
@ -6,9 +6,15 @@ Currently, however, the program only renders a single cube.
|
||||
|
||||

|
||||
|
||||
## World Render - 11/10/25
|
||||
## World Mesh Rendering - 11/10/25
|
||||
|
||||
World now renders as a single mesh! Much faster than rendering cube by cube.
|
||||
|
||||

|
||||
|
||||
## Chunk Mesh Rendering - 11/11/25
|
||||
|
||||
Instead of making the _entire_ world a single mesh, now the world is made up of 32x32x32 "Chunks" which are areas of the world that are a single mesh.
|
||||
|
||||

|
||||
|
||||
|
||||
108
src/Chunk.cpp
Normal file
108
src/Chunk.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include "Chunk.h"
|
||||
#include <vector>
|
||||
|
||||
const int VERTEX_SIZE = 6;
|
||||
|
||||
const float topFace[24] = {
|
||||
// x, y, z, nx, ny, nz
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
const float bottomFace[24] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f
|
||||
};
|
||||
const float rightFace[24] = {
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f
|
||||
};
|
||||
const float leftFace[24] = {
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f
|
||||
};
|
||||
const float frontFace[24] = {
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
const float backFace[24] = {
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f
|
||||
};
|
||||
|
||||
void addFace(glm::ivec3 pos, const float *faceVertices, std::vector<float> &vbo, std::vector<unsigned int> &ebo) {
|
||||
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const float* v = &faceVertices[i * VERTEX_SIZE];
|
||||
vbo.push_back(v[0] + pos.x);
|
||||
vbo.push_back(v[1] + pos.y);
|
||||
vbo.push_back(v[2] + pos.z);
|
||||
vbo.push_back(v[3]);
|
||||
vbo.push_back(v[4]);
|
||||
vbo.push_back(v[5]);
|
||||
}
|
||||
ebo.push_back(vIndex + 0);
|
||||
ebo.push_back(vIndex + 1);
|
||||
ebo.push_back(vIndex + 2);
|
||||
ebo.push_back(vIndex + 0);
|
||||
ebo.push_back(vIndex + 2);
|
||||
ebo.push_back(vIndex + 3);
|
||||
}
|
||||
|
||||
Chunk::Chunk() {
|
||||
// mesh is initially null (nullptr)
|
||||
}
|
||||
|
||||
Mesh* Chunk::getMesh() {
|
||||
// Generate mesh on first access if not already generated
|
||||
if (!mesh && !voxels.empty()) {
|
||||
generateMesh();
|
||||
}
|
||||
return mesh.get();
|
||||
}
|
||||
|
||||
void Chunk::generateMesh() {
|
||||
std::vector<float> vboData;
|
||||
std::vector<unsigned int> eboData;
|
||||
|
||||
for (const glm::ivec3 pos : voxels) {
|
||||
if (voxels.count(pos + glm::ivec3(0, 1, 0)) == 0) {
|
||||
addFace(pos, topFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, -1, 0)) == 0) {
|
||||
addFace(pos, bottomFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(1, 0, 0)) == 0) {
|
||||
addFace(pos, rightFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(-1, 0, 0)) == 0) {
|
||||
addFace(pos, leftFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, 0, 1)) == 0) {
|
||||
addFace(pos, frontFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, 0, -1)) == 0) {
|
||||
addFace(pos, backFace, vboData, eboData);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and initialize mesh if it doesn't exist
|
||||
if (!mesh) {
|
||||
mesh = std::make_unique<Mesh>();
|
||||
mesh->init();
|
||||
}
|
||||
|
||||
// Now, upload this data to our mesh object
|
||||
mesh->uploadData(vboData, eboData);
|
||||
}
|
||||
43
src/Chunk.h
Normal file
43
src/Chunk.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef CHUNK_H
|
||||
#define CHUNK_H
|
||||
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
const int CHUNK_SIZE = 32;
|
||||
|
||||
// Hash function for glm::ivec3 to use with unordered_set
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<glm::ivec3> {
|
||||
size_t operator()(const glm::ivec3& v) const {
|
||||
// Combine hash values of x, y, z components
|
||||
size_t h1 = hash<int>()(v.x);
|
||||
size_t h2 = hash<int>()(v.y);
|
||||
size_t h3 = hash<int>()(v.z);
|
||||
|
||||
// Use a simple hash combination algorithm
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
std::unordered_set<glm::ivec3> voxels;
|
||||
|
||||
Chunk();
|
||||
|
||||
Mesh* getMesh(); // Returns pointer, can be null if not generated yet
|
||||
|
||||
void generateMesh();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Mesh> mesh; // Nullable mesh
|
||||
};
|
||||
|
||||
#endif CHUNK_H
|
||||
@ -1,3 +1,5 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
Mesh::Mesh() : m_VAO(0), m_VBO(0), m_EBO(0), m_indexCount(0) {}
|
||||
@ -38,10 +40,14 @@ void Mesh::init() {
|
||||
void Mesh::uploadData(const std::vector<float> &vboData, const std::vector<unsigned int> &eboData) {
|
||||
m_indexCount = eboData.size();
|
||||
|
||||
std::cout << "Uploading mesh: " << vboData.size() << " floats, " << eboData.size() << " indices" << std::endl;
|
||||
|
||||
// Bind VAO first, then upload buffer data
|
||||
glBindVertexArray(m_VAO);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(float), vboData.data(), GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(m_VAO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, eboData.size() * sizeof(unsigned int), eboData.data(), GL_STATIC_DRAW);
|
||||
glBindVertexArray(0);
|
||||
|
||||
104
src/World.cpp
104
src/World.cpp
@ -1,98 +1,22 @@
|
||||
#include "World.h"
|
||||
#include <vector>
|
||||
|
||||
const int VERTEX_SIZE = 6;
|
||||
World::World() {}
|
||||
|
||||
const float topFace[24] = {
|
||||
// x, y, z, nx, ny, nz
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f
|
||||
};
|
||||
const float bottomFace[24] = {
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f
|
||||
};
|
||||
const float rightFace[24] = {
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f
|
||||
};
|
||||
const float leftFace[24] = {
|
||||
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f
|
||||
};
|
||||
const float frontFace[24] = {
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
const float backFace[24] = {
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f
|
||||
};
|
||||
void World::flip_voxel(glm::ivec3 position) {
|
||||
glm::ivec3 chunk_position = position / CHUNK_SIZE;
|
||||
glm::ivec3 local_position = position % CHUNK_SIZE;
|
||||
|
||||
void addFace(glm::ivec3 pos, const float *faceVertices, std::vector<float> &vbo, std::vector<unsigned int> &ebo) {
|
||||
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
const float* v = &faceVertices[i * VERTEX_SIZE];
|
||||
vbo.push_back(v[0] + pos.x);
|
||||
vbo.push_back(v[1] + pos.y);
|
||||
vbo.push_back(v[2] + pos.z);
|
||||
vbo.push_back(v[3]);
|
||||
vbo.push_back(v[4]);
|
||||
vbo.push_back(v[5]);
|
||||
}
|
||||
ebo.push_back(vIndex + 0);
|
||||
ebo.push_back(vIndex + 1);
|
||||
ebo.push_back(vIndex + 2);
|
||||
ebo.push_back(vIndex + 0);
|
||||
ebo.push_back(vIndex + 2);
|
||||
ebo.push_back(vIndex + 3);
|
||||
}
|
||||
|
||||
World::World() {
|
||||
m_mesh.init();
|
||||
}
|
||||
|
||||
Mesh& World::getMesh() {
|
||||
return m_mesh;
|
||||
}
|
||||
|
||||
void World::generateMesh() {
|
||||
std::vector<float> vboData;
|
||||
std::vector<unsigned int> eboData;
|
||||
|
||||
for (const glm::ivec3 pos : voxels) {
|
||||
if (voxels.count(pos + glm::ivec3(0, 1, 0)) == 0) {
|
||||
addFace(pos, topFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, -1, 0)) == 0) {
|
||||
addFace(pos, bottomFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(1, 0, 0)) == 0) {
|
||||
addFace(pos, rightFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(-1, 0, 0)) == 0) {
|
||||
addFace(pos, leftFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, 0, 1)) == 0) {
|
||||
addFace(pos, frontFace, vboData, eboData);
|
||||
}
|
||||
if (voxels.count(pos + glm::ivec3(0, 0, -1)) == 0) {
|
||||
addFace(pos, backFace, vboData, eboData);
|
||||
Chunk * chunk = get_or_create_chunk(chunk_position);
|
||||
if (chunk->voxels.count(local_position) != 0) {
|
||||
chunk->voxels.erase(chunk->voxels.find(local_position));
|
||||
} else {
|
||||
chunk->voxels.insert(local_position);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, upload this data to our mesh object
|
||||
m_mesh.uploadData(vboData, eboData);
|
||||
Chunk* World::get_or_create_chunk(glm::ivec3 chunk_position) {
|
||||
if (this->chunks.count(chunk_position) == 0) {
|
||||
this->chunks[chunk_position] = Chunk();
|
||||
}
|
||||
return &this->chunks[chunk_position];
|
||||
}
|
||||
|
||||
31
src/World.h
31
src/World.h
@ -1,41 +1,22 @@
|
||||
#ifndef WORLD_H
|
||||
#define CAMERA_H
|
||||
#define WORLD_H
|
||||
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Mesh.h"
|
||||
|
||||
// Hash function for glm::ivec3 to use with unordered_set
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<glm::ivec3> {
|
||||
size_t operator()(const glm::ivec3& v) const {
|
||||
// Combine hash values of x, y, z components
|
||||
size_t h1 = hash<int>()(v.x);
|
||||
size_t h2 = hash<int>()(v.y);
|
||||
size_t h3 = hash<int>()(v.z);
|
||||
|
||||
// Use a simple hash combination algorithm
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||
}
|
||||
};
|
||||
}
|
||||
#include "Chunk.h"
|
||||
|
||||
class World
|
||||
{
|
||||
public:
|
||||
std::unordered_set<glm::ivec3> voxels;
|
||||
std::unordered_map<glm::ivec3, Chunk> chunks;
|
||||
|
||||
World();
|
||||
|
||||
void generateMesh();
|
||||
void flip_voxel(glm::ivec3 position);
|
||||
|
||||
Mesh& getMesh();
|
||||
|
||||
private:
|
||||
Mesh m_mesh;
|
||||
Chunk* get_or_create_chunk(glm::ivec3 chunk_position);
|
||||
};
|
||||
|
||||
#endif WORLD_H
|
||||
|
||||
84
src/main.cpp
84
src/main.cpp
@ -1,5 +1,4 @@
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <glad/glad.h> // Must be included before GLFW
|
||||
#include <GLFW/glfw3.h>
|
||||
@ -171,28 +170,6 @@ void processInput(GLFWwindow *window)
|
||||
camera.speed = CAMERA_SPEED * 20;
|
||||
}
|
||||
|
||||
// Draw a cube at some x, y, z
|
||||
// [UPDATED] Added a new 'color' parameter
|
||||
void draw_cube(glm::ivec3 coords, Shader& shader, unsigned int VAO, size_t indexCount, const glm::mat4& view, const glm::mat4& projection, const glm::vec3& color) {
|
||||
// Create model matrix for positioning the cube
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
model = glm::translate(model, glm::vec3(coords));
|
||||
|
||||
model = glm::scale(model, glm::vec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
// Calculate MVP matrix
|
||||
glm::mat4 mvp = projection * view * model;
|
||||
|
||||
// Set the uniform and draw
|
||||
shader.use();
|
||||
shader.setMat4("u_mvp", mvp);
|
||||
// [NEW] Set the color uniform in the fragment shader
|
||||
shader.setVec3("u_Color", color);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// 1. --- Initialize GLFW ---
|
||||
if (!glfwInit()) {
|
||||
@ -231,16 +208,15 @@ int main() {
|
||||
Object3D cube = Object3D("objs/cube.obj");
|
||||
|
||||
// Place cubes in the world
|
||||
for (int z = 0; z <= 32; z++) {
|
||||
for (int x = 0; x <= 32; x++) {
|
||||
world.voxels.insert(glm::ivec3(x, -1, z));
|
||||
for (int z = 0; z <= 256; z++) {
|
||||
for (int x = 0; x <= 256; x++) {
|
||||
world.flip_voxel(glm::ivec3(x, -1, z));
|
||||
}
|
||||
}
|
||||
|
||||
world.voxels.insert(glm::ivec3(7, 0, 13));
|
||||
std::cout << "Generating world mesh..." << std::endl;
|
||||
world.generateMesh();
|
||||
std::cout << "Mesh generated!" << std::endl;
|
||||
world.flip_voxel(glm::ivec3(7, 0, 13));
|
||||
std::cout << "World created with " << world.chunks.size() << " chunks" << std::endl;
|
||||
// Mesh generation now happens automatically when first rendering
|
||||
|
||||
if (WIREFRAME_MODE)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
@ -257,6 +233,7 @@ int main() {
|
||||
double move_time = glfwGetTime();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
bool debug_printed = false;
|
||||
|
||||
// 6. --- The Render Loop ---
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
@ -269,9 +246,13 @@ int main() {
|
||||
view = camera.getView();
|
||||
|
||||
shader.use();
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
glm::mat4 mvp = projection * view * model;
|
||||
shader.setMat4("u_mvp", mvp);
|
||||
|
||||
if (!debug_printed) {
|
||||
std::cout << "\n=== RENDER DEBUG ===" << std::endl;
|
||||
std::cout << "Camera pos: (" << camera.position.x << ", " << camera.position.y << ", " << camera.position.z << ")" << std::endl;
|
||||
std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||
std::cout << "Number of chunks to draw: " << world.chunks.size() << std::endl;
|
||||
}
|
||||
|
||||
// ---- PASS 1: Draw solid grey cubes ----
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
@ -279,7 +260,28 @@ int main() {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
shader.setVec3("u_Color", glm::vec3(0.5, 0.5, 0.5));
|
||||
|
||||
world.getMesh().draw();
|
||||
for (auto& [chunk_position, chunk] : world.chunks) {
|
||||
|
||||
glm::ivec3 chunk_offset = chunk_position * CHUNK_SIZE;
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
model = glm::translate(model, glm::vec3(chunk_offset));
|
||||
glm::mat4 mvp = projection * view * model;
|
||||
shader.setMat4("u_mvp", mvp);
|
||||
|
||||
if (!debug_printed) {
|
||||
std::cout << "Drawing chunk at (" << chunk_position.x << ", " << chunk_position.y << ", " << chunk_position.z << ")" << std::endl;
|
||||
std::cout << "Chunk offset: (" << chunk_offset.x << ", " << chunk_offset.y << ", " << chunk_offset.z << ")" << std::endl;
|
||||
}
|
||||
|
||||
Mesh* chunkMesh = chunk.getMesh();
|
||||
if (chunkMesh) {
|
||||
chunkMesh->draw();
|
||||
}
|
||||
}
|
||||
|
||||
if (!debug_printed) {
|
||||
debug_printed = true;
|
||||
}
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
@ -287,7 +289,19 @@ int main() {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Just the lines
|
||||
shader.setVec3("u_Color", glm::vec3(1.0, 1.0, 1.0));
|
||||
|
||||
world.getMesh().draw();
|
||||
for (auto& [chunk_position, chunk] : world.chunks) {
|
||||
|
||||
glm::ivec3 chunk_offset = chunk_position * CHUNK_SIZE;
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
model = glm::translate(model, glm::vec3(chunk_offset));
|
||||
glm::mat4 mvp = projection * view * model;
|
||||
shader.setMat4("u_mvp", mvp);
|
||||
|
||||
Mesh* chunkMesh = chunk.getMesh();
|
||||
if (chunkMesh) {
|
||||
chunkMesh->draw();
|
||||
}
|
||||
}
|
||||
|
||||
// --- Reset polygon mode for next frame (good practice) ---
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user