Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_subdivision.cc')
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc131
1 files changed, 80 insertions, 51 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index a0c7e064e00..cde2b59ea23 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -39,10 +39,10 @@
#include "opensubdiv_evaluator_capi.h"
#include "opensubdiv_topology_refiner_capi.h"
-#include "draw_cache_extract.h"
+#include "draw_cache_extract.hh"
#include "draw_cache_impl.h"
#include "draw_cache_inline.h"
-#include "mesh_extractors/extract_mesh.h"
+#include "mesh_extractors/extract_mesh.hh"
extern "C" char datatoc_common_subdiv_custom_data_interp_comp_glsl[];
extern "C" char datatoc_common_subdiv_ibo_lines_comp_glsl[];
@@ -221,7 +221,7 @@ static GPUShader *get_patch_evaluation_shader(int shader_type)
"#define OSD_PATCH_BASIS_GLSL\n"
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
"#define FDOTS_EVALUATION\n"
- "#define FOTS_NORMALS\n";
+ "#define FDOTS_NORMALS\n";
}
else if (shader_type == SHADER_PATCH_EVALUATION_ORCO) {
defines =
@@ -575,6 +575,7 @@ static void draw_subdiv_free_edit_mode_cache(DRWSubdivCache *cache)
void draw_subdiv_cache_free(DRWSubdivCache *cache)
{
GPU_VERTBUF_DISCARD_SAFE(cache->patch_coords);
+ GPU_VERTBUF_DISCARD_SAFE(cache->corner_patch_coords);
GPU_VERTBUF_DISCARD_SAFE(cache->face_ptex_offset_buffer);
GPU_VERTBUF_DISCARD_SAFE(cache->subdiv_polygon_offset_buffer);
GPU_VERTBUF_DISCARD_SAFE(cache->extra_coarse_face_data);
@@ -780,7 +781,7 @@ struct DRWCacheBuildingContext {
DRWSubdivCache *cache;
- /* Pointers into DRWSubdivCache buffers for easier access during traversal. */
+ /* Pointers into #DRWSubdivCache buffers for easier access during traversal. */
CompressedPatchCoord *patch_coords;
int *subdiv_loop_vert_index;
int *subdiv_loop_subdiv_vert_index;
@@ -792,9 +793,9 @@ struct DRWCacheBuildingContext {
int *vert_origindex_map;
int *edge_origindex_map;
- /* Origindex layers from the mesh to directly look up during traversal the origindex from the
- * base mesh for edit data so that we do not have to handle yet another GPU buffer and do this in
- * the shaders. */
+ /* #CD_ORIGINDEX layers from the mesh to directly look up during traversal the original-index
+ * from the base mesh for edit data so that we do not have to handle yet another GPU buffer and
+ * do this in the shaders. */
const int *v_origindex;
const int *e_origindex;
};
@@ -834,6 +835,11 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
cache->patch_coords, get_blender_patch_coords_format(), GPU_USAGE_DYNAMIC);
GPU_vertbuf_data_alloc(cache->patch_coords, cache->num_subdiv_loops);
+ cache->corner_patch_coords = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_with_format_ex(
+ cache->corner_patch_coords, get_blender_patch_coords_format(), GPU_USAGE_DYNAMIC);
+ GPU_vertbuf_data_alloc(cache->corner_patch_coords, cache->num_subdiv_loops);
+
cache->verts_orig_index = GPU_vertbuf_calloc();
GPU_vertbuf_init_with_format_ex(
cache->verts_orig_index, get_origindex_format(), GPU_USAGE_DYNAMIC);
@@ -861,10 +867,10 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
ctx->subdiv_loop_subdiv_edge_index = cache->subdiv_loop_subdiv_edge_index;
ctx->subdiv_loop_poly_index = cache->subdiv_loop_poly_index;
- ctx->v_origindex = static_cast<int *>(
+ ctx->v_origindex = static_cast<const int *>(
CustomData_get_layer(&ctx->coarse_mesh->vdata, CD_ORIGINDEX));
- ctx->e_origindex = static_cast<int *>(
+ ctx->e_origindex = static_cast<const int *>(
CustomData_get_layer(&ctx->coarse_mesh->edata, CD_ORIGINDEX));
if (cache->num_subdiv_verts) {
@@ -1046,14 +1052,10 @@ static void build_vertex_face_adjacency_maps(DRWSubdivCache *cache)
static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
Subdiv *subdiv,
Mesh *mesh_eval,
- const Scene *scene,
- const SubsurfModifierData *smd,
- const bool is_final_render)
+ const SubsurfRuntimeData *runtime_data)
{
- const int requested_levels = (is_final_render) ? smd->renderLevels : smd->levels;
- const int level = get_render_subsurf_level(&scene->r, requested_levels, is_final_render);
SubdivToMeshSettings to_mesh_settings;
- to_mesh_settings.resolution = (1 << level) + 1;
+ to_mesh_settings.resolution = runtime_data->resolution;
to_mesh_settings.use_optimal_display = false;
if (cache->resolution != to_mesh_settings.resolution) {
@@ -1124,6 +1126,31 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
cache->resolution = to_mesh_settings.resolution;
cache->num_coarse_poly = mesh_eval->totpoly;
+ /* To avoid floating point precision issues when evaluating patches at patch boundaries,
+ * ensure that all loops sharing a vertex use the same patch coordinate. This could cause
+ * the mesh to not be watertight, leading to shadowing artifacts (see T97877). */
+ blender::Vector<int> first_loop_index(cache->num_subdiv_verts, -1);
+
+ /* Save coordinates for corners, as attributes may vary for each loop connected to the same
+ * vertex. */
+ memcpy(GPU_vertbuf_get_data(cache->corner_patch_coords),
+ cache_building_context.patch_coords,
+ sizeof(CompressedPatchCoord) * cache->num_subdiv_loops);
+
+ for (int i = 0; i < cache->num_subdiv_loops; i++) {
+ const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i];
+ if (first_loop_index[vertex] != -1) {
+ continue;
+ }
+ first_loop_index[vertex] = i;
+ }
+
+ for (int i = 0; i < cache->num_subdiv_loops; i++) {
+ const int vertex = cache_building_context.subdiv_loop_subdiv_vert_index[i];
+ cache_building_context.patch_coords[i] =
+ cache_building_context.patch_coords[first_loop_index[vertex]];
+ }
+
/* Cleanup. */
MEM_SAFE_FREE(cache_building_context.vert_origindex_map);
MEM_SAFE_FREE(cache_building_context.edge_origindex_map);
@@ -1177,8 +1204,8 @@ struct DRWSubdivUboStorage {
* of out of bond accesses as compute dispatch are of fixed size. */
uint total_dispatch_size;
- int _pad0;
- int _pad2;
+ int is_edit_mode;
+ int use_hide;
int _pad3;
};
@@ -1209,6 +1236,8 @@ static void draw_subdiv_init_ubo_storage(const DRWSubdivCache *cache,
ubo->coarse_face_hidden_mask = SUBDIV_COARSE_FACE_FLAG_HIDDEN_MASK;
ubo->coarse_face_loopstart_mask = SUBDIV_COARSE_FACE_LOOP_START_MASK;
ubo->total_dispatch_size = total_dispatch_size;
+ ubo->is_edit_mode = cache->is_edit_mode;
+ ubo->use_hide = cache->use_hide;
}
static void draw_subdiv_ubo_update_and_bind(const DRWSubdivCache *cache,
@@ -1405,7 +1434,7 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(src_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->gpu_patch_map.patch_map_handles, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->gpu_patch_map.patch_map_quadtree, binding_point++);
- GPU_vertbuf_bind_as_ssbo(cache->patch_coords, binding_point++);
+ GPU_vertbuf_bind_as_ssbo(cache->corner_patch_coords, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->verts_orig_index, binding_point++);
GPU_vertbuf_bind_as_ssbo(patch_arrays_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
@@ -1441,6 +1470,11 @@ void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
{
GPUShader *shader = nullptr;
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
if (dimensions == 1) {
shader = get_subdiv_shader(SHADER_COMP_CUSTOM_DATA_INTERP_1D,
"#define SUBDIV_POLYGON_OFFSET\n"
@@ -1480,7 +1514,7 @@ void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(cache->subdiv_polygon_offset_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(src_data, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->face_ptex_offset_buffer, binding_point++);
- GPU_vertbuf_bind_as_ssbo(cache->patch_coords, binding_point++);
+ GPU_vertbuf_bind_as_ssbo(cache->corner_patch_coords, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->extra_coarse_face_data, binding_point++);
GPU_vertbuf_bind_as_ssbo(dst_data, binding_point++);
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
@@ -1806,6 +1840,7 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache *cache,
GPU_vertbuf_bind_as_ssbo(cache->subdiv_polygon_offset_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
GPU_vertbuf_bind_as_ssbo(cache->extra_coarse_face_data, binding_point++);
+ GPU_vertbuf_bind_as_ssbo(cache->verts_orig_index, binding_point++);
/* Outputs */
GPU_vertbuf_bind_as_ssbo(lnor, binding_point++);
@@ -1974,10 +2009,9 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache *cache,
MEM_freeN(per_polygon_mat_offset);
}
-static bool draw_subdiv_create_requested_buffers(const Scene *scene,
- Object *ob,
+static bool draw_subdiv_create_requested_buffers(Object *ob,
Mesh *mesh,
- struct MeshBatchCache *batch_cache,
+ MeshBatchCache *batch_cache,
MeshBufferCache *mbc,
const bool is_editmode,
const bool is_paint_mode,
@@ -1989,16 +2023,10 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
const bool use_hide,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
- SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData *>(
- BKE_modifiers_findby_session_uuid(ob, &mesh->runtime.subsurf_session_uuid));
- BLI_assert(smd);
-
- const bool is_final_render = DRW_state_is_scene_render();
-
- SubdivSettings settings;
- BKE_subsurf_modifier_subdiv_settings_init(&settings, smd, is_final_render);
+ SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data;
+ BLI_assert(runtime_data && runtime_data->has_gpu_subdiv);
- if (settings.level == 0) {
+ if (runtime_data->settings.level == 0) {
return false;
}
@@ -2009,9 +2037,7 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
bm = mesh->edit_mesh->bm;
}
- BKE_subsurf_modifier_ensure_runtime(smd);
-
- Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(smd, &settings, mesh_eval, true);
+ Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, mesh_eval, true);
if (!subdiv) {
return false;
}
@@ -2019,7 +2045,7 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
draw_subdiv_invalidate_evaluator_for_orco(subdiv, mesh_eval);
if (!BKE_subdiv_eval_begin_from_mesh(
- subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GLSL_COMPUTE, evaluator_cache)) {
+ subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GPU, evaluator_cache)) {
/* This could happen in two situations:
* - OpenSubdiv is disabled.
* - Something totally bad happened, and OpenSubdiv rejected our
@@ -2032,13 +2058,13 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
}
DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache);
- if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, scene, smd, is_final_render)) {
+ if (!draw_subdiv_build_cache(draw_cache, subdiv, mesh_eval, runtime_data)) {
return false;
}
/* Edges which do not come from coarse edges should not be drawn in edit mode, only in object
* mode when optimal display in turned off. */
- const bool optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges) || is_editmode;
+ const bool optimal_display = runtime_data->use_optimal_display || is_editmode;
draw_cache->bm = bm;
draw_cache->mesh = mesh_eval;
@@ -2046,14 +2072,13 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
draw_cache->optimal_display = optimal_display;
draw_cache->num_subdiv_triangles = tris_count_from_number_of_loops(draw_cache->num_subdiv_loops);
- /* Copy topology information for stats display. Use `mesh` directly, as `mesh_eval` could be the
- * edit mesh. */
- mesh->runtime.subsurf_totvert = draw_cache->num_subdiv_verts;
- mesh->runtime.subsurf_totedge = draw_cache->num_subdiv_edges;
- mesh->runtime.subsurf_totpoly = draw_cache->num_subdiv_quads;
- mesh->runtime.subsurf_totloop = draw_cache->num_subdiv_loops;
+ /* Copy topology information for stats display. */
+ runtime_data->stats_totvert = draw_cache->num_subdiv_verts;
+ runtime_data->stats_totedge = draw_cache->num_subdiv_edges;
+ runtime_data->stats_totpoly = draw_cache->num_subdiv_quads;
+ runtime_data->stats_totloop = draw_cache->num_subdiv_loops;
- draw_cache->use_custom_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
+ draw_cache->use_custom_loop_normals = (runtime_data->use_loop_normals) &&
(mesh_eval->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&mesh_eval->ldata,
CD_CUSTOMLOOPNORMAL);
@@ -2065,10 +2090,16 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
MeshRenderData *mr = mesh_render_data_create(
ob, mesh, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
mr->use_hide = use_hide;
+ draw_cache->use_hide = use_hide;
+
+ /* Used for setting loop normals flags. Mapped extraction is only used during edit mode.
+ * See comments in #extract_lnor_iter_poly_mesh.
+ */
+ draw_cache->is_edit_mode = mr->edit_bmesh != nullptr;
draw_subdiv_cache_update_extra_coarse_face_data(draw_cache, mesh_eval, mr);
- mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, mr);
+ blender::draw::mesh_buffer_cache_create_requested_subdiv(batch_cache, mbc, draw_cache, mr);
mesh_render_data_free(mr);
@@ -2175,10 +2206,9 @@ blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWS
static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr;
-void DRW_create_subdivision(const Scene *scene,
- Object *ob,
+void DRW_create_subdivision(Object *ob,
Mesh *mesh,
- struct MeshBatchCache *batch_cache,
+ MeshBatchCache *batch_cache,
MeshBufferCache *mbc,
const bool is_editmode,
const bool is_paint_mode,
@@ -2190,7 +2220,7 @@ void DRW_create_subdivision(const Scene *scene,
const bool use_hide)
{
if (g_evaluator_cache == nullptr) {
- g_evaluator_cache = openSubdiv_createEvaluatorCache(OPENSUBDIV_EVALUATOR_GLSL_COMPUTE);
+ g_evaluator_cache = openSubdiv_createEvaluatorCache(OPENSUBDIV_EVALUATOR_GPU);
}
#undef TIME_SUBDIV
@@ -2199,8 +2229,7 @@ void DRW_create_subdivision(const Scene *scene,
const double begin_time = PIL_check_seconds_timer();
#endif
- if (!draw_subdiv_create_requested_buffers(scene,
- ob,
+ if (!draw_subdiv_create_requested_buffers(ob,
mesh,
batch_cache,
mbc,