Merge branch 'blender-v4.1-release'
This commit is contained in:
@@ -149,9 +149,55 @@ OIDNFilter OIDNDenoiserGPU::create_filter()
|
||||
denoiser_device_->set_error(error_message);
|
||||
}
|
||||
}
|
||||
|
||||
# if OIDN_VERSION_MAJOR >= 2
|
||||
switch (quality_) {
|
||||
case DENOISER_QUALITY_BALANCED:
|
||||
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_BALANCED);
|
||||
break;
|
||||
case DENOISER_QUALITY_HIGH:
|
||||
default:
|
||||
oidnSetFilterInt(filter, "quality", OIDN_QUALITY_HIGH);
|
||||
}
|
||||
# endif
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
bool OIDNDenoiserGPU::commit_and_execute_filter(OIDNFilter filter, ExecMode mode)
|
||||
{
|
||||
const char *error_message = nullptr;
|
||||
OIDNError err = OIDN_ERROR_NONE;
|
||||
|
||||
for (;;) {
|
||||
oidnCommitFilter(filter);
|
||||
if (mode == ExecMode::ASYNC) {
|
||||
oidnExecuteFilterAsync(filter);
|
||||
}
|
||||
else {
|
||||
oidnExecuteFilter(filter);
|
||||
}
|
||||
|
||||
/* If OIDN runs out of memory, reduce mem limit and retry */
|
||||
err = oidnGetDeviceError(oidn_device_, (const char **)&error_message);
|
||||
if (err != OIDN_ERROR_OUT_OF_MEMORY || max_mem_ < 200) {
|
||||
break;
|
||||
}
|
||||
max_mem_ = max_mem_ / 2;
|
||||
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
|
||||
}
|
||||
|
||||
if (err != OIDN_ERROR_NONE) {
|
||||
if (error_message == nullptr) {
|
||||
error_message = "Unspecified OIDN error";
|
||||
}
|
||||
LOG(ERROR) << "OIDN error: " << error_message;
|
||||
denoiser_device_->set_error(error_message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
|
||||
{
|
||||
const bool recreate_denoiser = (oidn_device_ == nullptr) || (oidn_filter_ == nullptr) ||
|
||||
@@ -224,24 +270,8 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
|
||||
|
||||
oidnSetFilterBool(oidn_filter_, "hdr", true);
|
||||
oidnSetFilterBool(oidn_filter_, "srgb", false);
|
||||
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
|
||||
if (params_.prefilter == DENOISER_PREFILTER_NONE ||
|
||||
params_.prefilter == DENOISER_PREFILTER_ACCURATE)
|
||||
{
|
||||
oidnSetFilterInt(oidn_filter_, "cleanAux", true);
|
||||
}
|
||||
|
||||
# if OIDN_VERSION_MAJOR >= 2
|
||||
switch (params_.quality) {
|
||||
case DENOISER_QUALITY_BALANCED:
|
||||
oidnSetFilterInt(oidn_filter_, "quality", OIDN_QUALITY_BALANCED);
|
||||
break;
|
||||
case DENOISER_QUALITY_HIGH:
|
||||
default:
|
||||
oidnSetFilterInt(oidn_filter_, "quality", OIDN_QUALITY_HIGH);
|
||||
}
|
||||
quality_ = params_.quality;
|
||||
# endif
|
||||
|
||||
if (context.use_pass_albedo) {
|
||||
albedo_filter_ = create_filter();
|
||||
@@ -295,6 +325,7 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
|
||||
pass.denoised_offset * sizeof(float),
|
||||
pass_stride_in_bytes,
|
||||
pass_stride_in_bytes * context.buffer_params.stride);
|
||||
|
||||
set_filter_pass(oidn_filter_,
|
||||
"output",
|
||||
context.render_buffers->buffer.device_pointer,
|
||||
@@ -312,8 +343,18 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
|
||||
const int64_t row_stride_in_bytes = context.guiding_params.stride * pixel_stride_in_bytes;
|
||||
|
||||
if (context.use_pass_albedo) {
|
||||
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
|
||||
set_filter_pass(oidn_filter_,
|
||||
set_filter_pass(oidn_filter_,
|
||||
"albedo",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_albedo * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
|
||||
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
|
||||
set_filter_pass(albedo_filter_,
|
||||
"albedo",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
@@ -322,17 +363,7 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
|
||||
context.guiding_params.pass_albedo * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
}
|
||||
else {
|
||||
set_filter_pass(albedo_filter_,
|
||||
"color",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_albedo * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
|
||||
set_filter_pass(albedo_filter_,
|
||||
"output",
|
||||
d_guiding_buffer,
|
||||
@@ -342,36 +373,27 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
|
||||
context.guiding_params.pass_albedo * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
oidnCommitFilter(albedo_filter_);
|
||||
oidnExecuteFilterAsync(albedo_filter_);
|
||||
|
||||
set_filter_pass(oidn_filter_,
|
||||
"albedo",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_albedo * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
if (!commit_and_execute_filter(albedo_filter_, ExecMode::ASYNC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (context.use_pass_normal) {
|
||||
if (params_.prefilter == DENOISER_PREFILTER_NONE) {
|
||||
set_filter_pass(oidn_filter_,
|
||||
"normal",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_normal * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
}
|
||||
else {
|
||||
set_filter_pass(oidn_filter_,
|
||||
"normal",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_normal * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
|
||||
if (params_.prefilter == DENOISER_PREFILTER_ACCURATE) {
|
||||
set_filter_pass(normal_filter_,
|
||||
"color",
|
||||
"normal",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
@@ -390,47 +412,15 @@ bool OIDNDenoiserGPU::denoise_run(const DenoiseContext &context, const DenoisePa
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
|
||||
oidnCommitFilter(normal_filter_);
|
||||
oidnExecuteFilterAsync(normal_filter_);
|
||||
|
||||
set_filter_pass(oidn_filter_,
|
||||
"normal",
|
||||
d_guiding_buffer,
|
||||
OIDN_FORMAT_FLOAT3,
|
||||
context.buffer_params.width,
|
||||
context.buffer_params.height,
|
||||
context.guiding_params.pass_normal * sizeof(float),
|
||||
pixel_stride_in_bytes,
|
||||
row_stride_in_bytes);
|
||||
if (!commit_and_execute_filter(normal_filter_, ExecMode::ASYNC)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oidnCommitFilter(oidn_filter_);
|
||||
oidnExecuteFilter(oidn_filter_);
|
||||
|
||||
const char *out_message = nullptr;
|
||||
OIDNError err = oidnGetDeviceError(oidn_device_, (const char **)&out_message);
|
||||
if (OIDN_ERROR_NONE != err) {
|
||||
/* If OIDN runs out of memory, reduce mem limit and retry */
|
||||
while (err == OIDN_ERROR_OUT_OF_MEMORY && max_mem_ > 200) {
|
||||
max_mem_ = max_mem_ / 2;
|
||||
oidnSetFilterInt(oidn_filter_, "maxMemoryMB", max_mem_);
|
||||
oidnCommitFilter(oidn_filter_);
|
||||
oidnExecuteFilter(oidn_filter_);
|
||||
err = oidnGetDeviceError(oidn_device_, &out_message);
|
||||
}
|
||||
if (out_message) {
|
||||
LOG(ERROR) << "OIDN error: " << out_message;
|
||||
denoiser_device_->set_error(out_message);
|
||||
}
|
||||
else {
|
||||
LOG(ERROR) << "OIDN error: unspecified";
|
||||
denoiser_device_->set_error("Unspecified OIDN error");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
oidnSetFilterInt(oidn_filter_, "cleanAux", params_.prefilter != DENOISER_PREFILTER_FAST);
|
||||
return commit_and_execute_filter(oidn_filter_);
|
||||
}
|
||||
|
||||
void OIDNDenoiserGPU::set_filter_pass(OIDNFilter filter,
|
||||
|
||||
@@ -36,6 +36,11 @@ class OIDNDenoiserGPU : public DenoiserGPU {
|
||||
static bool is_device_supported(const DeviceInfo &device);
|
||||
|
||||
protected:
|
||||
enum class ExecMode {
|
||||
SYNC,
|
||||
ASYNC,
|
||||
};
|
||||
|
||||
virtual uint get_device_type_mask() const override;
|
||||
|
||||
/* Create OIDN denoiser descriptor if needed.
|
||||
@@ -50,6 +55,7 @@ class OIDNDenoiserGPU : public DenoiserGPU {
|
||||
virtual bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) override;
|
||||
|
||||
OIDNFilter create_filter();
|
||||
bool commit_and_execute_filter(OIDNFilter filter, ExecMode mode = ExecMode::SYNC);
|
||||
|
||||
void set_filter_pass(OIDNFilter filter,
|
||||
const char *name,
|
||||
@@ -73,7 +79,8 @@ class OIDNDenoiserGPU : public DenoiserGPU {
|
||||
bool use_pass_normal_ = false;
|
||||
DenoiserQuality quality_ = DENOISER_QUALITY_HIGH;
|
||||
|
||||
int max_mem_ = 3000;
|
||||
/* Filter memory usage limit if we ran out of memory with OIDN's default limit. */
|
||||
int max_mem_ = 768;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -4466,6 +4466,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu):
|
||||
|
||||
col.operator("mesh.mark_sharp")
|
||||
col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
|
||||
col.operator("mesh.set_sharpness_by_angle")
|
||||
|
||||
if with_freestyle:
|
||||
col.separator()
|
||||
|
||||
@@ -49,6 +49,7 @@ set(SRC
|
||||
editmesh_rip_edge.cc
|
||||
editmesh_select.cc
|
||||
editmesh_select_similar.cc
|
||||
editmesh_set_sharpness_by_angle.cc
|
||||
editmesh_tools.cc
|
||||
editmesh_undo.cc
|
||||
editmesh_utils.cc
|
||||
|
||||
105
source/blender/editors/mesh/editmesh_set_sharpness_by_angle.cc
Normal file
105
source/blender/editors/mesh/editmesh_set_sharpness_by_angle.cc
Normal file
@@ -0,0 +1,105 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edmesh
|
||||
*/
|
||||
|
||||
#include "BLI_math_angle_types.hh"
|
||||
#include "BLI_math_vector.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_layer.hh"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "ED_mesh.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "mesh_intern.hh"
|
||||
|
||||
namespace blender::ed::mesh {
|
||||
|
||||
static int set_sharpness_by_angle_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const float angle_limit_cos = std::cos(RNA_float_get(op->ptr, "angle"));
|
||||
const bool extend = RNA_boolean_get(op->ptr, "extend");
|
||||
const Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
CTX_data_scene(C), CTX_data_view_layer(C), CTX_wm_view3d(C));
|
||||
|
||||
for (Object *object : objects) {
|
||||
Mesh &mesh = *static_cast<Mesh *>(object->data);
|
||||
BMEditMesh *em = mesh.edit_mesh;
|
||||
|
||||
bool changed = false;
|
||||
BMIter iter;
|
||||
BMEdge *e;
|
||||
BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) {
|
||||
if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
|
||||
continue;
|
||||
}
|
||||
const bool prev_sharp = !BM_elem_flag_test(e, BM_ELEM_SMOOTH);
|
||||
if (extend && prev_sharp) {
|
||||
continue;
|
||||
}
|
||||
BMLoop *l1, *l2;
|
||||
if (!BM_edge_loop_pair(e, &l1, &l2)) {
|
||||
continue;
|
||||
}
|
||||
const float angle_cos = math::dot(float3(l1->f->no), float3(l2->f->no));
|
||||
const bool sharp = angle_cos <= angle_limit_cos;
|
||||
BM_elem_flag_set(e, BM_ELEM_SMOOTH, !sharp);
|
||||
changed = changed || sharp != prev_sharp;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
BKE_editmesh_lnorspace_update(em);
|
||||
DEG_id_tag_update(&mesh.id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, &mesh.id);
|
||||
}
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Set Sharpness by Angle";
|
||||
ot->description = "Set edge sharpness based on the angle between neighboring faces";
|
||||
ot->idname = "MESH_OT_set_sharpness_by_angle";
|
||||
|
||||
ot->exec = set_sharpness_by_angle_exec;
|
||||
ot->poll = ED_operator_editmesh;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
PropertyRNA *prop = RNA_def_float_rotation(ot->srna,
|
||||
"angle",
|
||||
0,
|
||||
nullptr,
|
||||
math::AngleRadian::from_degree(0.01f).radian(),
|
||||
math::AngleRadian::from_degree(180.0f).radian(),
|
||||
"Angle",
|
||||
"",
|
||||
math::AngleRadian::from_degree(1.0f).radian(),
|
||||
math::AngleRadian::from_degree(180.0f).radian());
|
||||
RNA_def_property_float_default(prop, math::AngleRadian::from_degree(30.0f).radian());
|
||||
|
||||
RNA_def_boolean(ot->srna,
|
||||
"extend",
|
||||
false,
|
||||
"Extend",
|
||||
"Add new sharp edges without clearing existing sharp edges");
|
||||
}
|
||||
|
||||
} // namespace blender::ed::mesh
|
||||
@@ -256,6 +256,9 @@ void MESH_OT_delete_loose(wmOperatorType *ot);
|
||||
void MESH_OT_edge_collapse(wmOperatorType *ot);
|
||||
void MESH_OT_faces_shade_smooth(wmOperatorType *ot);
|
||||
void MESH_OT_faces_shade_flat(wmOperatorType *ot);
|
||||
namespace blender::ed::mesh {
|
||||
void MESH_OT_set_sharpness_by_angle(wmOperatorType *ot);
|
||||
}
|
||||
void MESH_OT_split(wmOperatorType *ot);
|
||||
void MESH_OT_edge_rotate(wmOperatorType *ot);
|
||||
void MESH_OT_hide(wmOperatorType *ot);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
void ED_operatortypes_mesh()
|
||||
{
|
||||
using namespace blender::ed::mesh;
|
||||
WM_operatortype_append(MESH_OT_select_all);
|
||||
WM_operatortype_append(MESH_OT_select_interior_faces);
|
||||
WM_operatortype_append(MESH_OT_select_more);
|
||||
@@ -98,6 +99,7 @@ void ED_operatortypes_mesh()
|
||||
WM_operatortype_append(MESH_OT_delete_edgeloop);
|
||||
WM_operatortype_append(MESH_OT_faces_shade_smooth);
|
||||
WM_operatortype_append(MESH_OT_faces_shade_flat);
|
||||
WM_operatortype_append(MESH_OT_set_sharpness_by_angle);
|
||||
WM_operatortype_append(MESH_OT_sort_elements);
|
||||
#ifdef WITH_FREESTYLE
|
||||
WM_operatortype_append(MESH_OT_mark_freestyle_face);
|
||||
|
||||
Reference in New Issue
Block a user