refactor(render): replace UI shaders with image shaders and Image widget

This commit is contained in:
2026-07-11 14:54:08 +08:00
parent 09653c318a
commit 2d28488126
19 changed files with 213 additions and 127 deletions

View File

@@ -61,4 +61,5 @@ target_sources(${PROJECT_NAME}
ui/widget.cpp
ui/label.cpp
ui/ui_vertex_data.cpp
ui/image.cpp
)

View File

@@ -21,22 +21,22 @@ void DebugCollector::init_text() {
#else
version.append("-release");
#endif
version_text.set_position(0.0f, 100.0f)
.set_scale(0.8f)
.set_color(Color::WHITE)
.set_text(version);
version_text.set_color(Color::WHITE)
.set_text(version)
.set_position(0.0f, 100.0f)
.set_scale(0.8f);
m_component.try_emplace(version_text.id(), &version_text);
// fps
auto& fps_text = m_widget.add_child<Label>("fps");
fps_text.set_position(0.0f, 50.0f).set_text("FPS: 0");
fps_text.set_text("FPS: 0").set_position(0.0f, 50.0f);
m_component.try_emplace(fps_text.id(), &fps_text);
// player_pos
auto& player_pos_text = m_widget.add_child<Label>("player_pos");
player_pos_text.set_position(0.0f, 150.0f)
.set_scale(0.8f)
.set_text("x: 0.00 y: 0.00 z: 0.00");
player_pos_text.set_text("x: 0.00 y: 0.00 z: 0.00")
.set_position(0.0f, 150.0f)
.set_scale(0.8f);
m_component.try_emplace(player_pos_text.id(), &player_pos_text);
// rendered_chunk

View File

@@ -119,6 +119,13 @@ void Renderer::init(bool debug_on) {
VertexArray::unbind();
VertexBuffer::unbind();
m_crosshair_image = std::make_unique<Image>();
m_crosshair_image->set_image("texture/ui/0.png");
m_crosshair_image
->set_position(m_width / 2 + m_crosshair_image->width() / 2,
m_height / 2 + m_crosshair_image->height() / 2)
.set_scale(3.0f);
m_init = true;
}
@@ -150,9 +157,15 @@ void Renderer::render() {
m_world_renderer.render();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
render_ui();
render_dev_panel();
glEnable(GL_DEPTH_TEST);
}
void Renderer::render_lable(const Label& label) {
@@ -161,11 +174,6 @@ void Renderer::render_lable(const Label& label) {
shader.use();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_DEPTH_TEST);
shader.set_loc("projection", m_ui_proj_matrix);
Font::text_texture()->bind(0);
@@ -183,8 +191,24 @@ void Renderer::render_lable(const Label& label) {
shader.set_loc("mv_matrix", model_matrix);
glDrawArrays(GL_TRIANGLES, 0, data.m_sum);
}
glEnable(GL_DEPTH_TEST);
void Renderer::render_image(const Image& image) {
const auto& shader = get_shader("image");
shader.use();
auto& pos = image.pos();
glm::mat4 model_matrix =
glm::translate(glm::mat4(1.0f), glm::vec3(pos.x, pos.y, 0.0f)) *
glm::scale(glm::mat4(1.0f),
glm::vec3(image.width() * image.scale(),
image.height() * image.scale(), 1.0f));
shader.set_loc("model_matrix", model_matrix);
shader.set_loc("proj_matrix", m_ui_proj_matrix);
m_vao[3].bind();
image.texture().bind(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
Tools::check_opengl_error();
}
void Renderer::render_ui() {
@@ -194,25 +218,7 @@ void Renderer::render_ui() {
render_crosshair();
}
void Renderer::render_crosshair() {
const auto& shader = get_shader("ui");
shader.use();
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader.set_loc("m_matrix", m_ui_model_matrix);
shader.set_loc("proj_matrix", m_ui_proj_matrix);
m_vao[3].bind();
m_texture_manager.get_ui_array()->bind(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
Tools::check_opengl_error();
glEnable(GL_DEPTH_TEST);
}
void Renderer::render_crosshair() { m_crosshair_image->render(*this); }
void Renderer::update(float delta_time) { m_delta_time = delta_time; }
@@ -231,10 +237,9 @@ void Renderer::update_proj_matrix(float aspect, float width, float height) {
m_ui_proj_matrix = glm::ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f);
// scale and then translate
m_ui_model_matrix =
glm::translate(glm::mat4(1.0f),
glm::vec3(width / 2.0f, height / 2.0f, 0.0)) *
glm::scale(glm::mat4(1.0f), glm::vec3(50.0f, 50.0f, 1.0f));
m_crosshair_image->set_position(
width / 2.0f + m_crosshair_image->width() / 2,
height / 2.0f + m_crosshair_image->height() / 2);
}
void Renderer::updata_framebuffer(int width, int height) {

View File

@@ -13,8 +13,8 @@ void ShaderManager::init() {
"shaders/outline_f_shader.glsl");
register_shader("sky", "shaders/sky_v_shader.glsl",
"shaders/sky_f_shader.glsl");
register_shader("ui", "shaders/ui_v_shader.glsl",
"shaders/ui_f_shader.glsl");
register_shader("image", "shaders/image_v_shader.glsl",
"shaders/image_f_shader.glsl");
register_shader("text", "shaders/text_v_shader.glsl",
"shaders/text_f_shader.glsl");
register_shader("under_water", "shaders/under_water_v_shader.glsl",

View File

@@ -77,15 +77,11 @@ void TextureManager::load_block_status(unsigned id) {
std::string path = "texture/status/" + std::to_string(id) + ".png";
unsigned char* image_data = nullptr;
image_data = (Tools::load_image_data(path));
auto image_data = (Tools::load_image_data(path));
m_block_status_array->tex_sub_image_3d(
TextureFormat::RGBA, GL_UNSIGNED_BYTE, image_data, 0, 0, id,
TextureFormat::RGBA, GL_UNSIGNED_BYTE, image_data.data, 0, 0, id,
BLOCK_STATUS_SIZE, BLOCK_STATUS_SIZE);
Tools::delete_image_data(image_data);
}
void TextureManager::load_block_texture(unsigned id) {
@@ -101,7 +97,7 @@ void TextureManager::load_block_texture(unsigned id) {
return;
}
unsigned char* image_data[6];
std::array<ImageData, 6> image_data;
std::string block_texture_path = "texture/block/" + name;
image_data[0] = (Tools::load_image_data(block_texture_path + "/front.png"));
@@ -114,10 +110,9 @@ void TextureManager::load_block_texture(unsigned id) {
Tools::check_opengl_error();
for (int i = 0; i < 6; i++) {
m_texture_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
image_data[i], 0, 0, id * 6 + i,
image_data[i].data, 0, 0, id * 6 + i,
BLOCK_SIZE, BLOCK_SIZE);
Tools::check_opengl_error();
Tools::delete_image_data(image_data[i]);
}
}
@@ -127,41 +122,37 @@ void TextureManager::load_block_item_texture(unsigned id) {
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);
auto data = Tools::load_image_data(path);
std::unique_ptr<Texture> texture =
std::make_unique<Texture>(TextureType::TEXTURE_2D);
texture->tex_image_2d(TextureFormat::RGBA8, TextureFormat::RGBA,
GL_UNSIGNED_BYTE, data, BLOCK_ITEM_SIZE,
GL_UNSIGNED_BYTE, data.data, BLOCK_ITEM_SIZE,
BLOCK_ITEM_SIZE);
texture->set_nearest();
texture->set_clamp_to_border();
m_item_textures.push_back(std::move(texture));
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);
auto image_data = Tools::load_image_data(path);
m_cross_plane_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
image_data, 0, 0,
image_data.data, 0, 0,
BlockManager::cross_plane_index(id),
CROSS_PLANE_SIZE, CROSS_PLANE_SIZE);
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");
std::string path = "texture/ui/" + std::to_string(id) + ".png";
unsigned char* image_data = nullptr;
image_data = (Tools::load_image_data(path));
auto image_data = (Tools::load_image_data(path));
m_ui_array->tex_sub_image_3d(TextureFormat::RGBA, GL_UNSIGNED_BYTE,
image_data, 0, 0, id, UI_SIZE, UI_SIZE);
Tools::delete_image_data(image_data);
image_data.data, 0, 0, id, UI_SIZE, UI_SIZE);
}
void TextureManager::load_pbr_texture(unsigned id) {
@@ -177,7 +168,7 @@ void TextureManager::load_pbr_texture(unsigned id) {
std::string path = "normal/block/" + BlockManager::name_form_id(id);
unsigned char* image_data[6];
std::array<ImageData, 6> image_data;
image_data[0] = (Tools::load_image_data(path + "/front_n.png", false));
image_data[1] = (Tools::load_image_data(path + "/right_n.png", false));
@@ -187,7 +178,7 @@ void TextureManager::load_pbr_texture(unsigned id) {
image_data[5] = (Tools::load_image_data(path + "/base_n.png", false));
for (int i = 0; i < 6; i++) {
unsigned char* data = image_data[i];
unsigned char* data = image_data[i].data;
bool is_fallback = false;
if (!data) {
is_fallback = true;
@@ -200,7 +191,6 @@ void TextureManager::load_pbr_texture(unsigned id) {
if (is_fallback) {
delete[] data;
} else {
Tools::delete_image_data(image_data[i]);
}
}
}
@@ -257,11 +247,11 @@ void TextureManager::init_ui() {
void TextureManager::init_skin() {
m_skin = std::make_unique<Texture>(TextureType::TEXTURE_2D);
std::string path = "texture/skin/player001.png";
unsigned char* image_data = nullptr;
image_data = (Tools::load_image_data(path));
auto image_data = (Tools::load_image_data(path));
m_skin->tex_image_2d(TextureFormat::RGBA, TextureFormat::RGBA,
GL_UNSIGNED_BYTE, image_data, SKIN_SIZE, SKIN_SIZE);
Tools::delete_image_data(image_data);
GL_UNSIGNED_BYTE, image_data.data, SKIN_SIZE,
SKIN_SIZE);
m_skin->set_nearest_and_minpmap();
m_skin->set_aniso(m_aniso);
}

View File

@@ -174,8 +174,7 @@ void delete_image_data(unsigned char* data) {
SOIL_free_image_data(data);
}
unsigned char* load_image_data(const std::string& tex_image_path,
bool check_exist) {
ImageData load_image_data(const std::string& tex_image_path, bool check_exist) {
fs::path path = ASSETS_PATH + tex_image_path;
if (check_exist) {
ASSERT_MSG(fs::is_regular_file(path), path.c_str());
@@ -193,7 +192,7 @@ unsigned char* load_image_data(const std::string& tex_image_path,
}
}
return data;
return {data, width, height, channels};
}
} // namespace Tools

27
src/ui/image.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include "Cubed/ui/image.hpp"
#include "Cubed/render/renderer.hpp"
#include "Cubed/tools/shader_tools.hpp"
namespace Cubed {
Image::Image() : m_texture(TextureType::TEXTURE_2D) {}
void Image::update(float dt) { (void)dt; }
void Image::render(Renderer& renderer) { renderer.render_image(*this); }
Image& Image::set_image(std::filesystem::path path) {
auto data = Tools::load_image_data(path);
m_texture.tex_image_2d(RGBA, RGBA, GL_UNSIGNED_BYTE, data.data, data.width,
data.height);
m_height = data.height;
m_width = data.width;
m_texture.set_nearest();
return *this;
}
float Image::height() const { return m_height; }
float Image::width() const { return m_width; }
const Texture& Image::texture() const { return m_texture; }
} // namespace Cubed

View File

@@ -11,21 +11,6 @@ Label& Label::set_text(std::string_view text) {
return *this;
}
Label& Label::set_position(const glm::vec2& pos) {
return set_position(pos.x, pos.y);
}
Label& Label::set_position(float x, float y) {
m_pos.x = x;
m_pos.y = y;
return *this;
}
Label& Label::set_scale(float scale) {
m_scale = scale;
return *this;
}
Label& Label::set_color(Color color) {
m_text.color = color;
return *this;
@@ -52,7 +37,6 @@ void Label::update_vertices() {
}
const UIVertexData& Label::data() const { return m_data; }
const glm::vec2& Label::pos() const { return m_pos; }
const TextStyle& Label::text_style() const { return m_text; }
float Label::scale() const { return m_scale; }
} // namespace Cubed

View File

@@ -21,6 +21,22 @@ void Widget::render(Renderer& renderer) {
void Widget::on_update(float dt) {}
void Widget::on_render(Renderer& renderer) {}
Widget& Widget::set_position(const glm::vec2& pos) {
return set_position(pos.x, pos.y);
}
Widget& Widget::set_position(float x, float y) {
m_pos.x = x;
m_pos.y = y;
return *this;
}
Widget& Widget::set_scale(float scale) {
m_scale = scale;
return *this;
}
const glm::vec2& Widget::pos() const { return m_pos; }
float Widget::scale() const { return m_scale; }
const std::string& Widget::id() const { return m_id; }
} // namespace Cubed