Transform mesh's AABB to skeleton's space when calculate mesh's bounds.
(cherry picked from commit 27f71c4e78
)
This commit is contained in:
parent
e2c96dc711
commit
211dd2fb53
|
@ -918,6 +918,14 @@
|
||||||
[b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
|
[b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [code]null[/code].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="debug_canvas_item_get_rect">
|
||||||
|
<return type="Rect2" />
|
||||||
|
<param index="0" name="item" type="RID" />
|
||||||
|
<description>
|
||||||
|
Returns the bounding rectangle for a canvas item in local space, as calculated by the renderer. This bound is used internally for culling.
|
||||||
|
[b]Warning:[/b] This function is intended for debugging in the editor, and will pass through and return a zero [Rect2] in exported projects.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="decal_create">
|
<method name="decal_create">
|
||||||
<return type="RID" />
|
<return type="RID" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -248,6 +248,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
||||||
|
|
||||||
s->aabb = p_surface.aabb;
|
s->aabb = p_surface.aabb;
|
||||||
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
|
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
|
||||||
|
s->mesh_to_skeleton_xform = p_surface.mesh_to_skeleton_xform;
|
||||||
|
|
||||||
if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
|
if (p_surface.skin_data.size() || mesh->blend_shape_count > 0) {
|
||||||
// Size must match the size of the vertex array.
|
// Size must match the size of the vertex array.
|
||||||
|
@ -471,6 +472,7 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
sd.bone_aabbs = s.bone_aabbs;
|
sd.bone_aabbs = s.bone_aabbs;
|
||||||
|
sd.mesh_to_skeleton_xform = s.mesh_to_skeleton_xform;
|
||||||
|
|
||||||
if (mesh->blend_shape_count) {
|
if (mesh->blend_shape_count) {
|
||||||
sd.blend_shape_data = Vector<uint8_t>();
|
sd.blend_shape_data = Vector<uint8_t>();
|
||||||
|
@ -522,15 +524,16 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
||||||
AABB laabb;
|
AABB laabb;
|
||||||
if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
|
const Mesh::Surface &surface = *mesh->surfaces[i];
|
||||||
int bs = mesh->surfaces[i]->bone_aabbs.size();
|
if ((surface.format & RS::ARRAY_FORMAT_BONES) && surface.bone_aabbs.size()) {
|
||||||
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
|
int bs = surface.bone_aabbs.size();
|
||||||
|
const AABB *skbones = surface.bone_aabbs.ptr();
|
||||||
|
|
||||||
int sbs = skeleton->size;
|
int sbs = skeleton->size;
|
||||||
ERR_CONTINUE(bs > sbs);
|
ERR_CONTINUE(bs > sbs);
|
||||||
const float *baseptr = skeleton->data.ptr();
|
const float *baseptr = skeleton->data.ptr();
|
||||||
|
|
||||||
bool first = true;
|
bool found_bone_aabb = false;
|
||||||
|
|
||||||
if (skeleton->use_2d) {
|
if (skeleton->use_2d) {
|
||||||
for (int j = 0; j < bs; j++) {
|
for (int j = 0; j < bs; j++) {
|
||||||
|
@ -550,11 +553,13 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
mtx.basis.rows[1][1] = dataptr[5];
|
mtx.basis.rows[1][1] = dataptr[5];
|
||||||
mtx.origin.y = dataptr[7];
|
mtx.origin.y = dataptr[7];
|
||||||
|
|
||||||
AABB baabb = mtx.xform(skbones[j]);
|
// Transform bounds to skeleton's space before applying animation data.
|
||||||
|
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
|
||||||
|
baabb = mtx.xform(baabb);
|
||||||
|
|
||||||
if (first) {
|
if (!found_bone_aabb) {
|
||||||
laabb = baabb;
|
laabb = baabb;
|
||||||
first = false;
|
found_bone_aabb = true;
|
||||||
} else {
|
} else {
|
||||||
laabb.merge_with(baabb);
|
laabb.merge_with(baabb);
|
||||||
}
|
}
|
||||||
|
@ -582,21 +587,29 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
mtx.basis.rows[2][2] = dataptr[10];
|
mtx.basis.rows[2][2] = dataptr[10];
|
||||||
mtx.origin.z = dataptr[11];
|
mtx.origin.z = dataptr[11];
|
||||||
|
|
||||||
AABB baabb = mtx.xform(skbones[j]);
|
// Transform bounds to skeleton's space before applying animation data.
|
||||||
if (first) {
|
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
|
||||||
|
baabb = mtx.xform(baabb);
|
||||||
|
|
||||||
|
if (!found_bone_aabb) {
|
||||||
laabb = baabb;
|
laabb = baabb;
|
||||||
first = false;
|
found_bone_aabb = true;
|
||||||
} else {
|
} else {
|
||||||
laabb.merge_with(baabb);
|
laabb.merge_with(baabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found_bone_aabb) {
|
||||||
|
// Transform skeleton bounds back to mesh's space if any animated AABB applied.
|
||||||
|
laabb = surface.mesh_to_skeleton_xform.affine_inverse().xform(laabb);
|
||||||
|
}
|
||||||
|
|
||||||
if (laabb.size == Vector3()) {
|
if (laabb.size == Vector3()) {
|
||||||
laabb = mesh->surfaces[i]->aabb;
|
laabb = surface.aabb;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
laabb = mesh->surfaces[i]->aabb;
|
laabb = surface.aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
|
|
@ -103,6 +103,10 @@ struct Mesh {
|
||||||
|
|
||||||
Vector<AABB> bone_aabbs;
|
Vector<AABB> bone_aabbs;
|
||||||
|
|
||||||
|
// Transform used in runtime bone AABBs compute.
|
||||||
|
// As bone AABBs are saved in Mesh space, but bones animation is in Skeleton space.
|
||||||
|
Transform3D mesh_to_skeleton_xform;
|
||||||
|
|
||||||
struct BlendShape {
|
struct BlendShape {
|
||||||
GLuint vertex_buffer = 0;
|
GLuint vertex_buffer = 0;
|
||||||
GLuint vertex_array = 0;
|
GLuint vertex_array = 0;
|
||||||
|
|
|
@ -101,7 +101,12 @@ void Polygon2D::_skeleton_bone_setup_changed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Polygon2D::_notification(int p_what) {
|
void Polygon2D::_notification(int p_what) {
|
||||||
|
if (p_what == NOTIFICATION_TRANSFORM_CHANGED && !Engine::get_singleton()->is_editor_hint()) {
|
||||||
|
return; // Mesh recreation for NOTIFICATION_TRANSFORM_CHANGED is only needed in editor.
|
||||||
|
}
|
||||||
|
|
||||||
switch (p_what) {
|
switch (p_what) {
|
||||||
|
case NOTIFICATION_TRANSFORM_CHANGED:
|
||||||
case NOTIFICATION_DRAW: {
|
case NOTIFICATION_DRAW: {
|
||||||
if (polygon.size() < 3) {
|
if (polygon.size() < 3) {
|
||||||
return;
|
return;
|
||||||
|
@ -364,7 +369,30 @@ void Polygon2D::_notification(int p_what) {
|
||||||
|
|
||||||
arr[RS::ARRAY_INDEX] = index_array;
|
arr[RS::ARRAY_INDEX] = index_array;
|
||||||
|
|
||||||
RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
|
RS::SurfaceData sd;
|
||||||
|
|
||||||
|
if (skeleton_node) {
|
||||||
|
// Compute transform between mesh and skeleton for runtime AABB compute.
|
||||||
|
const Transform2D mesh_transform = get_global_transform();
|
||||||
|
const Transform2D skeleton_transform = skeleton_node->get_global_transform();
|
||||||
|
const Transform2D mesh_to_sk2d = mesh_transform * skeleton_transform.affine_inverse();
|
||||||
|
|
||||||
|
// Convert 2d transform to 3d.
|
||||||
|
sd.mesh_to_skeleton_xform.basis.rows[0][0] = mesh_to_sk2d.columns[0][0];
|
||||||
|
sd.mesh_to_skeleton_xform.basis.rows[0][1] = mesh_to_sk2d.columns[0][1];
|
||||||
|
sd.mesh_to_skeleton_xform.origin.x = mesh_to_sk2d.get_origin().x;
|
||||||
|
|
||||||
|
sd.mesh_to_skeleton_xform.basis.rows[1][0] = mesh_to_sk2d.columns[1][0];
|
||||||
|
sd.mesh_to_skeleton_xform.basis.rows[1][1] = mesh_to_sk2d.columns[1][1];
|
||||||
|
sd.mesh_to_skeleton_xform.origin.y = mesh_to_sk2d.get_origin().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&sd, RS::PRIMITIVE_TRIANGLES, arr, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
|
||||||
|
if (err != OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RS::get_singleton()->mesh_add_surface(mesh, sd);
|
||||||
RS::get_singleton()->canvas_item_add_mesh(get_canvas_item(), mesh, Transform2D(), Color(1, 1, 1), texture.is_valid() ? texture->get_rid() : RID());
|
RS::get_singleton()->canvas_item_add_mesh(get_canvas_item(), mesh, Transform2D(), Color(1, 1, 1), texture.is_valid() ? texture->get_rid() : RID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2030,6 +2030,12 @@ void RendererCanvasCull::update_visibility_notifiers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect2 RendererCanvasCull::_debug_canvas_item_get_rect(RID p_item) {
|
||||||
|
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
|
||||||
|
ERR_FAIL_NULL_V(canvas_item, Rect2());
|
||||||
|
return canvas_item->get_rect();
|
||||||
|
}
|
||||||
|
|
||||||
bool RendererCanvasCull::free(RID p_rid) {
|
bool RendererCanvasCull::free(RID p_rid) {
|
||||||
if (canvas_owner.owns(p_rid)) {
|
if (canvas_owner.owns(p_rid)) {
|
||||||
Canvas *canvas = canvas_owner.get_or_null(p_rid);
|
Canvas *canvas = canvas_owner.get_or_null(p_rid);
|
||||||
|
|
|
@ -319,6 +319,8 @@ public:
|
||||||
|
|
||||||
void update_visibility_notifiers();
|
void update_visibility_notifiers();
|
||||||
|
|
||||||
|
Rect2 _debug_canvas_item_get_rect(RID p_item);
|
||||||
|
|
||||||
bool free(RID p_rid);
|
bool free(RID p_rid);
|
||||||
RendererCanvasCull();
|
RendererCanvasCull();
|
||||||
~RendererCanvasCull();
|
~RendererCanvasCull();
|
||||||
|
|
|
@ -389,6 +389,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
|
||||||
|
|
||||||
s->aabb = p_surface.aabb;
|
s->aabb = p_surface.aabb;
|
||||||
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
|
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
|
||||||
|
s->mesh_to_skeleton_xform = p_surface.mesh_to_skeleton_xform;
|
||||||
|
|
||||||
if (mesh->blend_shape_count > 0) {
|
if (mesh->blend_shape_count > 0) {
|
||||||
s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
|
s->blend_shape_buffer = RD::get_singleton()->storage_buffer_create(p_surface.blend_shape_data.size(), p_surface.blend_shape_data);
|
||||||
|
@ -569,6 +570,7 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
sd.bone_aabbs = s.bone_aabbs;
|
sd.bone_aabbs = s.bone_aabbs;
|
||||||
|
sd.mesh_to_skeleton_xform = s.mesh_to_skeleton_xform;
|
||||||
|
|
||||||
if (s.blend_shape_buffer.is_valid()) {
|
if (s.blend_shape_buffer.is_valid()) {
|
||||||
sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
|
sd.blend_shape_data = RD::get_singleton()->buffer_get_data(s.blend_shape_buffer);
|
||||||
|
@ -615,15 +617,16 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
for (uint32_t i = 0; i < mesh->surface_count; i++) {
|
||||||
AABB laabb;
|
AABB laabb;
|
||||||
if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) {
|
const Mesh::Surface &surface = *mesh->surfaces[i];
|
||||||
int bs = mesh->surfaces[i]->bone_aabbs.size();
|
if ((surface.format & RS::ARRAY_FORMAT_BONES) && surface.bone_aabbs.size()) {
|
||||||
const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr();
|
int bs = surface.bone_aabbs.size();
|
||||||
|
const AABB *skbones = surface.bone_aabbs.ptr();
|
||||||
|
|
||||||
int sbs = skeleton->size;
|
int sbs = skeleton->size;
|
||||||
ERR_CONTINUE(bs > sbs);
|
ERR_CONTINUE(bs > sbs);
|
||||||
const float *baseptr = skeleton->data.ptr();
|
const float *baseptr = skeleton->data.ptr();
|
||||||
|
|
||||||
bool first = true;
|
bool found_bone_aabb = false;
|
||||||
|
|
||||||
if (skeleton->use_2d) {
|
if (skeleton->use_2d) {
|
||||||
for (int j = 0; j < bs; j++) {
|
for (int j = 0; j < bs; j++) {
|
||||||
|
@ -643,11 +646,13 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
mtx.basis.rows[1][1] = dataptr[5];
|
mtx.basis.rows[1][1] = dataptr[5];
|
||||||
mtx.origin.y = dataptr[7];
|
mtx.origin.y = dataptr[7];
|
||||||
|
|
||||||
AABB baabb = mtx.xform(skbones[j]);
|
// Transform bounds to skeleton's space before applying animation data.
|
||||||
|
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
|
||||||
|
baabb = mtx.xform(baabb);
|
||||||
|
|
||||||
if (first) {
|
if (!found_bone_aabb) {
|
||||||
laabb = baabb;
|
laabb = baabb;
|
||||||
first = false;
|
found_bone_aabb = true;
|
||||||
} else {
|
} else {
|
||||||
laabb.merge_with(baabb);
|
laabb.merge_with(baabb);
|
||||||
}
|
}
|
||||||
|
@ -675,21 +680,29 @@ AABB MeshStorage::mesh_get_aabb(RID p_mesh, RID p_skeleton) {
|
||||||
mtx.basis.rows[2][2] = dataptr[10];
|
mtx.basis.rows[2][2] = dataptr[10];
|
||||||
mtx.origin.z = dataptr[11];
|
mtx.origin.z = dataptr[11];
|
||||||
|
|
||||||
AABB baabb = mtx.xform(skbones[j]);
|
// Transform bounds to skeleton's space before applying animation data.
|
||||||
if (first) {
|
AABB baabb = surface.mesh_to_skeleton_xform.xform(skbones[j]);
|
||||||
|
baabb = mtx.xform(baabb);
|
||||||
|
|
||||||
|
if (!found_bone_aabb) {
|
||||||
laabb = baabb;
|
laabb = baabb;
|
||||||
first = false;
|
found_bone_aabb = true;
|
||||||
} else {
|
} else {
|
||||||
laabb.merge_with(baabb);
|
laabb.merge_with(baabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found_bone_aabb) {
|
||||||
|
// Transform skeleton bounds back to mesh's space if any animated AABB applied.
|
||||||
|
laabb = surface.mesh_to_skeleton_xform.affine_inverse().xform(laabb);
|
||||||
|
}
|
||||||
|
|
||||||
if (laabb.size == Vector3()) {
|
if (laabb.size == Vector3()) {
|
||||||
laabb = mesh->surfaces[i]->aabb;
|
laabb = surface.aabb;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
laabb = mesh->surfaces[i]->aabb;
|
laabb = surface.aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
|
|
@ -116,6 +116,10 @@ private:
|
||||||
|
|
||||||
Vector<AABB> bone_aabbs;
|
Vector<AABB> bone_aabbs;
|
||||||
|
|
||||||
|
// Transform used in runtime bone AABBs compute.
|
||||||
|
// As bone AABBs are saved in Mesh space, but bones animation is in Skeleton space.
|
||||||
|
Transform3D mesh_to_skeleton_xform;
|
||||||
|
|
||||||
RID blend_shape_buffer;
|
RID blend_shape_buffer;
|
||||||
|
|
||||||
RID material;
|
RID material;
|
||||||
|
|
|
@ -925,6 +925,8 @@ public:
|
||||||
|
|
||||||
FUNC1(canvas_set_shadow_texture_size, int)
|
FUNC1(canvas_set_shadow_texture_size, int)
|
||||||
|
|
||||||
|
FUNC1R(Rect2, _debug_canvas_item_get_rect, RID)
|
||||||
|
|
||||||
/* GLOBAL SHADER UNIFORMS */
|
/* GLOBAL SHADER UNIFORMS */
|
||||||
|
|
||||||
#undef server_name
|
#undef server_name
|
||||||
|
|
|
@ -1410,6 +1410,14 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Rect2 RenderingServer::debug_canvas_item_get_rect(RID p_item) {
|
||||||
|
#ifdef TOOLS_ENABLED
|
||||||
|
return _debug_canvas_item_get_rect(p_item);
|
||||||
|
#else
|
||||||
|
return Rect2();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type) {
|
int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type) {
|
||||||
switch (p_type) {
|
switch (p_type) {
|
||||||
case RS::GLOBAL_VAR_TYPE_BOOL:
|
case RS::GLOBAL_VAR_TYPE_BOOL:
|
||||||
|
@ -2636,6 +2644,8 @@ void RenderingServer::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_notifier", "item", "enable", "area", "enter_callable", "exit_callable"), &RenderingServer::canvas_item_set_visibility_notifier);
|
ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_notifier", "item", "enable", "area", "enter_callable", "exit_callable"), &RenderingServer::canvas_item_set_visibility_notifier);
|
||||||
ClassDB::bind_method(D_METHOD("canvas_item_set_canvas_group_mode", "item", "mode", "clear_margin", "fit_empty", "fit_margin", "blur_mipmaps"), &RenderingServer::canvas_item_set_canvas_group_mode, DEFVAL(5.0), DEFVAL(false), DEFVAL(0.0), DEFVAL(false));
|
ClassDB::bind_method(D_METHOD("canvas_item_set_canvas_group_mode", "item", "mode", "clear_margin", "fit_empty", "fit_margin", "blur_mipmaps"), &RenderingServer::canvas_item_set_canvas_group_mode, DEFVAL(5.0), DEFVAL(false), DEFVAL(0.0), DEFVAL(false));
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("debug_canvas_item_get_rect", "item"), &RenderingServer::debug_canvas_item_get_rect);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
|
BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH);
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
|
BIND_ENUM_CONSTANT(NINE_PATCH_TILE);
|
||||||
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
|
BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT);
|
||||||
|
|
|
@ -312,6 +312,10 @@ public:
|
||||||
Vector<LOD> lods;
|
Vector<LOD> lods;
|
||||||
Vector<AABB> bone_aabbs;
|
Vector<AABB> bone_aabbs;
|
||||||
|
|
||||||
|
// Transforms used in runtime bone AABBs compute.
|
||||||
|
// Since bone AABBs is saved in Mesh space, but bones is in Skeleton space.
|
||||||
|
Transform3D mesh_to_skeleton_xform;
|
||||||
|
|
||||||
Vector<uint8_t> blend_shape_data;
|
Vector<uint8_t> blend_shape_data;
|
||||||
|
|
||||||
RID material;
|
RID material;
|
||||||
|
@ -1461,6 +1465,9 @@ public:
|
||||||
|
|
||||||
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
|
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
|
||||||
|
|
||||||
|
Rect2 debug_canvas_item_get_rect(RID p_item);
|
||||||
|
virtual Rect2 _debug_canvas_item_get_rect(RID p_item) = 0;
|
||||||
|
|
||||||
/* GLOBAL SHADER UNIFORMS */
|
/* GLOBAL SHADER UNIFORMS */
|
||||||
|
|
||||||
enum GlobalShaderParameterType {
|
enum GlobalShaderParameterType {
|
||||||
|
|
Loading…
Reference in New Issue