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

Shadows don't update when changing blend shape values #91871

Open
RedMser opened this issue May 12, 2024 · 1 comment · May be fixed by #92244
Open

Shadows don't update when changing blend shape values #91871

RedMser opened this issue May 12, 2024 · 1 comment · May be fixed by #92244

Comments

@RedMser
Copy link
Contributor

RedMser commented May 12, 2024

Tested versions

Reproducible in 2ba22d1 (custom build from 2 days ago)

System information

Windows 10.0.19044 - dedicated NVIDIA GeForce RTX 2080 (NVIDIA; 31.0.15.5186) - Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz (12 Threads)

Issue description

If you change a MeshInstance's blend shapes using code set_blend_shape_value in e.g. _process, then shadows of an OmniLight3D will not update until you also move the mesh (e.g. by nudging the position value slightly).

This happens in Compatibility, Mobile and Forward+ renderers.

Steps to reproduce

See above.

Minimal reproduction project (MRP)

blend-shapes-dont-update-shadows.zip

The cube is animated via blend shapes only. Uncommenting the last line in the cube's script will fix shadows not updating. Change renderer to any other and observe the same problem.

@clayjohn
Copy link
Member

This will need a bit of investigation to track down. But I think there is one of three things to look for:

  1. We may need to notify the dependency system that the variable changed like we do for skeletons:
    skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_BONES);
  2. We may need to set the instance to dirty some other way when updating blend shapes. Maybe here:
    void MeshStorage::mesh_instance_set_blend_shape_weight(RID p_mesh_instance, int p_shape, float p_weight) {
    MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance);
    ERR_FAIL_NULL(mi);
    ERR_FAIL_INDEX(p_shape, (int)mi->blend_weights.size());
    mi->blend_weights[p_shape] = p_weight;
    mi->weights_dirty = true;
    //will be eventually updated
    }

For context instance_set_blend_shape_weight() will try to update the instance if it is already dirty.

void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_NULL(instance);
if (instance->update_item.in_list()) {
_update_dirty_instance(instance);
}
if (instance->mesh_instance.is_valid()) {
RSG::mesh_storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
}

If the instance is flagged as dirty, then we will mark the shadows as dirty. But we could also do it manually when blend shapes are modified:

if (geom->can_cast_shadows) {
for (HashSet<RendererSceneCull::Instance *>::Iterator I = geom->lights.begin(); I != geom->lights.end(); ++I) {
InstanceLightData *light = static_cast<InstanceLightData *>((*I)->base_data);
light->make_shadow_dirty();
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants