diff options
author | Rémi Verschelde <remi@verschelde.fr> | 2021-06-30 20:18:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-30 20:18:59 +0200 |
commit | 270f9d4c88c43895ae6d6a4ff8247f77f811beda (patch) | |
tree | 767dc2499fa3fc5c023dbfc28b1f4812f0148016 /scene/3d | |
parent | a02620f3a5f3b94c68dfbe18874b34ac1c32374a (diff) | |
parent | 85cf99f28e93556f1298a5136254253f9da82b9a (diff) |
Merge pull request #50014 from reduz/remove-immediate
Deprecate ImmediateGeometry
Diffstat (limited to 'scene/3d')
-rw-r--r-- | scene/3d/immediate_geometry_3d.cpp | 157 | ||||
-rw-r--r-- | scene/3d/immediate_geometry_3d.h | 72 | ||||
-rw-r--r-- | scene/3d/soft_body_3d.cpp | 2 | ||||
-rw-r--r-- | scene/3d/sprite_3d.cpp | 306 | ||||
-rw-r--r-- | scene/3d/sprite_3d.h | 49 |
5 files changed, 261 insertions, 325 deletions
diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp deleted file mode 100644 index d64babaa9d..0000000000 --- a/scene/3d/immediate_geometry_3d.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry_3d.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "immediate_geometry_3d.h" - -void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture) { - RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); - if (p_texture.is_valid()) { - cached_textures.push_back(p_texture); - } -} - -void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) { - RS::get_singleton()->immediate_normal(im, p_normal); -} - -void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) { - RS::get_singleton()->immediate_tangent(im, p_tangent); -} - -void ImmediateGeometry3D::set_color(const Color &p_color) { - RS::get_singleton()->immediate_color(im, p_color); -} - -void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) { - RS::get_singleton()->immediate_uv(im, p_uv); -} - -void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) { - RS::get_singleton()->immediate_uv2(im, p_uv2); -} - -void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) { - RS::get_singleton()->immediate_vertex(im, p_vertex); - if (empty) { - aabb.position = p_vertex; - aabb.size = Vector3(); - empty = false; - } else { - aabb.expand_to(p_vertex); - } -} - -void ImmediateGeometry3D::end() { - RS::get_singleton()->immediate_end(im); -} - -void ImmediateGeometry3D::clear() { - RS::get_singleton()->immediate_clear(im); - empty = true; - cached_textures.clear(); -} - -AABB ImmediateGeometry3D::get_aabb() const { - return aabb; -} - -Vector<Face3> ImmediateGeometry3D::get_faces(uint32_t p_usage_flags) const { - return Vector<Face3>(); -} - -void ImmediateGeometry3D::add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv) { - const double lat_step = Math_TAU / p_lats; - const double lon_step = Math_TAU / p_lons; - - for (int i = 1; i <= p_lats; i++) { - double lat0 = lat_step * (i - 1) - Math_TAU / 4; - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = lat_step * i - Math_TAU / 4; - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for (int j = p_lons; j >= 1; j--) { - double lng0 = lon_step * (j - 1); - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = lon_step * j; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v[4] = { - Vector3(x1 * zr0, z0, y1 * zr0), - Vector3(x1 * zr1, z1, y1 * zr1), - Vector3(x0 * zr1, z1, y0 * zr1), - Vector3(x0 * zr0, z0, y0 * zr0) - }; - -#define ADD_POINT(m_idx) \ - if (p_add_uv) { \ - set_uv(Vector2(Math::atan2(v[m_idx].x, v[m_idx].z) / Math_PI * 0.5 + 0.5, v[m_idx].y * 0.5 + 0.5)); \ - set_tangent(Plane(Vector3(-v[m_idx].z, v[m_idx].y, v[m_idx].x), 1)); \ - } \ - set_normal(v[m_idx]); \ - add_vertex(v[m_idx] * p_radius); - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } -} - -void ImmediateGeometry3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("begin", "primitive", "texture"), &ImmediateGeometry3D::begin, DEFVAL(Ref<Texture2D>())); - ClassDB::bind_method(D_METHOD("set_normal", "normal"), &ImmediateGeometry3D::set_normal); - ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &ImmediateGeometry3D::set_tangent); - ClassDB::bind_method(D_METHOD("set_color", "color"), &ImmediateGeometry3D::set_color); - ClassDB::bind_method(D_METHOD("set_uv", "uv"), &ImmediateGeometry3D::set_uv); - ClassDB::bind_method(D_METHOD("set_uv2", "uv"), &ImmediateGeometry3D::set_uv2); - ClassDB::bind_method(D_METHOD("add_vertex", "position"), &ImmediateGeometry3D::add_vertex); - ClassDB::bind_method(D_METHOD("add_sphere", "lats", "lons", "radius", "add_uv"), &ImmediateGeometry3D::add_sphere, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("end"), &ImmediateGeometry3D::end); - ClassDB::bind_method(D_METHOD("clear"), &ImmediateGeometry3D::clear); -} - -ImmediateGeometry3D::ImmediateGeometry3D() { - im = RenderingServer::get_singleton()->immediate_create(); - set_base(im); -} - -ImmediateGeometry3D::~ImmediateGeometry3D() { - RenderingServer::get_singleton()->free(im); -} diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h deleted file mode 100644 index ee4938d9f7..0000000000 --- a/scene/3d/immediate_geometry_3d.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************/ -/* immediate_geometry_3d.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef IMMEDIATE_GEOMETRY_3D_H -#define IMMEDIATE_GEOMETRY_3D_H - -#include "scene/3d/visual_instance_3d.h" -#include "scene/resources/mesh.h" - -class ImmediateGeometry3D : public GeometryInstance3D { - GDCLASS(ImmediateGeometry3D, GeometryInstance3D); - - RID im; - //a list of textures drawn need to be kept, to avoid references - // in RenderingServer from becoming invalid if the texture is no longer used - List<Ref<Texture2D>> cached_textures; - bool empty = true; - AABB aabb; - -protected: - static void _bind_methods(); - -public: - void begin(Mesh::PrimitiveType p_primitive, const Ref<Texture2D> &p_texture = Ref<Texture2D>()); - void set_normal(const Vector3 &p_normal); - void set_tangent(const Plane &p_tangent); - void set_color(const Color &p_color); - void set_uv(const Vector2 &p_uv); - void set_uv2(const Vector2 &p_uv2); - - void add_vertex(const Vector3 &p_vertex); - - void end(); - void clear(); - - void add_sphere(int p_lats, int p_lons, float p_radius, bool p_add_uv = true); - - virtual AABB get_aabb() const override; - virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override; - - ImmediateGeometry3D(); - ~ImmediateGeometry3D(); -}; - -#endif // IMMEDIATE_GEOMETRY_H diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 9592fe5849..324131d400 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -81,7 +81,7 @@ void SoftBodyRenderingServerHandler::close() { } void SoftBodyRenderingServerHandler::commit_changes() { - RS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer); } void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 9ec461d973..8a79b03ad4 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -164,6 +164,8 @@ void SpriteBase3D::_im_update() { _draw(); pending_update = false; + + //texture->draw_rect_region(ci,dst_rect,src_rect,modulate); } void SpriteBase3D::_queue_update() { @@ -204,6 +206,7 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -313,6 +316,9 @@ void SpriteBase3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect); ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh); + ClassDB::bind_method(D_METHOD("_queue_update"), &SpriteBase3D::_queue_update); + ClassDB::bind_method(D_METHOD("_im_update"), &SpriteBase3D::_im_update); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "centered"), "set_centered", "is_centered"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_h"), "set_flip_h", "is_flipped_h"); @@ -343,21 +349,89 @@ SpriteBase3D::SpriteBase3D() { flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED; } - immediate = RenderingServer::get_singleton()->immediate_create(); - set_base(immediate); + material = RenderingServer::get_singleton()->material_create(); + // Set defaults for material, names need to match up those in StandardMaterial3D + RS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1)); + RS::get_singleton()->material_set_param(material, "specular", 0.5); + RS::get_singleton()->material_set_param(material, "metallic", 0.0); + RS::get_singleton()->material_set_param(material, "roughness", 1.0); + RS::get_singleton()->material_set_param(material, "uv1_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0)); + RS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1)); + RS::get_singleton()->material_set_param(material, "alpha_scissor_threshold", 0.98); + + mesh = RenderingServer::get_singleton()->mesh_create(); + + PackedVector3Array mesh_vertices; + PackedVector3Array mesh_normals; + PackedFloat32Array mesh_tangents; + PackedColorArray mesh_colors; + PackedVector2Array mesh_uvs; + PackedInt32Array indices; + + mesh_vertices.resize(4); + mesh_normals.resize(4); + mesh_tangents.resize(16); + mesh_colors.resize(4); + mesh_uvs.resize(4); + + // create basic mesh and store format information + for (int i = 0; i < 4; i++) { + mesh_normals.write[i] = Vector3(0.0, 0.0, 0.0); + mesh_tangents.write[i * 4 + 0] = 0.0; + mesh_tangents.write[i * 4 + 1] = 0.0; + mesh_tangents.write[i * 4 + 2] = 0.0; + mesh_tangents.write[i * 4 + 3] = 0.0; + mesh_colors.write[i] = Color(1.0, 1.0, 1.0, 1.0); + mesh_uvs.write[i] = Vector2(0.0, 0.0); + mesh_vertices.write[i] = Vector3(0.0, 0.0, 0.0); + } + + indices.resize(6); + indices.write[0] = 0; + indices.write[1] = 1; + indices.write[2] = 2; + indices.write[3] = 0; + indices.write[4] = 2; + indices.write[5] = 3; + + Array mesh_array; + mesh_array.resize(RS::ARRAY_MAX); + mesh_array[RS::ARRAY_VERTEX] = mesh_vertices; + mesh_array[RS::ARRAY_NORMAL] = mesh_normals; + mesh_array[RS::ARRAY_TANGENT] = mesh_tangents; + mesh_array[RS::ARRAY_COLOR] = mesh_colors; + mesh_array[RS::ARRAY_TEX_UV] = mesh_uvs; + mesh_array[RS::ARRAY_INDEX] = indices; + + RS::SurfaceData sd; + RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, mesh_array); + + mesh_surface_format = sd.format; + vertex_buffer = sd.vertex_data; + attribute_buffer = sd.attribute_data; + + sd.material = material; + + RS::get_singleton()->mesh_surface_make_offsets_from_format(sd.format, sd.vertex_count, sd.index_count, mesh_surface_offsets, vertex_stride, attrib_stride, skin_stride); + RS::get_singleton()->mesh_add_surface(mesh, sd); + set_base(mesh); } SpriteBase3D::~SpriteBase3D() { - RenderingServer::get_singleton()->free(immediate); + RenderingServer::get_singleton()->free(mesh); + RenderingServer::get_singleton()->free(material); } /////////////////////////////////////////// void Sprite3D::_draw() { - RID immediate = get_immediate(); - - RS::get_singleton()->immediate_clear(immediate); + if (get_base() != get_mesh()) { + set_base(get_mesh()); + } if (!texture.is_valid()) { + set_base(RID()); return; } Vector2 tsize = texture->get_size(); @@ -366,7 +440,7 @@ void Sprite3D::_draw() { } Rect2 base_rect; - if (region_enabled) { + if (region) { base_rect = region_rect; } else { base_rect = Rect2(0, 0, texture->get_width(), texture->get_height()); @@ -399,6 +473,7 @@ void Sprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -426,6 +501,7 @@ void Sprite3D::_draw() { SWAP(uvs[0], uvs[1]); SWAP(uvs[2], uvs[3]); } + if (is_flipped_v()) { SWAP(uvs[0], uvs[3]); SWAP(uvs[1], uvs[2]); @@ -442,11 +518,6 @@ void Sprite3D::_draw() { tangent = Plane(1, 0, 0, 1); } - RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - RS::get_singleton()->immediate_set_material(immediate, mat); - - RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); - int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -466,31 +537,80 @@ void Sprite3D::_draw() { AABB aabb; - for (int i = 0; i < 6; i++) { - static const int index[6] = { 0, 1, 2, 0, 2, 3 }; + // Everything except position and UV is compressed + uint8_t *vertex_write_buffer = vertex_buffer.ptrw(); + uint8_t *attribute_write_buffer = attribute_buffer.ptrw(); + + uint32_t v_normal; + { + Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); + + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + + v_normal = value; + } + uint32_t v_tangent; + { + Plane t = tangent; + uint32_t value = 0; + value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023); + value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; + value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; + if (t.d > 0) { + value |= 3 << 30; + } + v_tangent = value; + } - RS::get_singleton()->immediate_normal(immediate, normal); - RS::get_singleton()->immediate_tangent(immediate, tangent); - RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[index[i]]); + uint16_t v_color[4] = { + Math::make_half_float(color.r), + Math::make_half_float(color.g), + Math::make_half_float(color.b), + Math::make_half_float(color.a), + }; + for (int i = 0; i < 4; i++) { Vector3 vtx; - vtx[x_axis] = vertices[index[i]][0]; - vtx[y_axis] = vertices[index[i]][1]; - RS::get_singleton()->immediate_vertex(immediate, vtx); + vtx[x_axis] = vertices[i][0]; + vtx[y_axis] = vertices[i][1]; if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); } + + float v_uv[2] = { uvs[i].x, uvs[i].y }; + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8); + + float v_vertex[3] = { vtx.x, vtx.y, vtx.z }; + + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4); + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 8); } + + RID mesh = get_mesh(); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer); + + RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb); set_aabb(aabb); - RS::get_singleton()->immediate_end(immediate); -} -void Sprite3D::_texture_changed() { - _queue_update(); + RID shader_rid; + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + if (last_shader != shader_rid) { + RS::get_singleton()->material_set_shader(get_material(), shader_rid); + last_shader = shader_rid; + } + if (last_texture != texture->get_rid()) { + RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid()); + last_texture = texture->get_rid(); + } } void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) { @@ -498,38 +618,36 @@ void Sprite3D::set_texture(const Ref<Texture2D> &p_texture) { return; } if (texture.is_valid()) { - texture->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed)); + texture->disconnect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update")); } texture = p_texture; if (texture.is_valid()) { - texture->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &Sprite3D::_texture_changed)); + texture->connect(CoreStringNames::get_singleton()->changed, Callable(this, "_queue_update")); } _queue_update(); - emit_signal(SceneStringNames::get_singleton()->texture_changed); } Ref<Texture2D> Sprite3D::get_texture() const { return texture; } -void Sprite3D::set_region_enabled(bool p_region_enabled) { - if (p_region_enabled == region_enabled) { +void Sprite3D::set_region_enabled(bool p_region) { + if (p_region == region) { return; } - region_enabled = p_region_enabled; + region = p_region; _queue_update(); - notify_property_list_changed(); } bool Sprite3D::is_region_enabled() const { - return region_enabled; + return region; } void Sprite3D::set_region_rect(const Rect2 &p_region_rect) { bool changed = region_rect != p_region_rect; region_rect = p_region_rect; - if (region_enabled && changed) { + if (region && changed) { _queue_update(); } } @@ -596,7 +714,7 @@ Rect2 Sprite3D::get_item_rect() const { Size2i s; - if (region_enabled) { + if (region) { s = region_rect.size; } else { s = texture->get_size(); @@ -625,10 +743,6 @@ void Sprite3D::_validate_property(PropertyInfo &property) const { if (property.name == "frame_coords") { property.usage |= PROPERTY_USAGE_KEYING_INCREMENTS; } - - if (!region_enabled && property.name == "region_rect") { - property.usage = PROPERTY_USAGE_NOEDITOR; - } } void Sprite3D::_bind_methods() { @@ -653,32 +767,28 @@ void Sprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hframes", "hframes"), &Sprite3D::set_hframes); ClassDB::bind_method(D_METHOD("get_hframes"), &Sprite3D::get_hframes); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture"); ADD_GROUP("Animation", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_hframes", "get_hframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), "set_vframes", "get_vframes"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "frame_coords", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_frame_coords", "get_frame_coords"); ADD_GROUP("Region", "region_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "region_enabled"), "set_region_enabled", "is_region_enabled"); ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region_rect"), "set_region_rect", "get_region_rect"); ADD_SIGNAL(MethodInfo("frame_changed")); - ADD_SIGNAL(MethodInfo("texture_changed")); } Sprite3D::Sprite3D() { - region_enabled = false; - frame = 0; - vframes = 1; - hframes = 1; } //////////////////////////////////////// void AnimatedSprite3D::_draw() { - RID immediate = get_immediate(); - RS::get_singleton()->immediate_clear(immediate); + if (get_base() != get_mesh()) { + set_base(get_mesh()); + } if (frames.is_null()) { return; @@ -694,7 +804,8 @@ void AnimatedSprite3D::_draw() { Ref<Texture2D> texture = frames->get_frame(animation, frame); if (!texture.is_valid()) { - return; //no texture no life + set_base(RID()); + return; //no texuture no life } Vector2 tsize = texture->get_size(); if (tsize.x == 0 || tsize.y == 0) { @@ -729,6 +840,7 @@ void AnimatedSprite3D::_draw() { float pixel_size = get_pixel_size(); Vector2 vertices[4] = { + (final_rect.position + Vector2(0, final_rect.size.y)) * pixel_size, (final_rect.position + final_rect.size) * pixel_size, (final_rect.position + Vector2(final_rect.size.x, 0)) * pixel_size, @@ -772,12 +884,6 @@ void AnimatedSprite3D::_draw() { tangent = Plane(1, 0, 0, -1); } - RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - - RS::get_singleton()->immediate_set_material(immediate, mat); - - RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); - int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -797,30 +903,79 @@ void AnimatedSprite3D::_draw() { AABB aabb; - for (int i = 0; i < 6; i++) { - static const int indices[6] = { - 0, 1, 2, - 0, 2, 3 - }; + // Everything except position and UV is compressed + uint8_t *vertex_write_buffer = vertex_buffer.ptrw(); + uint8_t *attribute_write_buffer = attribute_buffer.ptrw(); + + uint32_t v_normal; + { + Vector3 n = normal * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5); + + uint32_t value = 0; + value |= CLAMP(int(n.x * 1023.0), 0, 1023); + value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10; + value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20; + + v_normal = value; + } + uint32_t v_tangent; + { + Plane t = tangent; + uint32_t value = 0; + value |= CLAMP(int((t.normal.x * 0.5 + 0.5) * 1023.0), 0, 1023); + value |= CLAMP(int((t.normal.y * 0.5 + 0.5) * 1023.0), 0, 1023) << 10; + value |= CLAMP(int((t.normal.z * 0.5 + 0.5) * 1023.0), 0, 1023) << 20; + if (t.d > 0) { + value |= 3 << 30; + } + v_tangent = value; + } - RS::get_singleton()->immediate_normal(immediate, normal); - RS::get_singleton()->immediate_tangent(immediate, tangent); - RS::get_singleton()->immediate_color(immediate, color); - RS::get_singleton()->immediate_uv(immediate, uvs[indices[i]]); + uint16_t v_color[4] = { + Math::make_half_float(color.r), + Math::make_half_float(color.g), + Math::make_half_float(color.b), + Math::make_half_float(color.a), + }; + for (int i = 0; i < 4; i++) { Vector3 vtx; - vtx[x_axis] = vertices[indices[i]][0]; - vtx[y_axis] = vertices[indices[i]][1]; - RS::get_singleton()->immediate_vertex(immediate, vtx); + vtx[x_axis] = vertices[i][0]; + vtx[y_axis] = vertices[i][1]; if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); } else { aabb.expand_to(vtx); } + + float v_uv[2] = { uvs[i].x, uvs[i].y }; + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_TEX_UV]], v_uv, 8); + + float v_vertex[3] = { vtx.x, vtx.y, vtx.z }; + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_VERTEX]], &v_vertex, sizeof(float) * 3); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_NORMAL]], &v_normal, 4); + memcpy(&vertex_write_buffer[i * vertex_stride + mesh_surface_offsets[RS::ARRAY_TANGENT]], &v_tangent, 4); + memcpy(&attribute_write_buffer[i * attrib_stride + mesh_surface_offsets[RS::ARRAY_COLOR]], v_color, 8); } + + RID mesh = get_mesh(); + RS::get_singleton()->mesh_surface_update_vertex_region(mesh, 0, 0, vertex_buffer); + RS::get_singleton()->mesh_surface_update_attribute_region(mesh, 0, 0, attribute_buffer); + + RS::get_singleton()->mesh_set_custom_aabb(mesh, aabb); set_aabb(aabb); - RS::get_singleton()->immediate_end(immediate); + + RID shader_rid; + StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, &shader_rid); + if (last_shader != shader_rid) { + RS::get_singleton()->material_set_shader(get_material(), shader_rid); + last_shader = shader_rid; + } + if (last_texture != texture->get_rid()) { + RS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid()); + last_texture = texture->get_rid(); + } } void AnimatedSprite3D::_validate_property(PropertyInfo &property) const { @@ -914,11 +1069,11 @@ void AnimatedSprite3D::_notification(int p_what) { void AnimatedSprite3D::set_sprite_frames(const Ref<SpriteFrames> &p_frames) { if (frames.is_valid()) { - frames->disconnect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed)); + frames->disconnect("changed", Callable(this, "_res_changed")); } frames = p_frames; if (frames.is_valid()) { - frames->connect("changed", callable_mp(this, &AnimatedSprite3D::_res_changed)); + frames->connect("changed", Callable(this, "_res_changed")); } if (!frames.is_valid()) { @@ -944,9 +1099,8 @@ void AnimatedSprite3D::set_frame(int p_frame) { if (frames->has_animation(animation)) { int limit = frames->get_frame_count(animation); - if (p_frame >= limit) { + if (p_frame >= limit) p_frame = limit - 1; - } } if (p_frame < 0) { @@ -960,7 +1114,6 @@ void AnimatedSprite3D::set_frame(int p_frame) { frame = p_frame; _reset_timeout(); _queue_update(); - emit_signal(SceneStringNames::get_singleton()->frame_changed); } @@ -1061,8 +1214,7 @@ StringName AnimatedSprite3D::get_animation() const { } TypedArray<String> AnimatedSprite3D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); - + TypedArray<String> warnings = SpriteBase3D::get_configuration_warnings(); if (frames.is_null()) { warnings.push_back(TTR("A SpriteFrames resource must be created or set in the \"Frames\" property in order for AnimatedSprite3D to display frames.")); } @@ -1087,11 +1239,13 @@ void AnimatedSprite3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frame", "frame"), &AnimatedSprite3D::set_frame); ClassDB::bind_method(D_METHOD("get_frame"), &AnimatedSprite3D::get_frame); + ClassDB::bind_method(D_METHOD("_res_changed"), &AnimatedSprite3D::_res_changed); + ADD_SIGNAL(MethodInfo("frame_changed")); ADD_SIGNAL(MethodInfo("animation_finished")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "frames", PROPERTY_HINT_RESOURCE_TYPE, "SpriteFrames"), "set_sprite_frames", "get_sprite_frames"); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "animation"), "set_animation", "get_animation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "animation"), "set_animation", "get_animation"); ADD_PROPERTY(PropertyInfo(Variant::INT, "frame"), "set_frame", "get_frame"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing"), "_set_playing", "_is_playing"); } diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index e3dd117804..404ef57e6a 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -31,8 +31,8 @@ #ifndef SPRITE_3D_H #define SPRITE_3D_H +#include "scene/2d/animated_sprite_2d.h" #include "scene/3d/visual_instance_3d.h" -#include "scene/resources/sprite_frames.h" class SpriteBase3D : public GeometryInstance3D { GDCLASS(SpriteBase3D, GeometryInstance3D); @@ -75,9 +75,10 @@ private: float pixel_size = 0.01; AABB aabb; - RID immediate; + RID mesh; + RID material; - bool flags[FLAG_MAX]; + bool flags[FLAG_MAX] = {}; AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED; StandardMaterial3D::BillboardMode billboard_mode = StandardMaterial3D::BILLBOARD_DISABLED; bool pending_update = false; @@ -91,7 +92,17 @@ protected: static void _bind_methods(); virtual void _draw() = 0; _FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; } - _FORCE_INLINE_ RID &get_immediate() { return immediate; } + _FORCE_INLINE_ RID &get_mesh() { return mesh; } + _FORCE_INLINE_ RID &get_material() { return material; } + + uint32_t mesh_surface_offsets[RS::ARRAY_MAX]; + PackedByteArray vertex_buffer; + PackedByteArray attribute_buffer; + uint32_t vertex_stride; + uint32_t attrib_stride; + uint32_t skin_stride; + uint32_t mesh_surface_format; + void _queue_update(); public: @@ -107,7 +118,7 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region_enabled(bool p_region_enabled); + void set_region_enabled(bool p_region); bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); @@ -147,15 +158,16 @@ class Sprite3D : public SpriteBase3D { GDCLASS(Sprite3D, SpriteBase3D); Ref<Texture2D> texture; - bool region_enabled; + bool region = false; Rect2 region_rect; - int frame; + int frame = 0; - int vframes; - int hframes; + int vframes = 1; + int hframes = 1; - void _texture_changed(); + RID last_shader; + RID last_texture; protected: virtual void _draw() override; @@ -167,7 +179,7 @@ public: void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; - void set_region_enabled(bool p_region_enabled); + void set_region_enabled(bool p_region); bool is_region_enabled() const; void set_region_rect(const Rect2 &p_region_rect); @@ -199,14 +211,9 @@ class AnimatedSprite3D : public SpriteBase3D { StringName animation = "default"; int frame = 0; - bool centered = true; - - float timeout = 0.0; - - bool hflip = true; - bool vflip = true; + bool centered = false; - Color modulate; + float timeout = 0; void _res_changed(); @@ -214,6 +221,9 @@ class AnimatedSprite3D : public SpriteBase3D { void _set_playing(bool p_playing); bool _is_playing() const; + RID last_shader; + RID last_texture; + protected: virtual void _draw() override; static void _bind_methods(); @@ -236,10 +246,11 @@ public: virtual Rect2 get_item_rect() const override; - TypedArray<String> get_configuration_warnings() const override; + virtual TypedArray<String> get_configuration_warnings() const override; AnimatedSprite3D(); }; VARIANT_ENUM_CAST(SpriteBase3D::DrawFlags); VARIANT_ENUM_CAST(SpriteBase3D::AlphaCutMode); + #endif // SPRITE_3D_H |