Reimplement skeletons and blend shapes

Uses compute shaders, which only once, on demand, and all in parallel.
This commit is contained in:
reduz
2020-12-16 11:07:08 -03:00
parent c514cc5822
commit bf77016c8a
21 changed files with 868 additions and 117 deletions

View File

@ -370,6 +370,22 @@ RID RendererSceneCull::instance_create() {
return instance_rid;
}
void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
bool needs_instance = RSG::storage->mesh_needs_instance(p_instance->base, p_instance->skeleton.is_valid());
if (needs_instance != p_instance->mesh_instance.is_valid()) {
if (needs_instance) {
p_instance->mesh_instance = RSG::storage->mesh_instance_create(p_instance->base);
} else {
RSG::storage->free(p_instance->mesh_instance);
p_instance->mesh_instance = RID();
}
}
if (p_instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_set_skeleton(p_instance->mesh_instance, p_instance->skeleton);
}
}
void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
Instance *instance = instance_owner.getornull(p_instance);
ERR_FAIL_COND(!instance);
@ -384,6 +400,11 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->octree_id = 0;
}
if (instance->mesh_instance.is_valid()) {
RSG::storage->free(instance->mesh_instance);
instance->mesh_instance = RID();
}
switch (instance->base_type) {
case RS::INSTANCE_LIGHT: {
InstanceLightData *light = static_cast<InstanceLightData *>(instance->base_data);
@ -450,7 +471,6 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = nullptr;
}
instance->blend_values.clear();
instance->materials.clear();
}
@ -479,9 +499,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
case RS::INSTANCE_PARTICLES: {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
if (instance->base_type == RS::INSTANCE_MESH) {
instance->blend_values.resize(RSG::storage->mesh_get_blend_shape_count(p_base));
}
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData);
@ -520,6 +538,10 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base = p_base;
if (instance->base_type == RS::INSTANCE_MESH) {
_instance_update_mesh_instance(instance);
}
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
RSG::storage->base_update_dependency(p_base, instance);
}
@ -662,8 +684,9 @@ void RendererSceneCull::instance_set_blend_shape_weight(RID p_instance, int p_sh
_update_dirty_instance(instance);
}
ERR_FAIL_INDEX(p_shape, instance->blend_values.size());
instance->blend_values.write[p_shape] = p_weight;
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_set_blend_shape_weight(instance->mesh_instance, p_shape, p_weight);
}
}
void RendererSceneCull::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) {
@ -777,6 +800,9 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
//update the dependency now, so if cleared, we remove it
RSG::storage->skeleton_update_dependency(p_skeleton, instance);
}
_instance_update_mesh_instance(instance);
_instance_queue_update(instance, true, true);
}
@ -1571,6 +1597,10 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
if (j == 0 || max > cull_max) {
cull_max = max;
}
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
if (cull_max > z_max) {
@ -1671,6 +1701,8 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, z_max - z_min_cam, distances[i + 1], i, radius * 2.0 / texture_size, bias_scale * aspect_bias_scale * min_distance_bias_scale, z_max, uv_scale);
}
RSG::storage->update_mesh_instances();
scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
}
@ -1711,9 +1743,15 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
}
@ -1763,9 +1801,13 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
}
@ -1800,9 +1842,15 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
instance->depth = near_plane.distance_to(instance->transform.origin);
instance->depth_layer = 0;
if (instance->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(instance->mesh_instance);
}
}
}
RSG::storage->update_mesh_instances();
scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, cull_count);
@ -2143,6 +2191,10 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
if (ins->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(ins->mesh_instance);
}
ins->depth = near_plane.distance_to(ins->transform.origin);
ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15);
}
@ -2159,6 +2211,8 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
ins->last_frame_pass = frame_number;
}
RSG::storage->update_mesh_instances();
/* STEP 5 - PROCESS LIGHTS */
RID *directional_light_ptr = &light_instance_cull_result[light_cull_count];
@ -2344,6 +2398,9 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
} else if ((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
if (ins->baked_light) {
keep = true;
if (ins->mesh_instance.is_valid()) {
RSG::storage->mesh_instance_check_for_update(ins->mesh_instance);
}
}
}
@ -2355,6 +2412,8 @@ void RendererSceneCull::_prepare_scene(const Transform p_cam_transform, const Ca
}
}
RSG::storage->update_mesh_instances();
scene_render->render_sdfgi(p_render_buffers, i, (RendererSceneRender::InstanceBase **)instance_shadow_cull_result, sdfgi_cull_count);
//have to save updated cascades, then update static lights.
}
@ -2795,13 +2854,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base);
p_instance->materials.resize(new_mat_count);
int new_blend_shape_count = RSG::storage->mesh_get_blend_shape_count(p_instance->base);
if (new_blend_shape_count != p_instance->blend_values.size()) {
p_instance->blend_values.resize(new_blend_shape_count);
for (int i = 0; i < new_blend_shape_count; i++) {
p_instance->blend_values.write[i] = 0;
}
}
_instance_update_mesh_instance(p_instance);
}
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {