Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option for software skinning in MeshInstance #40313

Merged
merged 1 commit into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions doc/classes/MeshInstance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@
This helper creates a [StaticBody] child node with a [ConcavePolygonShape] collision shape calculated from the mesh geometry. It's mainly used for testing.
</description>
</method>
<method name="get_active_material" qualifiers="const">
<return type="Material">
</return>
<argument index="0" name="surface" type="int">
</argument>
<description>
Returns the [Material] that will be used by the [Mesh] when drawing. This can return the [member GeometryInstance.material_override], the surface override [Material] defined in this [MeshInstance], or the surface [Material] defined in the [Mesh]. For example, if [member GeometryInstance.material_override] is used, all surfaces will return the override material.
</description>
</method>
<method name="get_surface_material" qualifiers="const">
<return type="Material">
</return>
Expand Down Expand Up @@ -68,6 +77,10 @@
<member name="skin" type="Skin" setter="set_skin" getter="get_skin">
Sets the skin to be used by this instance.
</member>
<member name="software_skinning_transform_normals" type="bool" setter="set_software_skinning_transform_normals" getter="is_software_skinning_transform_normals_enabled" default="true">
If [code]true[/code], normals are transformed when software skinning is used. Set to [code]false[/code] when normals are not needed for better performance.
See [member ProjectSettings.rendering/quality/skinning/software_skinning_fallback] for details about how software skinning is enabled.
</member>
</members>
<constants>
</constants>
Expand Down
10 changes: 10 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,16 @@
<member name="rendering/quality/shadows/filter_mode.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/quality/shadows/filter_mode] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/quality/skinning/software_skinning_fallback" type="bool" setter="" getter="" default="true">
Allows [MeshInstance] to perform skinning on the CPU when the hardware doesn't support the default GPU skinning process with GLES2.
pouleyKetchoupp marked this conversation as resolved.
Show resolved Hide resolved
If [code]false[/code], an alternative skinning process on the GPU is used in this case (slower in most cases).
See also [member rendering/quality/skinning/force_software_skinning].
[b]Note:[/b] When the software skinning fallback is triggered, custom vertex shaders will behave in a different way, because the bone transform will be already applied to the modelview matrix.
</member>
<member name="rendering/quality/skinning/force_software_skinning" type="bool" setter="" getter="" default="false">
Forces [MeshInstance] to always perform skinning on the CPU (applies to both GLES2 and GLES3).
See also [member rendering/quality/skinning/software_skinning_fallback].
</member>
<member name="rendering/quality/spatial_partitioning/render_tree_balance" type="float" setter="" getter="" default="0.17">
The rendering octree balance can be changed to favor smaller ([code]0[/code]), or larger ([code]1[/code]) branches.
Larger branches can increase performance significantly in some projects.
Expand Down
3 changes: 2 additions & 1 deletion doc/classes/VisualServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,8 @@
<argument index="0" name="feature" type="String">
</argument>
<description>
Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], [code]etc2[/code] and [code]pvrtc[/code].
Returns [code]true[/code] if the OS supports a certain feature. Features might be [code]s3tc[/code], [code]etc[/code], [code]etc2[/code], [code]pvrtc[/code] and [code]skinning_fallback[/code].
When rendering with GLES2, returns [code]true[/code] with [code]skinning_fallback[/code] in case the hardware doesn't support the default GPU skinning process.
pouleyKetchoupp marked this conversation as resolved.
Show resolved Hide resolved
</description>
</method>
<method name="immediate_begin">
Expand Down
42 changes: 42 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
p_shader->spatial.uses_screen_texture = false;
p_shader->spatial.uses_depth_texture = false;
p_shader->spatial.uses_vertex = false;
p_shader->spatial.uses_tangent = false;
p_shader->spatial.uses_ensure_correct_normals = false;
p_shader->spatial.writes_modelview_or_projection = false;
p_shader->spatial.uses_world_coordinates = false;

Expand All @@ -1497,6 +1499,8 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {

shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;

shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;

shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;

Expand All @@ -1506,6 +1510,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;

// Use of any of these BUILTINS indicate the need for transformed tangents.
// This is needed to know when to transform tangents in software skinning.
shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;

shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
Expand Down Expand Up @@ -1897,6 +1906,36 @@ bool RasterizerStorageGLES2::material_casts_shadows(RID p_material) {
return casts_shadows;
}

bool RasterizerStorageGLES2::material_uses_tangents(RID p_material) {
Material *material = material_owner.get(p_material);
ERR_FAIL_COND_V(!material, false);

if (!material->shader) {
return false;
}

if (material->shader->dirty_list.in_list()) {
_update_shader(material->shader);
}
Comment on lines +1917 to +1919
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a shader update here and for ensure_correct_normals as well because information would be updated only on the next render update otherwise, and it wouldn't allow MeshInstance to check materials only once on init or when they are modified.

It didn't seem to cause any issue in the tests I've made.


return material->shader->spatial.uses_tangent;
}

bool RasterizerStorageGLES2::material_uses_ensure_correct_normals(RID p_material) {
Material *material = material_owner.get(p_material);
ERR_FAIL_COND_V(!material, false);

if (!material->shader) {
return false;
}

if (material->shader->dirty_list.in_list()) {
_update_shader(material->shader);
}

return material->shader->spatial.uses_ensure_correct_normals;
}

void RasterizerStorageGLES2::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {

Material *material = material_owner.getornull(p_material);
Expand Down Expand Up @@ -5769,6 +5808,9 @@ bool RasterizerStorageGLES2::has_os_feature(const String &p_feature) const {
if (p_feature == "etc")
return config.etc1_supported;

if (p_feature == "skinning_fallback")
return config.use_skeleton_software;

return false;
}

Expand Down
4 changes: 4 additions & 0 deletions drivers/gles2/rasterizer_storage_gles2.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,8 @@ class RasterizerStorageGLES2 : public RasterizerStorage {
bool uses_screen_texture;
bool uses_depth_texture;
bool uses_time;
bool uses_tangent;
bool uses_ensure_correct_normals;
bool writes_modelview_or_projection;
bool uses_vertex_lighting;
bool uses_world_coordinates;
Expand Down Expand Up @@ -607,6 +609,8 @@ class RasterizerStorageGLES2 : public RasterizerStorage {

virtual bool material_is_animated(RID p_material);
virtual bool material_casts_shadows(RID p_material);
virtual bool material_uses_tangents(RID p_material);
virtual bool material_uses_ensure_correct_normals(RID p_material);

virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
Expand Down
39 changes: 39 additions & 0 deletions drivers/gles3/rasterizer_storage_gles3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2342,6 +2342,8 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
p_shader->spatial.uses_screen_texture = false;
p_shader->spatial.uses_depth_texture = false;
p_shader->spatial.uses_vertex = false;
p_shader->spatial.uses_tangent = false;
p_shader->spatial.uses_ensure_correct_normals = false;
p_shader->spatial.writes_modelview_or_projection = false;
p_shader->spatial.uses_world_coordinates = false;

Expand All @@ -2366,6 +2368,8 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {

shaders.actions_scene.render_mode_flags["world_vertex_coords"] = &p_shader->spatial.uses_world_coordinates;

shaders.actions_scene.render_mode_flags["ensure_correct_normals"] = &p_shader->spatial.uses_ensure_correct_normals;

shaders.actions_scene.usage_flag_pointers["ALPHA"] = &p_shader->spatial.uses_alpha;
shaders.actions_scene.usage_flag_pointers["ALPHA_SCISSOR"] = &p_shader->spatial.uses_alpha_scissor;

Expand All @@ -2375,6 +2379,11 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
shaders.actions_scene.usage_flag_pointers["DEPTH_TEXTURE"] = &p_shader->spatial.uses_depth_texture;
shaders.actions_scene.usage_flag_pointers["TIME"] = &p_shader->spatial.uses_time;

// Use of any of these BUILTINS indicate the need for transformed tangents.
// This is needed to know when to transform tangents in software skinning.
shaders.actions_scene.usage_flag_pointers["TANGENT"] = &p_shader->spatial.uses_tangent;
shaders.actions_scene.usage_flag_pointers["NORMALMAP"] = &p_shader->spatial.uses_tangent;

shaders.actions_scene.write_flag_pointers["MODELVIEW_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
shaders.actions_scene.write_flag_pointers["PROJECTION_MATRIX"] = &p_shader->spatial.writes_modelview_or_projection;
shaders.actions_scene.write_flag_pointers["VERTEX"] = &p_shader->spatial.uses_vertex;
Expand Down Expand Up @@ -2726,6 +2735,36 @@ bool RasterizerStorageGLES3::material_casts_shadows(RID p_material) {
return casts_shadows;
}

bool RasterizerStorageGLES3::material_uses_tangents(RID p_material) {
Material *material = material_owner.get(p_material);
ERR_FAIL_COND_V(!material, false);

if (!material->shader) {
return false;
}

if (material->shader->dirty_list.in_list()) {
_update_shader(material->shader);
}

return material->shader->spatial.uses_tangent;
}

bool RasterizerStorageGLES3::material_uses_ensure_correct_normals(RID p_material) {
Material *material = material_owner.get(p_material);
ERR_FAIL_COND_V(!material, false);

if (!material->shader) {
return false;
}

if (material->shader->dirty_list.in_list()) {
_update_shader(material->shader);
}

return material->shader->spatial.uses_ensure_correct_normals;
}

void RasterizerStorageGLES3::material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance) {

Material *material = material_owner.get(p_material);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gles3/rasterizer_storage_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ class RasterizerStorageGLES3 : public RasterizerStorage {
bool uses_screen_texture;
bool uses_depth_texture;
bool uses_time;
bool uses_tangent;
bool uses_ensure_correct_normals;
bool writes_modelview_or_projection;
bool uses_vertex_lighting;
bool uses_world_coordinates;
Expand Down Expand Up @@ -606,6 +608,8 @@ class RasterizerStorageGLES3 : public RasterizerStorage {

virtual bool material_is_animated(RID p_material);
virtual bool material_casts_shadows(RID p_material);
virtual bool material_uses_tangents(RID p_material);
virtual bool material_uses_ensure_correct_normals(RID p_material);

virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance);
Expand Down
Loading