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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Mesh *>(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<Mesh *>(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,
|
||||
|
||||
@@ -152,7 +152,7 @@ static Vector<SculptBatch> sculpt_batches_get_ex(
|
||||
return data.batches;
|
||||
}
|
||||
|
||||
Vector<SculptBatch> sculpt_batches_get(Object *ob, SculptBatchFeature features)
|
||||
Vector<SculptBatch> sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features)
|
||||
{
|
||||
PBVHAttrReq attrs[16] = {};
|
||||
int attrs_len = 0;
|
||||
@@ -193,7 +193,8 @@ Vector<SculptBatch> 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<SculptBatch> sculpt_batches_per_material_get(Object *ob,
|
||||
|
||||
@@ -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<SculptBatch> sculpt_batches_get(Object *ob, SculptBatchFeature features);
|
||||
Vector<SculptBatch> sculpt_batches_get(Object *ob, bool per_material, SculptBatchFeature features);
|
||||
|
||||
/** Used by EEVEE and Workbench Material/Texture modes. */
|
||||
/** Used by EEVEE. */
|
||||
Vector<SculptBatch> sculpt_batches_per_material_get(Object *ob,
|
||||
MutableSpan<GPUMaterial *> materials);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user