From f42b02cccce062b9a2f2930b8d8ddac1a275b07b Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 13 Sep 2023 22:36:37 +0200 Subject: [PATCH] Workbench: Sculpt fixes * Fix #112284 and other non-reported sculpt-related regressions in the new Workbench. * Cleanup ObjectState setup. * Update `sculpt_batches_get` to support getting per material batches while passing SculptBatchFeatures. * Make material indices 0 based in Workbench. Pull Request: https://projects.blender.org/blender/blender/pulls/112344 --- .../engines/workbench/workbench_engine.cc | 32 +++-- .../engines/workbench/workbench_materials.cc | 2 +- .../engines/workbench/workbench_private.hh | 1 - .../draw/engines/workbench/workbench_state.cc | 116 +++++++----------- source/blender/draw/intern/draw_sculpt.cc | 5 +- source/blender/draw/intern/draw_sculpt.hh | 4 +- 6 files changed, 66 insertions(+), 94 deletions(-) diff --git a/source/blender/draw/engines/workbench/workbench_engine.cc b/source/blender/draw/engines/workbench/workbench_engine.cc index 353c4c5e887..7c8df9f3e9d 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.cc +++ b/source/blender/draw/engines/workbench/workbench_engine.cc @@ -107,7 +107,7 @@ class Instance { case V3D_SHADING_TEXTURE_COLOR: ATTR_FALLTHROUGH; case V3D_SHADING_MATERIAL_COLOR: - if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, slot)) { + if (::Material *_mat = BKE_object_material_get_eval(ob_ref.object, slot + 1)) { return Material(*_mat); } ATTR_FALLTHROUGH; @@ -271,8 +271,7 @@ class Instance { continue; } - /* Material slots start from 1. */ - int material_slot = i + 1; + int material_slot = i; Material mat = get_material(ob_ref, object_state.color_type, material_slot); has_transparent_material = has_transparent_material || mat.is_transparent(); @@ -324,11 +323,16 @@ class Instance { void sculpt_sync(ObjectRef &ob_ref, ResourceHandle handle, const ObjectState &object_state) { + SculptBatchFeature features = SCULPT_BATCH_DEFAULT; + if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) { + features = SCULPT_BATCH_VERTEX_COLOR; + } + else if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) { + features = SCULPT_BATCH_UV; + } + if (object_state.use_per_material_batches) { - const int material_count = DRW_cache_object_material_count_get(ob_ref.object); - for (SculptBatch &batch : sculpt_batches_per_material_get( - ob_ref.object, {get_dummy_gpu_materials(material_count), material_count})) - { + for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, true, features)) { Material mat = get_material(ob_ref, object_state.color_type, batch.material_slot); if (SCULPT_DEBUG_DRAW) { mat.base_color = batch.debug_color(); @@ -346,15 +350,7 @@ class Instance { } else { Material mat = get_material(ob_ref, object_state.color_type); - SculptBatchFeature features = SCULPT_BATCH_DEFAULT; - if (object_state.color_type == V3D_SHADING_VERTEX_COLOR) { - features = SCULPT_BATCH_VERTEX_COLOR; - } - else if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) { - features = SCULPT_BATCH_UV; - } - - for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, features)) { + for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, false, features)) { if (SCULPT_DEBUG_DRAW) { mat.base_color = batch.debug_color(); } @@ -395,12 +391,12 @@ class Instance { /* Skip frustum culling. */ ResourceHandle handle = manager.resource_handle(float4x4(ob_ref.object->object_to_world)); - Material mat = get_material(ob_ref, object_state.color_type, psys->part->omat); + Material mat = get_material(ob_ref, object_state.color_type, psys->part->omat - 1); ::Image *image = nullptr; ImageUser *iuser = nullptr; GPUSamplerState sampler_state = GPUSamplerState::default_sampler(); if (object_state.color_type == V3D_SHADING_TEXTURE_COLOR) { - get_material_image(ob_ref.object, psys->part->omat, image, iuser, sampler_state); + get_material_image(ob_ref.object, psys->part->omat - 1, image, iuser, sampler_state); } resources.material_buf.append(mat); int material_index = resources.material_buf.size() - 1; diff --git a/source/blender/draw/engines/workbench/workbench_materials.cc b/source/blender/draw/engines/workbench/workbench_materials.cc index 6ba229ea850..eb414aa6dfe 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.cc +++ b/source/blender/draw/engines/workbench/workbench_materials.cc @@ -68,7 +68,7 @@ void get_material_image(Object *ob, { const ::bNode *node = nullptr; - ED_object_get_active_image(ob, material_slot, &image, &iuser, &node, nullptr); + ED_object_get_active_image(ob, material_slot + 1, &image, &iuser, &node, nullptr); if (node && image) { switch (node->type) { case SH_NODE_TEX_IMAGE: { diff --git a/source/blender/draw/engines/workbench/workbench_private.hh b/source/blender/draw/engines/workbench/workbench_private.hh index 82697458727..b58c61a8952 100644 --- a/source/blender/draw/engines/workbench/workbench_private.hh +++ b/source/blender/draw/engines/workbench/workbench_private.hh @@ -107,7 +107,6 @@ struct SceneState { struct ObjectState { eV3DShadingColorType color_type = V3D_SHADING_SINGLE_COLOR; bool sculpt_pbvh = false; - bool texture_paint_mode = false; ::Image *image_paint_override = nullptr; GPUSamplerState override_sampler_state = GPUSamplerState::default_sampler(); bool draw_shadow = false; diff --git a/source/blender/draw/engines/workbench/workbench_state.cc b/source/blender/draw/engines/workbench/workbench_state.cc index 35b4de3d2ef..8fdd65dc2de 100644 --- a/source/blender/draw/engines/workbench/workbench_state.cc +++ b/source/blender/draw/engines/workbench/workbench_state.cc @@ -197,32 +197,42 @@ static const CustomData *get_vert_custom_data(const Mesh *mesh) ObjectState::ObjectState(const SceneState &scene_state, Object *ob) { - sculpt_pbvh = false; - texture_paint_mode = false; - image_paint_override = nullptr; - override_sampler_state = GPUSamplerState::default_sampler(); - draw_shadow = false; - const DRWContextState *draw_ctx = DRW_context_state_get(); const bool is_active = (ob == draw_ctx->obact); - /* TODO(@pragma37): Is the double check needed? - * If it is, wouldn't be needed for sculpt_pbvh too? */ - const bool is_render = DRW_state_is_image_render() && (draw_ctx->v3d == nullptr); - - color_type = (eV3DShadingColorType)scene_state.shading.color_type; - if (!(is_active && DRW_object_use_hide_faces(ob))) { - draw_shadow = (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && scene_state.draw_shadows; - } + image_paint_override = nullptr; + override_sampler_state = GPUSamplerState::default_sampler(); sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) && !DRW_state_is_image_render(); + draw_shadow = scene_state.draw_shadows && (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && + !is_active && !sculpt_pbvh && !DRW_object_use_hide_faces(ob); + + color_type = (eV3DShadingColorType)scene_state.shading.color_type; + + bool has_color = false; + bool has_uv = false; + + if (ob->type == OB_MESH) { + const Mesh *me = static_cast(ob->data); + const CustomData *cd_vdata = get_vert_custom_data(me); + const CustomData *cd_ldata = get_loop_custom_data(me); + + has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) || + CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) || + CustomData_has_layer(cd_ldata, CD_PROP_COLOR) || + CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR)); + + has_uv = CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2); + } + + if (color_type == V3D_SHADING_TEXTURE_COLOR && (!has_uv || ob->dt < OB_TEXTURE)) { + color_type = V3D_SHADING_MATERIAL_COLOR; + } + else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color) { + color_type = V3D_SHADING_OBJECT_COLOR; + } if (sculpt_pbvh) { - /* Shadows are unsupported in sculpt mode. We could revert to the slow - * method in this case but I'm not sure if it's a good idea given that - * sculpted meshes are heavy to begin with. */ - draw_shadow = false; - if (color_type == V3D_SHADING_TEXTURE_COLOR && BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES) { /* Force use of material color for sculpt. */ color_type = V3D_SHADING_MATERIAL_COLOR; @@ -236,59 +246,25 @@ ObjectState::ObjectState(const SceneState &scene_state, Object *ob) C, &scene_state.scene->toolsettings->paint_mode, ob, color_type); } } - else if (ob->type == OB_MESH) { - const Mesh *me = static_cast(ob->data); - const CustomData *cd_vdata = get_vert_custom_data(me); - const CustomData *cd_ldata = get_loop_custom_data(me); - - bool has_color = (CustomData_has_layer(cd_vdata, CD_PROP_COLOR) || - CustomData_has_layer(cd_vdata, CD_PROP_BYTE_COLOR) || - CustomData_has_layer(cd_ldata, CD_PROP_COLOR) || - CustomData_has_layer(cd_ldata, CD_PROP_BYTE_COLOR)); - - bool has_uv = CustomData_has_layer(cd_ldata, CD_PROP_FLOAT2); - - if (color_type == V3D_SHADING_TEXTURE_COLOR) { - if (ob->dt < OB_TEXTURE || !has_uv) { - color_type = V3D_SHADING_MATERIAL_COLOR; + else if (ob->type == OB_MESH && !DRW_state_is_scene_render()) { + /* Force texture or vertex mode if object is in paint mode. */ + const bool is_vertpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_VERTEX); + const bool is_texpaint_mode = is_active && (scene_state.object_mode == CTX_MODE_PAINT_TEXTURE); + if (is_vertpaint_mode && has_color) { + color_type = V3D_SHADING_VERTEX_COLOR; + } + else if (is_texpaint_mode && has_uv) { + color_type = V3D_SHADING_TEXTURE_COLOR; + const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint; + if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { + image_paint_override = imapaint->canvas; + override_sampler_state.extend_x = GPU_SAMPLER_EXTEND_MODE_REPEAT; + override_sampler_state.extend_yz = GPU_SAMPLER_EXTEND_MODE_REPEAT; + const bool use_linear_filter = imapaint->interp == IMAGEPAINT_INTERP_LINEAR; + override_sampler_state.set_filtering_flag_from_test(GPU_SAMPLER_FILTERING_LINEAR, + use_linear_filter); } } - else if (color_type == V3D_SHADING_VERTEX_COLOR && !has_color) { - color_type = V3D_SHADING_OBJECT_COLOR; - } - - if (!is_render) { - /* Force texture or vertex mode if object is in paint mode. */ - const bool is_vertpaint_mode = is_active && - (scene_state.object_mode == CTX_MODE_PAINT_VERTEX); - const bool is_texpaint_mode = is_active && - (scene_state.object_mode == CTX_MODE_PAINT_TEXTURE); - if (is_vertpaint_mode && has_color) { - color_type = V3D_SHADING_VERTEX_COLOR; - } - else if (is_texpaint_mode && has_uv) { - color_type = V3D_SHADING_TEXTURE_COLOR; - texture_paint_mode = true; - - const ImagePaintSettings *imapaint = &scene_state.scene->toolsettings->imapaint; - if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) { - image_paint_override = imapaint->canvas; - override_sampler_state.extend_x = GPU_SAMPLER_EXTEND_MODE_REPEAT; - override_sampler_state.extend_yz = GPU_SAMPLER_EXTEND_MODE_REPEAT; - const bool use_linear_filter = imapaint->interp == IMAGEPAINT_INTERP_LINEAR; - override_sampler_state.set_filtering_flag_from_test(GPU_SAMPLER_FILTERING_LINEAR, - use_linear_filter); - } - } - } - } - else { - if (color_type == V3D_SHADING_TEXTURE_COLOR) { - color_type = V3D_SHADING_MATERIAL_COLOR; - } - else if (color_type == V3D_SHADING_VERTEX_COLOR) { - color_type = V3D_SHADING_OBJECT_COLOR; - } } use_per_material_batches = image_paint_override == nullptr && ELEM(color_type, diff --git a/source/blender/draw/intern/draw_sculpt.cc b/source/blender/draw/intern/draw_sculpt.cc index 010a080ad42..fa02ff7d1d4 100644 --- a/source/blender/draw/intern/draw_sculpt.cc +++ b/source/blender/draw/intern/draw_sculpt.cc @@ -152,7 +152,7 @@ static Vector sculpt_batches_get_ex( return data.batches; } -Vector sculpt_batches_get(Object *ob, SculptBatchFeature features) +Vector sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features) { PBVHAttrReq attrs[16] = {}; int attrs_len = 0; @@ -193,7 +193,8 @@ Vector sculpt_batches_get(Object *ob, SculptBatchFeature features) } } - return sculpt_batches_get_ex(ob, features & SCULPT_BATCH_WIREFRAME, false, attrs, attrs_len); + return sculpt_batches_get_ex( + ob, features & SCULPT_BATCH_WIREFRAME, per_material, attrs, attrs_len); } Vector sculpt_batches_per_material_get(Object *ob, diff --git a/source/blender/draw/intern/draw_sculpt.hh b/source/blender/draw/intern/draw_sculpt.hh index 5c62b96684c..a521e710964 100644 --- a/source/blender/draw/intern/draw_sculpt.hh +++ b/source/blender/draw/intern/draw_sculpt.hh @@ -32,9 +32,9 @@ enum SculptBatchFeature { ENUM_OPERATORS(SculptBatchFeature, SCULPT_BATCH_UV); /** Used by engines that don't use GPUMaterials, like the Workbench and Overlay engines. */ -Vector sculpt_batches_get(Object *ob, SculptBatchFeature features); +Vector sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features); -/** Used by EEVEE and Workbench Material/Texture modes. */ +/** Used by EEVEE. */ Vector sculpt_batches_per_material_get(Object *ob, MutableSpan materials);