summaryrefslogtreecommitdiff
path: root/scene/3d
diff options
context:
space:
mode:
authorRémi Verschelde <remi@verschelde.fr>2021-06-30 20:18:59 +0200
committerGitHub <noreply@github.com>2021-06-30 20:18:59 +0200
commit270f9d4c88c43895ae6d6a4ff8247f77f811beda (patch)
tree767dc2499fa3fc5c023dbfc28b1f4812f0148016 /scene/3d
parenta02620f3a5f3b94c68dfbe18874b34ac1c32374a (diff)
parent85cf99f28e93556f1298a5136254253f9da82b9a (diff)
Merge pull request #50014 from reduz/remove-immediate
Deprecate ImmediateGeometry
Diffstat (limited to 'scene/3d')
-rw-r--r--scene/3d/immediate_geometry_3d.cpp157
-rw-r--r--scene/3d/immediate_geometry_3d.h72
-rw-r--r--scene/3d/soft_body_3d.cpp2
-rw-r--r--scene/3d/sprite_3d.cpp306
-rw-r--r--scene/3d/sprite_3d.h49
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