Use mesh instead of immediate for drawing Sprite3D
This commit is contained in:
parent
28c0088d86
commit
6c0ff26f35
4 changed files with 155 additions and 35 deletions
|
@ -4431,7 +4431,7 @@
|
||||||
Flag used to mark that the array uses 16-bit bones instead of 8-bit.
|
Flag used to mark that the array uses 16-bit bones instead of 8-bit.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="ARRAY_COMPRESS_DEFAULT" value="97280" enum="ArrayFormat">
|
<constant name="ARRAY_COMPRESS_DEFAULT" value="97280" enum="ArrayFormat">
|
||||||
Used to set flags [constant ARRAY_COMPRESS_VERTEX], [constant ARRAY_COMPRESS_NORMAL], [constant ARRAY_COMPRESS_TANGENT], [constant ARRAY_COMPRESS_COLOR], [constant ARRAY_COMPRESS_TEX_UV], [constant ARRAY_COMPRESS_TEX_UV2] and [constant ARRAY_COMPRESS_WEIGHTS] quickly.
|
Used to set flags [constant ARRAY_COMPRESS_NORMAL], [constant ARRAY_COMPRESS_TANGENT], [constant ARRAY_COMPRESS_COLOR], [constant ARRAY_COMPRESS_TEX_UV], [constant ARRAY_COMPRESS_TEX_UV2] and [constant ARRAY_COMPRESS_WEIGHTS] quickly.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="PRIMITIVE_POINTS" value="0" enum="PrimitiveType">
|
<constant name="PRIMITIVE_POINTS" value="0" enum="PrimitiveType">
|
||||||
Primitive to draw consists of points.
|
Primitive to draw consists of points.
|
||||||
|
|
|
@ -383,22 +383,73 @@ SpriteBase3D::SpriteBase3D() {
|
||||||
modulate = Color(1, 1, 1, 1);
|
modulate = Color(1, 1, 1, 1);
|
||||||
pending_update = false;
|
pending_update = false;
|
||||||
opacity = 1.0;
|
opacity = 1.0;
|
||||||
immediate = VisualServer::get_singleton()->immediate_create();
|
|
||||||
set_base(immediate);
|
material = VisualServer::get_singleton()->material_create();
|
||||||
|
// Set defaults for material, names need to match up those in SpatialMaterial
|
||||||
|
VS::get_singleton()->material_set_param(material, "albedo", Color(1, 1, 1, 1));
|
||||||
|
VS::get_singleton()->material_set_param(material, "specular", 0.5);
|
||||||
|
VS::get_singleton()->material_set_param(material, "metallic", 0.0);
|
||||||
|
VS::get_singleton()->material_set_param(material, "roughness", 1.0);
|
||||||
|
VS::get_singleton()->material_set_param(material, "uv1_offset", Vector3(0, 0, 0));
|
||||||
|
VS::get_singleton()->material_set_param(material, "uv1_scale", Vector3(1, 1, 1));
|
||||||
|
VS::get_singleton()->material_set_param(material, "uv2_offset", Vector3(0, 0, 0));
|
||||||
|
VS::get_singleton()->material_set_param(material, "uv2_scale", Vector3(1, 1, 1));
|
||||||
|
|
||||||
|
mesh = VisualServer::get_singleton()->mesh_create();
|
||||||
|
|
||||||
|
PoolVector2Array mesh_vertices;
|
||||||
|
PoolVector3Array mesh_normals;
|
||||||
|
PoolRealArray mesh_tangents;
|
||||||
|
PoolColorArray mesh_colors;
|
||||||
|
PoolVector2Array mesh_uvs;
|
||||||
|
|
||||||
|
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] = Vector2(0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array mesh_array;
|
||||||
|
mesh_array.resize(VS::ARRAY_MAX);
|
||||||
|
mesh_array[VS::ARRAY_VERTEX] = mesh_vertices;
|
||||||
|
mesh_array[VS::ARRAY_NORMAL] = mesh_normals;
|
||||||
|
mesh_array[VS::ARRAY_TANGENT] = mesh_tangents;
|
||||||
|
mesh_array[VS::ARRAY_COLOR] = mesh_colors;
|
||||||
|
mesh_array[VS::ARRAY_TEX_UV] = mesh_uvs;
|
||||||
|
|
||||||
|
VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLE_FAN, mesh_array);
|
||||||
|
const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, 0);
|
||||||
|
const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, 0);
|
||||||
|
const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, 0);
|
||||||
|
|
||||||
|
mesh_buffer = VS::get_singleton()->mesh_surface_get_array(mesh, 0);
|
||||||
|
mesh_stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, mesh_surface_offsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteBase3D::~SpriteBase3D() {
|
SpriteBase3D::~SpriteBase3D() {
|
||||||
|
|
||||||
VisualServer::get_singleton()->free(immediate);
|
VisualServer::get_singleton()->free(mesh);
|
||||||
|
VisualServer::get_singleton()->free(material);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
void Sprite3D::_draw() {
|
void Sprite3D::_draw() {
|
||||||
|
|
||||||
RID immediate = get_immediate();
|
set_base(RID());
|
||||||
|
|
||||||
VS::get_singleton()->immediate_clear(immediate);
|
|
||||||
if (!texture.is_valid())
|
if (!texture.is_valid())
|
||||||
return;
|
return;
|
||||||
Vector2 tsize = texture->get_size();
|
Vector2 tsize = texture->get_size();
|
||||||
|
@ -480,11 +531,6 @@ void Sprite3D::_draw() {
|
||||||
tangent = Plane(1, 0, 0, 1);
|
tangent = Plane(1, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RID mat = SpatialMaterial::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() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
|
|
||||||
VS::get_singleton()->immediate_set_material(immediate, mat);
|
|
||||||
|
|
||||||
VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
|
|
||||||
|
|
||||||
int x_axis = ((axis + 1) % 3);
|
int x_axis = ((axis + 1) % 3);
|
||||||
int y_axis = ((axis + 2) % 3);
|
int y_axis = ((axis + 2) % 3);
|
||||||
|
|
||||||
|
@ -504,25 +550,61 @@ void Sprite3D::_draw() {
|
||||||
|
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
// Buffer is using default compression, so everything except position is compressed
|
||||||
VS::get_singleton()->immediate_normal(immediate, normal);
|
PoolVector<uint8_t>::Write write_buffer = mesh_buffer.write();
|
||||||
VS::get_singleton()->immediate_tangent(immediate, tangent);
|
|
||||||
VS::get_singleton()->immediate_color(immediate, color);
|
|
||||||
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
|
|
||||||
|
|
||||||
|
int8_t v_normal[4] = {
|
||||||
|
(int8_t)CLAMP(normal.x * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(normal.y * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(normal.z * 127, -128, 127),
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
int8_t v_tangent[4] = {
|
||||||
|
(int8_t)CLAMP(tangent.normal.x * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.normal.y * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.normal.z * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.d * 127, -128, 127)
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t v_color[4] = {
|
||||||
|
(uint8_t)CLAMP(int(color.r * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.g * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.b * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.a * 255.0), 0, 255)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
Vector3 vtx;
|
Vector3 vtx;
|
||||||
vtx[x_axis] = vertices[i][0];
|
vtx[x_axis] = vertices[i][0];
|
||||||
vtx[y_axis] = vertices[i][1];
|
vtx[y_axis] = vertices[i][1];
|
||||||
VS::get_singleton()->immediate_vertex(immediate, vtx);
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
aabb.position = vtx;
|
aabb.position = vtx;
|
||||||
aabb.size = Vector3();
|
aabb.size = Vector3();
|
||||||
} else {
|
} else {
|
||||||
aabb.expand_to(vtx);
|
aabb.expand_to(vtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t v_uv[2] = { Math::make_half_float(uvs[i].x), Math::make_half_float(uvs[i].y) };
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_VERTEX]], &vertices[i], sizeof(float) * 2);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_COLOR]], v_color, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 2 * 2);
|
||||||
}
|
}
|
||||||
set_aabb(aabb);
|
set_aabb(aabb);
|
||||||
VS::get_singleton()->immediate_end(immediate);
|
|
||||||
|
write_buffer.release();
|
||||||
|
|
||||||
|
RID mesh = get_mesh();
|
||||||
|
VS::get_singleton()->mesh_surface_update_region(mesh, 0, 0, mesh_buffer);
|
||||||
|
|
||||||
|
set_base(mesh);
|
||||||
|
|
||||||
|
RID mat = SpatialMaterial::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() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
|
||||||
|
VS::get_singleton()->material_set_shader(get_material(), VS::get_singleton()->material_get_shader(mat));
|
||||||
|
VS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
|
||||||
|
VS::get_singleton()->instance_set_surface_material(get_instance(), 0, get_material());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite3D::set_texture(const Ref<Texture> &p_texture) {
|
void Sprite3D::set_texture(const Ref<Texture> &p_texture) {
|
||||||
|
@ -716,8 +798,7 @@ Sprite3D::Sprite3D() {
|
||||||
|
|
||||||
void AnimatedSprite3D::_draw() {
|
void AnimatedSprite3D::_draw() {
|
||||||
|
|
||||||
RID immediate = get_immediate();
|
set_base(RID());
|
||||||
VS::get_singleton()->immediate_clear(immediate);
|
|
||||||
|
|
||||||
if (frames.is_null()) {
|
if (frames.is_null()) {
|
||||||
return;
|
return;
|
||||||
|
@ -808,12 +889,6 @@ void AnimatedSprite3D::_draw() {
|
||||||
tangent = Plane(1, 0, 0, -1);
|
tangent = Plane(1, 0, 0, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
RID mat = SpatialMaterial::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() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
|
|
||||||
|
|
||||||
VS::get_singleton()->immediate_set_material(immediate, mat);
|
|
||||||
|
|
||||||
VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
|
|
||||||
|
|
||||||
int x_axis = ((axis + 1) % 3);
|
int x_axis = ((axis + 1) % 3);
|
||||||
int y_axis = ((axis + 2) % 3);
|
int y_axis = ((axis + 2) % 3);
|
||||||
|
|
||||||
|
@ -833,25 +908,61 @@ void AnimatedSprite3D::_draw() {
|
||||||
|
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
// Buffer is using default compression, so everything except position is compressed
|
||||||
VS::get_singleton()->immediate_normal(immediate, normal);
|
PoolVector<uint8_t>::Write write_buffer = mesh_buffer.write();
|
||||||
VS::get_singleton()->immediate_tangent(immediate, tangent);
|
|
||||||
VS::get_singleton()->immediate_color(immediate, color);
|
|
||||||
VS::get_singleton()->immediate_uv(immediate, uvs[i]);
|
|
||||||
|
|
||||||
|
int8_t v_normal[4] = {
|
||||||
|
(int8_t)CLAMP(normal.x * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(normal.y * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(normal.z * 127, -128, 127),
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
int8_t v_tangent[4] = {
|
||||||
|
(int8_t)CLAMP(tangent.normal.x * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.normal.y * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.normal.z * 127, -128, 127),
|
||||||
|
(int8_t)CLAMP(tangent.d * 127, -128, 127)
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t v_color[4] = {
|
||||||
|
(uint8_t)CLAMP(int(color.r * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.g * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.b * 255.0), 0, 255),
|
||||||
|
(uint8_t)CLAMP(int(color.a * 255.0), 0, 255)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
Vector3 vtx;
|
Vector3 vtx;
|
||||||
vtx[x_axis] = vertices[i][0];
|
vtx[x_axis] = vertices[i][0];
|
||||||
vtx[y_axis] = vertices[i][1];
|
vtx[y_axis] = vertices[i][1];
|
||||||
VS::get_singleton()->immediate_vertex(immediate, vtx);
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
aabb.position = vtx;
|
aabb.position = vtx;
|
||||||
aabb.size = Vector3();
|
aabb.size = Vector3();
|
||||||
} else {
|
} else {
|
||||||
aabb.expand_to(vtx);
|
aabb.expand_to(vtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t v_uv[2] = { Math::make_half_float(uvs[i].x), Math::make_half_float(uvs[i].y) };
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_VERTEX]], &vertices[i], sizeof(float) * 2);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_NORMAL]], v_normal, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TANGENT]], v_tangent, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_COLOR]], v_color, 4);
|
||||||
|
copymem(&write_buffer[i * mesh_stride + mesh_surface_offsets[VS::ARRAY_TEX_UV]], v_uv, 2 * 2);
|
||||||
}
|
}
|
||||||
set_aabb(aabb);
|
set_aabb(aabb);
|
||||||
VS::get_singleton()->immediate_end(immediate);
|
|
||||||
|
write_buffer.release();
|
||||||
|
|
||||||
|
RID mesh = get_mesh();
|
||||||
|
VS::get_singleton()->mesh_surface_update_region(mesh, 0, 0, mesh_buffer);
|
||||||
|
|
||||||
|
set_base(mesh);
|
||||||
|
|
||||||
|
RID mat = SpatialMaterial::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() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
|
||||||
|
VS::get_singleton()->material_set_shader(get_material(), VS::get_singleton()->material_get_shader(mat));
|
||||||
|
VS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
|
||||||
|
VS::get_singleton()->instance_set_surface_material(get_instance(), 0, get_material());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
|
void AnimatedSprite3D::_validate_property(PropertyInfo &property) const {
|
||||||
|
|
|
@ -76,7 +76,8 @@ private:
|
||||||
float pixel_size;
|
float pixel_size;
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
|
|
||||||
RID immediate;
|
RID mesh;
|
||||||
|
RID material;
|
||||||
|
|
||||||
bool flags[FLAG_MAX];
|
bool flags[FLAG_MAX];
|
||||||
AlphaCutMode alpha_cut;
|
AlphaCutMode alpha_cut;
|
||||||
|
@ -92,7 +93,13 @@ protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
virtual void _draw() = 0;
|
virtual void _draw() = 0;
|
||||||
_FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
|
_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[VS::ARRAY_MAX];
|
||||||
|
PoolByteArray mesh_buffer;
|
||||||
|
uint32_t mesh_stride;
|
||||||
|
|
||||||
void _queue_update();
|
void _queue_update();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1838,6 +1838,8 @@ RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent,
|
||||||
}
|
}
|
||||||
|
|
||||||
materials_for_2d[version] = material;
|
materials_for_2d[version] = material;
|
||||||
|
// flush before using so we can access the shader right away
|
||||||
|
flush_changes();
|
||||||
|
|
||||||
return materials_for_2d[version]->get_rid();
|
return materials_for_2d[version]->get_rid();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue