EEVEE Next: Sculpt support
Add sculpt support to EEVEE Next. It creates a new resource handle for sculpt object, since BKE_object_boundbox_get returns a wrong (zeroed) bounding box. This also adds a new `resource_handle` function to the `draw::Manager` that works like the default one, but lets the caller optionally override the object matrix and/or bounds. Pull Request: https://projects.blender.org/blender/blender/pulls/110703
This commit is contained in:
parent
ada738ac7c
commit
41c83d6cfc
|
@ -213,7 +213,9 @@ void Instance::object_sync(Object *ob)
|
|||
lights.sync_light(ob, ob_handle);
|
||||
break;
|
||||
case OB_MESH:
|
||||
sync.sync_mesh(ob, ob_handle, res_handle, ob_ref);
|
||||
if (!sync.sync_sculpt(ob, ob_handle, res_handle, ob_ref)) {
|
||||
sync.sync_mesh(ob, ob_handle, res_handle, ob_ref);
|
||||
}
|
||||
break;
|
||||
case OB_POINTCLOUD:
|
||||
sync.sync_point_cloud(ob, ob_handle, res_handle, ob_ref);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "BKE_gpencil_legacy.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh_api.hh"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_gpencil_legacy_types.h"
|
||||
|
@ -19,6 +21,7 @@
|
|||
#include "DNA_particle_types.h"
|
||||
|
||||
#include "draw_common.hh"
|
||||
#include "draw_sculpt.hh"
|
||||
|
||||
#include "eevee_instance.hh"
|
||||
|
||||
|
@ -154,6 +157,75 @@ void SyncModule::sync_mesh(Object *ob,
|
|||
inst_.cryptomatte.sync_object(ob, res_handle);
|
||||
}
|
||||
|
||||
bool SyncModule::sync_sculpt(Object *ob,
|
||||
ObjectHandle &ob_handle,
|
||||
ResourceHandle res_handle,
|
||||
const ObjectRef &ob_ref)
|
||||
{
|
||||
bool pbvh_draw = BKE_sculptsession_use_pbvh_draw(ob, inst_.rv3d) && !DRW_state_is_image_render();
|
||||
/* Needed for mesh cache validation, to prevent two copies of
|
||||
* of vertex color arrays from being sent to the GPU (e.g.
|
||||
* when switching from eevee to workbench).
|
||||
*/
|
||||
if (ob_ref.object->sculpt && ob_ref.object->sculpt->pbvh) {
|
||||
BKE_pbvh_is_drawing_set(ob_ref.object->sculpt->pbvh, pbvh_draw);
|
||||
}
|
||||
|
||||
if (!pbvh_draw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Use a valid bounding box. The PBVH module already does its own culling,
|
||||
* but a valid bounding box is still needed for directional shadow tilemap bounds computation. */
|
||||
float3 min, max;
|
||||
BKE_pbvh_bounding_box(ob_ref.object->sculpt->pbvh, min, max);
|
||||
float3 center = (min + max) * 0.5;
|
||||
float3 half_extent = max - center;
|
||||
res_handle = inst_.manager->resource_handle(ob_ref, nullptr, ¢er, &half_extent);
|
||||
|
||||
bool has_motion = false;
|
||||
MaterialArray &material_array = inst_.materials.material_array_get(ob, has_motion);
|
||||
|
||||
bool is_shadow_caster = false;
|
||||
bool is_alpha_blend = false;
|
||||
bool do_probe_sync = inst_.do_probe_sync();
|
||||
for (SculptBatch &batch :
|
||||
sculpt_batches_per_material_get(ob_ref.object, material_array.gpu_materials))
|
||||
{
|
||||
GPUBatch *geom = batch.batch;
|
||||
if (geom == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Material &material = material_array.materials[batch.material_slot];
|
||||
|
||||
geometry_call(material.shading.sub_pass, geom, res_handle);
|
||||
geometry_call(material.prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.shadow.sub_pass, geom, res_handle);
|
||||
|
||||
/* TODO(Miguel Pozo): Is this needed ? */
|
||||
geometry_call(material.capture.sub_pass, geom, res_handle);
|
||||
if (do_probe_sync) {
|
||||
geometry_call(material.probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.probe_shading.sub_pass, geom, res_handle);
|
||||
}
|
||||
|
||||
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
|
||||
is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent;
|
||||
|
||||
GPUMaterial *gpu_material = material_array.gpu_materials[batch.material_slot];
|
||||
::Material *mat = GPU_material_get_material(gpu_material);
|
||||
inst_.cryptomatte.sync_material(mat);
|
||||
}
|
||||
|
||||
inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials);
|
||||
|
||||
inst_.shadows.sync_object(ob_handle, res_handle, is_shadow_caster, is_alpha_blend);
|
||||
inst_.cryptomatte.sync_object(ob, res_handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -167,6 +167,10 @@ class SyncModule {
|
|||
ObjectHandle &ob_handle,
|
||||
ResourceHandle res_handle,
|
||||
const ObjectRef &ob_ref);
|
||||
bool sync_sculpt(Object *ob,
|
||||
ObjectHandle &ob_handle,
|
||||
ResourceHandle res_handle,
|
||||
const ObjectRef &ob_ref);
|
||||
void sync_point_cloud(Object *ob,
|
||||
ObjectHandle &ob_handle,
|
||||
ResourceHandle res_handle,
|
||||
|
|
|
@ -120,6 +120,14 @@ class Manager {
|
|||
* Create a new resource handle for the given object.
|
||||
*/
|
||||
ResourceHandle resource_handle(const ObjectRef ref);
|
||||
/**
|
||||
* Create a new resource handle for the given object, but optionally override model matrix and
|
||||
* bounds.
|
||||
*/
|
||||
ResourceHandle resource_handle(const ObjectRef ref,
|
||||
const float4x4 *model_matrix,
|
||||
const float3 *bounds_center,
|
||||
const float3 *bounds_half_extent);
|
||||
/**
|
||||
* Get resource id for a loose matrix. The draw-calls for this resource handle won't be culled
|
||||
* and there won't be any associated object info / bounds. Assumes correct handedness / winding.
|
||||
|
@ -207,6 +215,28 @@ inline ResourceHandle Manager::resource_handle(const ObjectRef ref)
|
|||
return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0);
|
||||
}
|
||||
|
||||
inline ResourceHandle Manager::resource_handle(const ObjectRef ref,
|
||||
const float4x4 *model_matrix,
|
||||
const float3 *bounds_center,
|
||||
const float3 *bounds_half_extent)
|
||||
{
|
||||
bool is_active_object = (ref.dupli_object ? ref.dupli_parent : ref.object) == object_active;
|
||||
if (model_matrix) {
|
||||
matrix_buf.current().get_or_resize(resource_len_).sync(*model_matrix);
|
||||
}
|
||||
else {
|
||||
matrix_buf.current().get_or_resize(resource_len_).sync(*ref.object);
|
||||
}
|
||||
if (bounds_center && bounds_half_extent) {
|
||||
bounds_buf.current().get_or_resize(resource_len_).sync(*bounds_center, *bounds_half_extent);
|
||||
}
|
||||
else {
|
||||
bounds_buf.current().get_or_resize(resource_len_).sync(*ref.object);
|
||||
}
|
||||
infos_buf.current().get_or_resize(resource_len_).sync(ref, is_active_object);
|
||||
return ResourceHandle(resource_len_++, (ref.object->transflag & OB_NEG_SCALE) != 0);
|
||||
}
|
||||
|
||||
inline ResourceHandle Manager::resource_handle(const float4x4 &model_matrix)
|
||||
{
|
||||
matrix_buf.current().get_or_resize(resource_len_).sync(model_matrix);
|
||||
|
|
Loading…
Reference in New Issue