Merge remote-tracking branch 'origin/blender-v3.1-release'
This commit is contained in:
@@ -128,9 +128,10 @@ ccl_device float point_radius(KernelGlobals kg, ccl_private const ShaderData *sd
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
float3 dir = make_float3(r, r, r);
|
||||
const float normalized_r = r * (1.0f / M_SQRT3_F);
|
||||
float3 dir = make_float3(normalized_r, normalized_r, normalized_r);
|
||||
object_dir_transform(kg, sd, &dir);
|
||||
return average(dir);
|
||||
return len(dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -67,6 +67,9 @@ CCL_NAMESPACE_BEGIN
|
||||
#ifndef M_SQRT2_F
|
||||
# define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
|
||||
#endif
|
||||
#ifndef M_SQRT3_F
|
||||
# define M_SQRT3_F (1.7320508075688772f) /* sqrt(3) */
|
||||
#endif
|
||||
#ifndef M_LN2_F
|
||||
# define M_LN2_F (0.6931471805599453f) /* ln(2) */
|
||||
#endif
|
||||
|
@@ -24,18 +24,30 @@ void BKE_subsurf_modifier_subdiv_settings_init(struct SubdivSettings *settings,
|
||||
const struct SubsurfModifierData *smd,
|
||||
bool use_render_params);
|
||||
|
||||
bool BKE_subsurf_modifier_use_custom_loop_normals(const struct SubsurfModifierData *smd,
|
||||
const struct Mesh *mesh);
|
||||
|
||||
/**
|
||||
* Return true if GPU subdivision evaluation is disabled by force due to incompatible mesh or
|
||||
* modifier settings. This will only return true if GPU subdivision is enabled in the preferences
|
||||
* and supported by the GPU. It is mainly useful for showing UI messages.
|
||||
*/
|
||||
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(
|
||||
const struct SubsurfModifierData *smd, const struct Mesh *mesh);
|
||||
/**
|
||||
* \param skip_check_is_last: When true, we assume that the modifier passed is the last enabled
|
||||
* modifier in the stack.
|
||||
*/
|
||||
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const struct Scene *scene,
|
||||
const struct Object *ob,
|
||||
const struct Mesh *mesh,
|
||||
const struct SubsurfModifierData *smd,
|
||||
int required_mode,
|
||||
bool skip_check_is_last);
|
||||
|
||||
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const struct Scene *scene,
|
||||
const struct Object *ob,
|
||||
const struct Mesh *mesh,
|
||||
int required_mode);
|
||||
|
||||
extern void (*BKE_subsurf_modifier_free_gpu_cache_cb)(struct Subdiv *subdiv);
|
||||
|
@@ -54,23 +54,20 @@ static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene,
|
||||
return md;
|
||||
}
|
||||
|
||||
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
|
||||
const Object *ob,
|
||||
const SubsurfModifierData *smd,
|
||||
int required_mode,
|
||||
bool skip_check_is_last)
|
||||
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
|
||||
{
|
||||
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
|
||||
return false;
|
||||
}
|
||||
return (smd->flags & eSubsurfModifierFlag_UseCustomNormals) && (mesh->flag & ME_AUTOSMOOTH) &&
|
||||
CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
}
|
||||
|
||||
if (!skip_check_is_last) {
|
||||
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
|
||||
if (md != (const ModifierData *)smd) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool subsurf_modifier_use_autosmooth_or_split_normals(const SubsurfModifierData *smd,
|
||||
const Mesh *mesh)
|
||||
{
|
||||
return (mesh->flag & ME_AUTOSMOOTH) || BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
|
||||
}
|
||||
|
||||
static bool is_subdivision_evaluation_possible_on_gpu(void)
|
||||
{
|
||||
/* Only OpenGL is supported for OpenSubdiv evaluation for now. */
|
||||
if (GPU_backend_get_type() != GPU_BACKEND_OPENGL) {
|
||||
return false;
|
||||
@@ -88,8 +85,52 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfModifierData *smd,
|
||||
const Mesh *mesh)
|
||||
{
|
||||
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
|
||||
/* GPU subdivision is explicitely disabled, so we don't force it. */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_subdivision_evaluation_possible_on_gpu()) {
|
||||
/* The GPU type is not compatible with the subdivision. */
|
||||
return false;
|
||||
}
|
||||
|
||||
return subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh);
|
||||
}
|
||||
|
||||
bool BKE_subsurf_modifier_can_do_gpu_subdiv_ex(const Scene *scene,
|
||||
const Object *ob,
|
||||
const Mesh *mesh,
|
||||
const SubsurfModifierData *smd,
|
||||
int required_mode,
|
||||
bool skip_check_is_last)
|
||||
{
|
||||
if ((U.gpu_flag & USER_GPU_FLAG_SUBDIVISION_EVALUATION) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Deactivate GPU subdivision if autosmooth or custom split normals are used as those are
|
||||
* complicated to support on GPU, and should really be separate workflows. */
|
||||
if (subsurf_modifier_use_autosmooth_or_split_normals(smd, mesh)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!skip_check_is_last) {
|
||||
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
|
||||
if (md != (const ModifierData *)smd) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return is_subdivision_evaluation_possible_on_gpu();
|
||||
}
|
||||
|
||||
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
|
||||
const Object *ob,
|
||||
const Mesh *mesh,
|
||||
int required_mode)
|
||||
{
|
||||
ModifierData *md = modifier_get_last_enabled_for_mode(scene, ob, required_mode);
|
||||
@@ -103,7 +144,7 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
|
||||
}
|
||||
|
||||
return BKE_subsurf_modifier_can_do_gpu_subdiv_ex(
|
||||
scene, ob, (SubsurfModifierData *)md, required_mode, true);
|
||||
scene, ob, mesh, (SubsurfModifierData *)md, required_mode, true);
|
||||
}
|
||||
|
||||
void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = NULL;
|
||||
|
@@ -1712,7 +1712,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
|
||||
|
||||
const int required_mode = BKE_subsurf_modifier_eval_required_mode(DRW_state_is_scene_render(),
|
||||
is_editmode);
|
||||
const bool do_subdivision = BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ob, required_mode);
|
||||
const bool do_subdivision = BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ob, me, required_mode);
|
||||
|
||||
MeshBufferList *mbuflist = &cache->final.buff;
|
||||
|
||||
|
@@ -67,7 +67,6 @@ enum {
|
||||
SHADER_BUFFER_NORMALS_ACCUMULATE,
|
||||
SHADER_BUFFER_NORMALS_FINALIZE,
|
||||
SHADER_PATCH_EVALUATION,
|
||||
SHADER_PATCH_EVALUATION_LIMIT_NORMALS,
|
||||
SHADER_PATCH_EVALUATION_FVAR,
|
||||
SHADER_PATCH_EVALUATION_FACE_DOTS,
|
||||
SHADER_COMP_CUSTOM_DATA_INTERP_1D,
|
||||
@@ -107,7 +106,6 @@ static const char *get_shader_code(int shader_type)
|
||||
return datatoc_common_subdiv_normals_finalize_comp_glsl;
|
||||
}
|
||||
case SHADER_PATCH_EVALUATION:
|
||||
case SHADER_PATCH_EVALUATION_LIMIT_NORMALS:
|
||||
case SHADER_PATCH_EVALUATION_FVAR:
|
||||
case SHADER_PATCH_EVALUATION_FACE_DOTS: {
|
||||
return datatoc_common_subdiv_patch_evaluation_comp_glsl;
|
||||
@@ -159,9 +157,6 @@ static const char *get_shader_name(int shader_type)
|
||||
case SHADER_PATCH_EVALUATION: {
|
||||
return "subdiv patch evaluation";
|
||||
}
|
||||
case SHADER_PATCH_EVALUATION_LIMIT_NORMALS: {
|
||||
return "subdiv patch evaluation limit normals";
|
||||
}
|
||||
case SHADER_PATCH_EVALUATION_FVAR: {
|
||||
return "subdiv patch evaluation face-varying";
|
||||
}
|
||||
@@ -199,13 +194,7 @@ static GPUShader *get_patch_evaluation_shader(int shader_type)
|
||||
const char *compute_code = get_shader_code(shader_type);
|
||||
|
||||
const char *defines = nullptr;
|
||||
if (shader_type == SHADER_PATCH_EVALUATION_LIMIT_NORMALS) {
|
||||
defines =
|
||||
"#define OSD_PATCH_BASIS_GLSL\n"
|
||||
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
|
||||
"#define LIMIT_NORMALS\n";
|
||||
}
|
||||
else if (shader_type == SHADER_PATCH_EVALUATION_FVAR) {
|
||||
if (shader_type == SHADER_PATCH_EVALUATION_FVAR) {
|
||||
defines =
|
||||
"#define OSD_PATCH_BASIS_GLSL\n"
|
||||
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
|
||||
@@ -246,7 +235,6 @@ static GPUShader *get_subdiv_shader(int shader_type, const char *defines)
|
||||
{
|
||||
if (ELEM(shader_type,
|
||||
SHADER_PATCH_EVALUATION,
|
||||
SHADER_PATCH_EVALUATION_LIMIT_NORMALS,
|
||||
SHADER_PATCH_EVALUATION_FVAR,
|
||||
SHADER_PATCH_EVALUATION_FACE_DOTS)) {
|
||||
return get_patch_evaluation_shader(shader_type);
|
||||
@@ -1194,9 +1182,7 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache,
|
||||
GPU_compute_dispatch(shader, dispatch_rx, dispatch_ry, 1);
|
||||
}
|
||||
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *pos_nor,
|
||||
const bool do_limit_normals)
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_nor)
|
||||
{
|
||||
Subdiv *subdiv = cache->subdiv;
|
||||
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
|
||||
@@ -1221,8 +1207,7 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
||||
get_patch_param_format());
|
||||
evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
|
||||
|
||||
GPUShader *shader = get_patch_evaluation_shader(
|
||||
do_limit_normals ? SHADER_PATCH_EVALUATION_LIMIT_NORMALS : SHADER_PATCH_EVALUATION);
|
||||
GPUShader *shader = get_patch_evaluation_shader(SHADER_PATCH_EVALUATION);
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
GPU_vertbuf_bind_as_ssbo(src_buffer, 0);
|
||||
@@ -1394,6 +1379,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *pos_nor,
|
||||
GPUVertBuf *face_adjacency_offsets,
|
||||
GPUVertBuf *face_adjacency_lists,
|
||||
GPUVertBuf *vertex_loop_map,
|
||||
GPUVertBuf *vertex_normals)
|
||||
{
|
||||
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_NORMALS_ACCUMULATE, nullptr);
|
||||
@@ -1404,6 +1390,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
||||
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(face_adjacency_offsets, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(face_adjacency_lists, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vertex_loop_map, binding_point++);
|
||||
GPU_vertbuf_bind_as_ssbo(vertex_normals, binding_point++);
|
||||
|
||||
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_verts);
|
||||
@@ -1851,8 +1838,6 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
|
||||
draw_cache->subdiv = subdiv;
|
||||
draw_cache->optimal_display = optimal_display;
|
||||
draw_cache->num_subdiv_triangles = tris_count_from_number_of_loops(draw_cache->num_subdiv_loops);
|
||||
/* We can only evaluate limit normals if the patches are adaptive. */
|
||||
draw_cache->do_limit_normals = settings.is_adaptive;
|
||||
|
||||
draw_cache->use_custom_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
|
||||
(mesh_eval->flag & ME_AUTOSMOOTH) &&
|
||||
|
@@ -51,7 +51,6 @@ typedef struct DRWSubdivCache {
|
||||
struct BMesh *bm;
|
||||
struct Subdiv *subdiv;
|
||||
bool optimal_display;
|
||||
bool do_limit_normals;
|
||||
bool use_custom_loop_normals;
|
||||
|
||||
/* Coordinates used to evaluate patches for UVs, positions, and normals. */
|
||||
@@ -165,6 +164,7 @@ void draw_subdiv_accumulate_normals(const DRWSubdivCache *cache,
|
||||
struct GPUVertBuf *pos_nor,
|
||||
struct GPUVertBuf *face_adjacency_offsets,
|
||||
struct GPUVertBuf *face_adjacency_lists,
|
||||
struct GPUVertBuf *vertex_loop_map,
|
||||
struct GPUVertBuf *vertex_normals);
|
||||
|
||||
void draw_subdiv_finalize_normals(const DRWSubdivCache *cache,
|
||||
@@ -176,9 +176,7 @@ void draw_subdiv_finalize_custom_normals(const DRWSubdivCache *cache,
|
||||
GPUVertBuf *src_custom_normals,
|
||||
GPUVertBuf *pos_nor);
|
||||
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
|
||||
struct GPUVertBuf *pos_nor,
|
||||
bool do_limit_normals);
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, struct GPUVertBuf *pos_nor);
|
||||
|
||||
void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
|
||||
struct GPUVertBuf *src_data,
|
||||
|
@@ -217,14 +217,12 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
const bool do_limit_normals = subdiv_cache->do_limit_normals &&
|
||||
!subdiv_cache->use_custom_loop_normals;
|
||||
|
||||
/* Initialize the vertex buffer, it was already allocated. */
|
||||
GPU_vertbuf_init_build_on_device(
|
||||
vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, vbo, do_limit_normals);
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, vbo);
|
||||
|
||||
if (subdiv_cache->use_custom_loop_normals) {
|
||||
Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
@@ -250,7 +248,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
GPU_vertbuf_discard(src_custom_normals);
|
||||
GPU_vertbuf_discard(dst_custom_normals);
|
||||
}
|
||||
else if (!do_limit_normals) {
|
||||
else {
|
||||
/* We cannot evaluate vertex normals using the limit surface, so compute them manually. */
|
||||
GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
|
||||
subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
|
||||
@@ -263,6 +261,7 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
vbo,
|
||||
subdiv_cache->subdiv_vertex_face_adjacency_offsets,
|
||||
subdiv_cache->subdiv_vertex_face_adjacency,
|
||||
subdiv_loop_subdiv_vert_index,
|
||||
vertex_normals);
|
||||
|
||||
draw_subdiv_finalize_normals(subdiv_cache, vertex_normals, subdiv_loop_subdiv_vert_index, vbo);
|
||||
|
@@ -140,6 +140,13 @@ void set_vertex_nor(inout PosNorLoop vertex_data, vec3 nor)
|
||||
set_vertex_nor(vertex_data, nor, 0);
|
||||
}
|
||||
|
||||
void add_newell_cross_v3_v3v3(inout vec3 n, vec3 v_prev, vec3 v_curr)
|
||||
{
|
||||
n[0] += (v_prev[1] - v_curr[1]) * (v_prev[2] + v_curr[2]);
|
||||
n[1] += (v_prev[2] - v_curr[2]) * (v_prev[0] + v_curr[0]);
|
||||
n[2] += (v_prev[0] - v_curr[0]) * (v_prev[1] + v_curr[1]);
|
||||
}
|
||||
|
||||
#define ORIGINDEX_NONE -1
|
||||
|
||||
#ifdef SUBDIV_POLYGON_OFFSET
|
||||
|
@@ -16,11 +16,33 @@ layout(std430, binding = 2) readonly buffer faceAdjacencyLists
|
||||
uint face_adjacency_lists[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 3) writeonly buffer vertexNormals
|
||||
layout(std430, binding = 3) readonly buffer vertexLoopMap
|
||||
{
|
||||
uint vert_loop_map[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 4) writeonly buffer vertexNormals
|
||||
{
|
||||
vec3 normals[];
|
||||
};
|
||||
|
||||
void find_prev_and_next_vertex_on_face(
|
||||
uint face_index, uint vertex_index, out uint curr, out uint next, out uint prev)
|
||||
{
|
||||
uint start_loop_index = face_index * 4;
|
||||
|
||||
for (uint i = 0; i < 4; i++) {
|
||||
uint subdiv_vert_index = vert_loop_map[start_loop_index + i];
|
||||
|
||||
if (subdiv_vert_index == vertex_index) {
|
||||
curr = i;
|
||||
next = (i + 1) % 4;
|
||||
prev = (i + 4 - 1) % 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint vertex_index = get_global_invocation_index();
|
||||
@@ -39,18 +61,37 @@ void main()
|
||||
uint adjacent_face = face_adjacency_lists[first_adjacent_face_offset + i];
|
||||
uint start_loop_index = adjacent_face * 4;
|
||||
|
||||
/* Compute face normal. */
|
||||
vec3 adjacent_verts[3];
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
adjacent_verts[j] = get_vertex_pos(pos_nor[start_loop_index + j]);
|
||||
/* Compute the face normal using Newell's method. */
|
||||
vec3 verts[4];
|
||||
for (uint j = 0; j < 4; j++) {
|
||||
verts[j] = get_vertex_pos(pos_nor[start_loop_index + j]);
|
||||
}
|
||||
|
||||
vec3 face_normal = normalize(
|
||||
cross(adjacent_verts[1] - adjacent_verts[0], adjacent_verts[2] - adjacent_verts[0]));
|
||||
accumulated_normal += face_normal;
|
||||
vec3 face_normal = vec3(0.0);
|
||||
add_newell_cross_v3_v3v3(face_normal, verts[0], verts[1]);
|
||||
add_newell_cross_v3_v3v3(face_normal, verts[1], verts[2]);
|
||||
add_newell_cross_v3_v3v3(face_normal, verts[2], verts[3]);
|
||||
add_newell_cross_v3_v3v3(face_normal, verts[3], verts[0]);
|
||||
|
||||
/* Accumulate angle weighted normal. */
|
||||
uint curr_vert = 0;
|
||||
uint next_vert = 0;
|
||||
uint prev_vert = 0;
|
||||
find_prev_and_next_vertex_on_face(
|
||||
adjacent_face, vertex_index, curr_vert, next_vert, prev_vert);
|
||||
|
||||
vec3 curr_co = verts[curr_vert];
|
||||
vec3 prev_co = verts[next_vert];
|
||||
vec3 next_co = verts[prev_vert];
|
||||
|
||||
vec3 edvec_prev = normalize(prev_co - curr_co);
|
||||
vec3 edvec_next = normalize(curr_co - next_co);
|
||||
|
||||
float fac = acos(-dot(edvec_prev, edvec_next));
|
||||
|
||||
accumulated_normal += face_normal * fac;
|
||||
}
|
||||
|
||||
float weight = 1.0 / float(number_of_adjacent_faces);
|
||||
vec3 normal = normalize(accumulated_normal);
|
||||
normals[vertex_index] = normal;
|
||||
}
|
||||
|
@@ -394,12 +394,8 @@ void main()
|
||||
|
||||
evaluate_patches_limits(patch_co.patch_index, uv.x, uv.y, pos, du, dv);
|
||||
|
||||
# if defined(LIMIT_NORMALS)
|
||||
vec3 nor = normalize(cross(du, dv));
|
||||
# else
|
||||
/* This will be computed later. */
|
||||
vec3 nor = vec3(0.0);
|
||||
# endif
|
||||
|
||||
int origindex = input_vert_origindex[loop_index];
|
||||
uint flag = 0;
|
||||
|
@@ -38,13 +38,18 @@ void main()
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Face is flat shaded, compute flat face normal from an inscribed triangle. */
|
||||
vec3 verts[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
verts[i] = get_vertex_pos(pos_nor[start_loop_index + i]);
|
||||
}
|
||||
vec3 v0 = get_vertex_pos(pos_nor[start_loop_index + 0]);
|
||||
vec3 v1 = get_vertex_pos(pos_nor[start_loop_index + 1]);
|
||||
vec3 v2 = get_vertex_pos(pos_nor[start_loop_index + 2]);
|
||||
vec3 v3 = get_vertex_pos(pos_nor[start_loop_index + 3]);
|
||||
|
||||
vec3 face_normal = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
|
||||
vec3 face_normal = vec3(0.0);
|
||||
add_newell_cross_v3_v3v3(face_normal, v0, v1);
|
||||
add_newell_cross_v3_v3v3(face_normal, v1, v2);
|
||||
add_newell_cross_v3_v3v3(face_normal, v2, v3);
|
||||
add_newell_cross_v3_v3v3(face_normal, v3, v0);
|
||||
|
||||
face_normal = normalize(face_normal);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output_lnor[start_loop_index + i] = face_normal;
|
||||
}
|
||||
|
@@ -234,7 +234,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
||||
* assigned at this stage of modifier stack evaluation. */
|
||||
const bool is_editmode = (mesh->edit_mesh != NULL);
|
||||
const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode);
|
||||
if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(scene, ctx->object, smd, required_mode, false)) {
|
||||
if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(
|
||||
scene, ctx->object, mesh, smd, required_mode, false)) {
|
||||
subdiv_cache_cpu_evaluation_settings(ctx, mesh, smd);
|
||||
return result;
|
||||
}
|
||||
@@ -246,9 +247,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
|
||||
/* Happens on bad topology, but also on empty input mesh. */
|
||||
return result;
|
||||
}
|
||||
const bool use_clnors = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
|
||||
(mesh->flag & ME_AUTOSMOOTH) &&
|
||||
CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
|
||||
const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
|
||||
if (use_clnors) {
|
||||
/* If custom normals are present and the option is turned on calculate the split
|
||||
* normals and clear flag so the normals get interpolated to the result mesh. */
|
||||
@@ -412,6 +411,13 @@ static void panel_draw(const bContext *C, Panel *panel)
|
||||
|
||||
uiItemR(layout, ptr, "show_only_control_edges", 0, NULL, ICON_NONE);
|
||||
|
||||
SubsurfModifierData *smd = ptr->data;
|
||||
Object *ob = ob_ptr.data;
|
||||
Mesh *mesh = ob->data;
|
||||
if (BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(smd, mesh)) {
|
||||
uiItemL(layout, "Autosmooth or custom normals detected, disabling GPU subdivision", ICON_INFO);
|
||||
}
|
||||
|
||||
modifier_panel_end(layout, ptr);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user