feat: grass (#11)

* feat: add grass texture and update grass_block texture

* feat: add block data

* feat: add blocks_tool

* feat: add sync info and change function in blocks_tools

* feat: add check and new function

* refactor: make block texture loading data-driven

* feat: add rendering for grass

* feat: passable grass

* feat: random grass place

* fix: memory leak in TextureManager::load_cross_plane_texture
This commit is contained in:
zhenyan121
2026-05-28 21:34:36 +08:00
committed by GitHub
parent bbf8b4e969
commit 5901ab7cd9
47 changed files with 1193 additions and 210 deletions

View File

@@ -16,6 +16,7 @@ TextureManager::~TextureManager() { delet_texture(); }
void TextureManager::delet_texture() {
glDeleteTextures(1, &m_texture_array);
glDeleteTextures(1, &m_block_status_array);
glDeleteTextures(1, &m_cross_plane_array);
for (auto& id : m_item_textures) {
glDeleteTextures(1, &id);
}
@@ -28,6 +29,9 @@ GLuint TextureManager::get_block_status_array() const {
GLuint TextureManager::get_texture_array() const { return m_texture_array; }
GLuint TextureManager::get_cross_plane_array() const {
return m_cross_plane_array;
}
GLuint TextureManager::get_ui_array() const { return m_ui_array; }
const std::vector<GLuint>& TextureManager::item_textures() const {
@@ -47,12 +51,18 @@ void TextureManager::load_block_status(unsigned id) {
}
void TextureManager::load_block_texture(unsigned id) {
ASSERT_MSG(id < MAX_BLOCK_NUM, "Exceed the max block sum limit");
std::string name{MapTable::get_name_from_id(id)};
ASSERT_MSG(id < BlockManager::sums(), "Exceed the max block sum limit");
std::string name{BlockManager::name_form_id(id)};
// air don`t need texture
if (id == 0) {
return;
}
if (BlockManager::is_cross_plane(id)) {
load_cross_plane_texture(id);
return;
}
unsigned char* image_data[6];
std::string block_texture_path = "texture/block/" + name;
@@ -73,7 +83,11 @@ void TextureManager::load_block_texture(unsigned id) {
}
}
void TextureManager::load_item_texture(const std::string& name) {
void TextureManager::load_block_item_texture(unsigned id) {
ASSERT_MSG(id < BlockManager::sums(), "Exceed the max block sum limit");
std::string name{BlockManager::name_form_id(id)};
std::string path = "texture/item/block/" + name + ".png";
unsigned char* data = nullptr;
data = Tools::load_image_data(path);
@@ -95,6 +109,17 @@ void TextureManager::load_item_texture(const std::string& name) {
Tools::delete_image_data(data);
}
void TextureManager::load_cross_plane_texture(unsigned id) {
std::string path =
"texture/block/" + BlockManager::name_form_id(id) + "/cross.png";
unsigned char* image_data = Tools::load_image_data(path);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0,
BlockManager::cross_plane_index(id), 16, 16, 1, GL_RGBA,
GL_UNSIGNED_BYTE, image_data);
Tools::delete_image_data(image_data);
}
void TextureManager::load_ui_texture(unsigned id) {
ASSERT_MSG(id < MAX_UI_NUM, "Exceed the max ui sum limit");
@@ -107,19 +132,22 @@ void TextureManager::load_ui_texture(unsigned id) {
Tools::delete_image_data(image_data);
}
void TextureManager::init_item() {
auto& map = MapTable::item_map();
for (const auto& name : map) {
load_item_texture(name);
}
}
void TextureManager::init_block() {
glGenTextures(1, &m_texture_array);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16, MAX_BLOCK_NUM * 6, 0,
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
for (int i = 0; i < MAX_BLOCK_NUM; i++) {
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16,
BlockManager::sums() * 6, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
glGenTextures(1, &m_cross_plane_array);
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 16, 16,
BlockManager::cross_plane_sum(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
for (unsigned i = 0; i < BlockManager::sums(); i++) {
load_block_texture(i);
load_block_item_texture(i);
}
glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture_array);
@@ -131,6 +159,17 @@ void TextureManager::init_block() {
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
static_cast<GLfloat>(m_aniso));
}
glBindTexture(GL_TEXTURE_2D_ARRAY, m_cross_plane_array);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
if (m_aniso >= 1) {
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY,
static_cast<GLfloat>(m_aniso));
}
Logger::info("Block Texture Load Success");
}
void TextureManager::init_ui() {
@@ -181,7 +220,6 @@ void TextureManager::init_texture() {
init_block();
init_block_status();
init_ui();
init_item();
}
void TextureManager::update() {