From e0f30d30e2cf7cfba460756a788b4bcf5b9feb54 Mon Sep 17 00:00:00 2001 From: BlueCube3310 <53150244+BlueCube3310@users.noreply.github.com> Date: Thu, 30 May 2024 13:53:26 +0200 Subject: [PATCH] Improve layered texture preview --- editor/plugins/texture_3d_editor_plugin.cpp | 127 ++++++--- editor/plugins/texture_3d_editor_plugin.h | 8 +- editor/plugins/texture_editor_plugin.cpp | 7 +- .../plugins/texture_layered_editor_plugin.cpp | 241 ++++++++++++------ .../plugins/texture_layered_editor_plugin.h | 8 +- modules/noise/noise_texture_3d.cpp | 4 + modules/noise/noise_texture_3d.h | 2 + 7 files changed, 274 insertions(+), 123 deletions(-) diff --git a/editor/plugins/texture_3d_editor_plugin.cpp b/editor/plugins/texture_3d_editor_plugin.cpp index fa90e982feb..9fce79622a8 100644 --- a/editor/plugins/texture_3d_editor_plugin.cpp +++ b/editor/plugins/texture_3d_editor_plugin.cpp @@ -30,8 +30,25 @@ #include "texture_3d_editor_plugin.h" +#include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/label.h" +// Shader sources. + +constexpr const char *texture_3d_shader = R"( + // Texture3DEditor preview shader. + + shader_type canvas_item; + + uniform sampler3D tex; + uniform float layer; + + void fragment() { + COLOR = textureLod(tex, vec3(UV, layer), 0.0); + } +)"; + void Texture3DEditor::_texture_rect_draw() { texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1)); } @@ -48,6 +65,13 @@ void Texture3DEditor::_notification(int p_what) { draw_texture_rect(checkerboard, Rect2(Point2(), size), true); } break; + + case NOTIFICATION_THEME_CHANGED: { + if (info) { + Ref metadata_label_font = get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)); + info->add_theme_font_override(SceneStringName(font), metadata_label_font); + } + } break; } } @@ -55,35 +79,27 @@ void Texture3DEditor::_texture_changed() { if (!is_visible()) { return; } + + setting = true; + _update_gui(); + setting = false; + + _update_material(true); queue_redraw(); } -void Texture3DEditor::_update_material() { +void Texture3DEditor::_update_material(bool p_texture_changed) { material->set_shader_parameter("layer", (layer->get_value() + 0.5) / texture->get_depth()); - material->set_shader_parameter("tex", texture->get_rid()); - String format = Image::get_format_name(texture->get_format()); - - String text; - text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + "x" + itos(texture->get_depth()) + " " + format; - - info->set_text(text); + if (p_texture_changed) { + material->set_shader_parameter("tex", texture->get_rid()); + } } void Texture3DEditor::_make_shaders() { shader.instantiate(); - shader->set_code(R"( -// Texture3DEditor preview shader. + shader->set_code(texture_3d_shader); -shader_type canvas_item; - -uniform sampler3D tex; -uniform float layer; - -void fragment() { - COLOR = textureLod(tex, vec3(UV, layer), 0.0); -} -)"); material.instantiate(); material->set_shader(shader); } @@ -113,6 +129,41 @@ void Texture3DEditor::_texture_rect_update_area() { texture_rect->set_size(Vector2(tex_width, tex_height)); } +void Texture3DEditor::_update_gui() { + if (texture.is_null()) { + return; + } + + _texture_rect_update_area(); + + layer->set_max(texture->get_depth() - 1); + + const String format = Image::get_format_name(texture->get_format()); + + if (texture->has_mipmaps()) { + const int mip_count = Image::get_image_required_mipmaps(texture->get_width(), texture->get_height(), texture->get_format()); + const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), true) * texture->get_depth(); + + info->set_text(vformat(String::utf8("%d×%d×%d %s\n") + TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"), + texture->get_width(), + texture->get_height(), + texture->get_depth(), + format, + mip_count, + String::humanize_size(memory))); + + } else { + const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), false) * texture->get_depth(); + + info->set_text(vformat(String::utf8("%d×%d×%d %s\n") + TTR("No Mipmaps") + "\n" + TTR("Memory: %s"), + texture->get_width(), + texture->get_height(), + texture->get_depth(), + format, + String::humanize_size(memory))); + } +} + void Texture3DEditor::edit(Ref p_texture) { if (!texture.is_null()) { texture->disconnect_changed(callable_mp(this, &Texture3DEditor::_texture_changed)); @@ -126,15 +177,17 @@ void Texture3DEditor::edit(Ref p_texture) { } texture->connect_changed(callable_mp(this, &Texture3DEditor::_texture_changed)); - queue_redraw(); texture_rect->set_material(material); + setting = true; - layer->set_max(texture->get_depth() - 1); layer->set_value(0); layer->show(); - _update_material(); + _update_gui(); setting = false; - _texture_rect_update_area(); + + _update_material(true); + queue_redraw(); + } else { hide(); } @@ -142,36 +195,43 @@ void Texture3DEditor::edit(Ref p_texture) { Texture3DEditor::Texture3DEditor() { set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); - set_custom_minimum_size(Size2(1, 150)); + set_custom_minimum_size(Size2(1, 256.0) * EDSCALE); texture_rect = memnew(Control); texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE); - add_child(texture_rect); texture_rect->connect(SceneStringName(draw), callable_mp(this, &Texture3DEditor::_texture_rect_draw)); + add_child(texture_rect); + layer = memnew(SpinBox); layer->set_step(1); layer->set_max(100); - layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); + layer->set_modulate(Color(1, 1, 1, 0.8)); - add_child(layer); + layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); layer->set_anchor(SIDE_RIGHT, 1); layer->set_anchor(SIDE_LEFT, 1); layer->connect(SceneStringName(value_changed), callable_mp(this, &Texture3DEditor::_layer_changed)); + add_child(layer); + info = memnew(Label); + info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1)); + info->add_theme_color_override("font_shadow_color", Color(0, 0, 0)); + info->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE); + info->add_theme_color_override("font_outline_color", Color(0, 0, 0)); + info->add_theme_constant_override("outline_size", 8 * EDSCALE); + info->set_h_grow_direction(GROW_DIRECTION_BEGIN); info->set_v_grow_direction(GROW_DIRECTION_BEGIN); - info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1)); - info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5)); - info->add_theme_constant_override("shadow_outline_size", 1); - info->add_theme_constant_override("shadow_offset_x", 2); - info->add_theme_constant_override("shadow_offset_y", 2); - add_child(info); + info->set_h_size_flags(Control::SIZE_SHRINK_END); + info->set_v_size_flags(Control::SIZE_SHRINK_END); info->set_anchor(SIDE_RIGHT, 1); info->set_anchor(SIDE_LEFT, 1); info->set_anchor(SIDE_BOTTOM, 1); info->set_anchor(SIDE_TOP, 1); + + add_child(info); } Texture3DEditor::~Texture3DEditor() { @@ -180,7 +240,6 @@ Texture3DEditor::~Texture3DEditor() { } } -// bool EditorInspectorPlugin3DTexture::can_handle(Object *p_object) { return Object::cast_to(p_object) != nullptr; } diff --git a/editor/plugins/texture_3d_editor_plugin.h b/editor/plugins/texture_3d_editor_plugin.h index 7a33a97a8f8..0712ff423a7 100644 --- a/editor/plugins/texture_3d_editor_plugin.h +++ b/editor/plugins/texture_3d_editor_plugin.h @@ -52,23 +52,27 @@ class Texture3DEditor : public Control { bool setting = false; void _make_shaders(); - void _update_material(); void _layer_changed(double) { if (!setting) { - _update_material(); + _update_material(false); } } + void _texture_changed(); void _texture_rect_update_area(); void _texture_rect_draw(); + void _update_material(bool p_texture_changed); + void _update_gui(); + protected: void _notification(int p_what); public: void edit(Ref p_texture); + Texture3DEditor(); ~Texture3DEditor(); }; diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index e9d7aa9eb85..a3c14055535 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -145,12 +145,13 @@ TexturePreview::TexturePreview(Ref p_texture, bool p_show_metadata) { p_texture->connect_changed(callable_mp(this, &TexturePreview::_update_metadata_label_text)); // It's okay that these colors are static since the grid color is static too. - metadata_label->add_theme_color_override(SceneStringName(font_color), Color::named("white")); - metadata_label->add_theme_color_override("font_shadow_color", Color::named("black")); + metadata_label->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1)); + metadata_label->add_theme_color_override("font_shadow_color", Color(0, 0, 0)); metadata_label->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE); - metadata_label->add_theme_color_override("font_outline_color", Color::named("black")); + metadata_label->add_theme_color_override("font_outline_color", Color(0, 0, 0)); metadata_label->add_theme_constant_override("outline_size", 8 * EDSCALE); + metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END); metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END); diff --git a/editor/plugins/texture_layered_editor_plugin.cpp b/editor/plugins/texture_layered_editor_plugin.cpp index 4ec9c91cf9a..a8aa89a8c45 100644 --- a/editor/plugins/texture_layered_editor_plugin.cpp +++ b/editor/plugins/texture_layered_editor_plugin.cpp @@ -30,16 +30,64 @@ #include "texture_layered_editor_plugin.h" +#include "editor/editor_string_names.h" +#include "editor/themes/editor_scale.h" #include "scene/gui/label.h" +// Shader sources. + +constexpr const char *array_2d_shader = R"( + // TextureLayeredEditor preview shader (2D array). + + shader_type canvas_item; + + uniform sampler2DArray tex; + uniform float layer; + + void fragment() { + COLOR = textureLod(tex, vec3(UV, layer), 0.0); + } +)"; + +constexpr const char *cubemap_shader = R"( + // TextureLayeredEditor preview shader (cubemap). + + shader_type canvas_item; + + uniform samplerCube tex; + uniform vec3 normal; + uniform mat3 rot; + + void fragment() { + vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z)); + COLOR = textureLod(tex, n, 0.0); + } +)"; + +constexpr const char *cubemap_array_shader = R"( + // TextureLayeredEditor preview shader (cubemap array). + + shader_type canvas_item; + uniform samplerCubeArray tex; + uniform vec3 normal; + uniform mat3 rot; + uniform float layer; + + void fragment() { + vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z)); + COLOR = textureLod(tex, vec4(n, layer), 0.0); + } +)"; + void TextureLayeredEditor::gui_input(const Ref &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref mm = p_event; if (mm.is_valid() && (mm->get_button_mask().has_flag(MouseButtonMask::LEFT))) { y_rot += -mm->get_relative().x * 0.01; - x_rot += mm->get_relative().y * 0.01; - _update_material(); + x_rot += -mm->get_relative().y * 0.01; + + _update_material(false); } } @@ -47,6 +95,69 @@ void TextureLayeredEditor::_texture_rect_draw() { texture_rect->draw_rect(Rect2(Point2(), texture_rect->get_size()), Color(1, 1, 1, 1)); } +void TextureLayeredEditor::_update_gui() { + if (texture.is_null()) { + return; + } + + _texture_rect_update_area(); + + const String format = Image::get_format_name(texture->get_format()); + String texture_info; + + switch (texture->get_layered_type()) { + case TextureLayered::LAYERED_TYPE_2D_ARRAY: { + layer->set_max(texture->get_layers() - 1); + + texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"), + texture->get_width(), + texture->get_height(), + texture->get_layers(), + format); + + } break; + case TextureLayered::LAYERED_TYPE_CUBEMAP: { + layer->hide(); + + texture_info = vformat(String::utf8("%d×%d %s\n"), + texture->get_width(), + texture->get_height(), + format); + + } break; + case TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY: { + layer->set_max(texture->get_layers() / 6 - 1); + + texture_info = vformat(String::utf8("%d×%d (×%d) %s\n"), + texture->get_width(), + texture->get_height(), + texture->get_layers() / 6, + format); + + } break; + + default: { + } + } + + if (texture->has_mipmaps()) { + const int mip_count = Image::get_image_required_mipmaps(texture->get_width(), texture->get_height(), texture->get_format()); + const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), true) * texture->get_layers(); + + texture_info += vformat(TTR("%s Mipmaps") + "\n" + TTR("Memory: %s"), + mip_count, + String::humanize_size(memory)); + + } else { + const int memory = Image::get_image_data_size(texture->get_width(), texture->get_height(), texture->get_format(), false) * texture->get_layers(); + + texture_info += vformat(TTR("No Mipmaps") + "\n" + TTR("Memory: %s"), + String::humanize_size(memory)); + } + + info->set_text(texture_info); +} + void TextureLayeredEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_RESIZED: { @@ -59,6 +170,13 @@ void TextureLayeredEditor::_notification(int p_what) { draw_texture_rect(checkerboard, Rect2(Point2(), size), true); } break; + + case NOTIFICATION_THEME_CHANGED: { + if (info) { + Ref metadata_label_font = get_theme_font(SNAME("expression"), EditorStringName(EditorFonts)); + info->add_theme_font_override(SceneStringName(font), metadata_label_font); + } + } break; } } @@ -66,13 +184,18 @@ void TextureLayeredEditor::_texture_changed() { if (!is_visible()) { return; } + + setting = true; + _update_gui(); + setting = false; + + _update_material(true); queue_redraw(); } -void TextureLayeredEditor::_update_material() { +void TextureLayeredEditor::_update_material(bool p_texture_changed) { materials[0]->set_shader_parameter("layer", layer->get_value()); materials[2]->set_shader_parameter("layer", layer->get_value()); - materials[texture->get_layered_type()]->set_shader_parameter("tex", texture->get_rid()); Vector3 v(1, 1, 1); v.normalize(); @@ -86,67 +209,20 @@ void TextureLayeredEditor::_update_material() { materials[2]->set_shader_parameter("normal", v); materials[2]->set_shader_parameter("rot", b); - String format = Image::get_format_name(texture->get_format()); - - String text; - if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) { - text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers()) + ")" + format; - } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP) { - text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format; - } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) { - text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " (x " + itos(texture->get_layers() / 6) + ")" + format; + if (p_texture_changed) { + materials[texture->get_layered_type()]->set_shader_parameter("tex", texture->get_rid()); } - - info->set_text(text); } void TextureLayeredEditor::_make_shaders() { shaders[0].instantiate(); - shaders[0]->set_code(R"( -// TextureLayeredEditor preview shader (2D array). - -shader_type canvas_item; - -uniform sampler2DArray tex; -uniform float layer; - -void fragment() { - COLOR = textureLod(tex, vec3(UV, layer), 0.0); -} -)"); + shaders[0]->set_code(array_2d_shader); shaders[1].instantiate(); - shaders[1]->set_code(R"( -// TextureLayeredEditor preview shader (cubemap). - -shader_type canvas_item; - -uniform samplerCube tex; -uniform vec3 normal; -uniform mat3 rot; - -void fragment() { - vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z)); - COLOR = textureLod(tex, n, 0.0); -} -)"); + shaders[1]->set_code(cubemap_shader); shaders[2].instantiate(); - shaders[2]->set_code(R"( -// TextureLayeredEditor preview shader (cubemap array). - -shader_type canvas_item; - -uniform samplerCubeArray tex; -uniform vec3 normal; -uniform mat3 rot; -uniform float layer; - -void fragment() { - vec3 n = rot * normalize(vec3(normal.xy * (UV * 2.0 - 1.0), normal.z)); - COLOR = textureLod(tex, vec4(n, layer), 0.0); -} -)"); + shaders[2]->set_code(cubemap_array_shader); for (int i = 0; i < 3; i++) { materials[i].instantiate(); @@ -192,25 +268,20 @@ void TextureLayeredEditor::edit(Ref p_texture) { } texture->connect_changed(callable_mp(this, &TextureLayeredEditor::_texture_changed)); - queue_redraw(); texture_rect->set_material(materials[texture->get_layered_type()]); + setting = true; - if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_2D_ARRAY) { - layer->set_max(texture->get_layers() - 1); - layer->set_value(0); - layer->show(); - } else if (texture->get_layered_type() == TextureLayered::LAYERED_TYPE_CUBEMAP_ARRAY) { - layer->set_max(texture->get_layers() / 6 - 1); - layer->set_value(0); - layer->show(); - } else { - layer->hide(); - } + layer->set_value(0); + layer->show(); + _update_gui(); + setting = false; + x_rot = 0; y_rot = 0; - _update_material(); - setting = false; - _texture_rect_update_area(); + + _update_material(true); + queue_redraw(); + } else { hide(); } @@ -218,42 +289,48 @@ void TextureLayeredEditor::edit(Ref p_texture) { TextureLayeredEditor::TextureLayeredEditor() { set_texture_repeat(TextureRepeat::TEXTURE_REPEAT_ENABLED); - set_custom_minimum_size(Size2(1, 150)); + set_custom_minimum_size(Size2(0, 256.0) * EDSCALE); texture_rect = memnew(Control); texture_rect->set_mouse_filter(MOUSE_FILTER_IGNORE); - add_child(texture_rect); texture_rect->connect(SceneStringName(draw), callable_mp(this, &TextureLayeredEditor::_texture_rect_draw)); + add_child(texture_rect); + layer = memnew(SpinBox); layer->set_step(1); layer->set_max(100); - layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); + layer->set_modulate(Color(1, 1, 1, 0.8)); - add_child(layer); + layer->set_h_grow_direction(GROW_DIRECTION_BEGIN); layer->set_anchor(SIDE_RIGHT, 1); layer->set_anchor(SIDE_LEFT, 1); layer->connect(SceneStringName(value_changed), callable_mp(this, &TextureLayeredEditor::_layer_changed)); + add_child(layer); + info = memnew(Label); + info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1)); + info->add_theme_color_override("font_shadow_color", Color(0, 0, 0)); + info->add_theme_font_size_override(SceneStringName(font_size), 14 * EDSCALE); + info->add_theme_color_override("font_outline_color", Color(0, 0, 0)); + info->add_theme_constant_override("outline_size", 8 * EDSCALE); + info->set_h_grow_direction(GROW_DIRECTION_BEGIN); info->set_v_grow_direction(GROW_DIRECTION_BEGIN); - info->add_theme_color_override(SceneStringName(font_color), Color(1, 1, 1, 1)); - info->add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.5)); - info->add_theme_constant_override("shadow_outline_size", 1); - info->add_theme_constant_override("shadow_offset_x", 2); - info->add_theme_constant_override("shadow_offset_y", 2); - add_child(info); + info->set_h_size_flags(Control::SIZE_SHRINK_END); + info->set_v_size_flags(Control::SIZE_SHRINK_END); info->set_anchor(SIDE_RIGHT, 1); info->set_anchor(SIDE_LEFT, 1); info->set_anchor(SIDE_BOTTOM, 1); info->set_anchor(SIDE_TOP, 1); + + add_child(info); } TextureLayeredEditor::~TextureLayeredEditor() { } -// bool EditorInspectorPluginLayeredTexture::can_handle(Object *p_object) { return Object::cast_to(p_object) != nullptr; } diff --git a/editor/plugins/texture_layered_editor_plugin.h b/editor/plugins/texture_layered_editor_plugin.h index 83729f922ef..900ba94c6da 100644 --- a/editor/plugins/texture_layered_editor_plugin.h +++ b/editor/plugins/texture_layered_editor_plugin.h @@ -54,24 +54,28 @@ class TextureLayeredEditor : public Control { bool setting = false; void _make_shaders(); - void _update_material(); + void _update_material(bool p_texture_changed); void _layer_changed(double) { if (!setting) { - _update_material(); + _update_material(false); } } + void _texture_changed(); void _texture_rect_update_area(); void _texture_rect_draw(); + void _update_gui(); + protected: void _notification(int p_what); virtual void gui_input(const Ref &p_event) override; public: void edit(Ref p_texture); + TextureLayeredEditor(); ~TextureLayeredEditor(); }; diff --git a/modules/noise/noise_texture_3d.cpp b/modules/noise/noise_texture_3d.cpp index 1e929e6f637..9047491344c 100644 --- a/modules/noise/noise_texture_3d.cpp +++ b/modules/noise/noise_texture_3d.cpp @@ -331,6 +331,10 @@ int NoiseTexture3D::get_depth() const { return depth; } +bool NoiseTexture3D::has_mipmaps() const { + return false; +} + RID NoiseTexture3D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_3d_placeholder_create(); diff --git a/modules/noise/noise_texture_3d.h b/modules/noise/noise_texture_3d.h index 13125efe7f2..d55b78a2bad 100644 --- a/modules/noise/noise_texture_3d.h +++ b/modules/noise/noise_texture_3d.h @@ -103,6 +103,8 @@ public: virtual int get_height() const override; virtual int get_depth() const override; + virtual bool has_mipmaps() const override; + virtual RID get_rid() const override; virtual Vector> get_data() const override;