Mesh: Split paint overlay flag data from normals buffers
For paint modes the selection and visibility were encoded in in the W component of the normals. Separating the normals into a separate vertex buffer, though it increases memory usage a bit in those paint modes, means the status doesn't need to be computed outside of paint modes, and the whole system becomes less convoluted and easier to optimize. The particular optimization I have in mind is better caching of vertex buffers, which gets much more complicated when the normals VBO contains data like selection and visibility and depends on the paint mode. Internally, a there are now three mesh draw batches that are specific to the paint overlay. The GPU subdivision normals buffer is now just three components rather than 4 components. Pull Request: https://projects.blender.org/blender/blender/pulls/140156
This commit is contained in:
@@ -49,6 +49,7 @@ set(SRC
|
||||
intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_orco.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_pos.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_paint_overlay_flag.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
|
||||
intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc
|
||||
@@ -541,12 +542,12 @@ set(GLSL_SRC
|
||||
intern/shaders/subdiv_ibo_tris_comp.glsl
|
||||
intern/shaders/subdiv_lib.glsl
|
||||
intern/shaders/subdiv_normals_accumulate_comp.glsl
|
||||
intern/shaders/subdiv_normals_finalize_comp.glsl
|
||||
intern/shaders/subdiv_patch_evaluation_comp.glsl
|
||||
intern/shaders/subdiv_vbo_edge_fac_comp.glsl
|
||||
intern/shaders/subdiv_vbo_edituv_strech_angle_comp.glsl
|
||||
intern/shaders/subdiv_vbo_edituv_strech_area_comp.glsl
|
||||
intern/shaders/subdiv_vbo_lnor_comp.glsl
|
||||
intern/shaders/subdiv_vbo_paint_overlay_flag_comp.glsl
|
||||
intern/shaders/subdiv_vbo_sculpt_data_comp.glsl
|
||||
intern/shaders/draw_aabb_lib.glsl
|
||||
intern/shaders/draw_colormanagement_lib.glsl
|
||||
|
||||
@@ -233,16 +233,16 @@ class Paints : Overlay {
|
||||
const bool in_texture_paint_mode = state.ctx_mode == CTX_MODE_PAINT_TEXTURE;
|
||||
|
||||
if ((use_face_selection || show_wires_) && !in_texture_paint_mode) {
|
||||
gpu::Batch *geom = DRW_cache_mesh_surface_edges_get(ob_ref.object);
|
||||
gpu::Batch *geom = DRW_cache_mesh_paint_overlay_edges_get(ob_ref.object);
|
||||
paint_region_edge_ps_->push_constant("use_select", use_face_selection);
|
||||
paint_region_edge_ps_->draw(geom, manager.unique_handle(ob_ref));
|
||||
}
|
||||
if (use_face_selection) {
|
||||
gpu::Batch *geom = DRW_cache_mesh_surface_get(ob_ref.object);
|
||||
gpu::Batch *geom = DRW_cache_mesh_paint_overlay_surface_get(ob_ref.object);
|
||||
paint_region_face_ps_->draw(geom, manager.unique_handle(ob_ref));
|
||||
}
|
||||
if (use_vert_selection && !in_texture_paint_mode) {
|
||||
gpu::Batch *geom = DRW_cache_mesh_all_verts_get(ob_ref.object);
|
||||
gpu::Batch *geom = DRW_cache_mesh_paint_overlay_verts_get(ob_ref.object);
|
||||
paint_region_vert_ps_->draw(geom, manager.unique_handle(ob_ref));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
GPU_SHADER_CREATE_INFO(overlay_paint_face)
|
||||
DO_STATIC_COMPILATION()
|
||||
VERTEX_IN(0, float3, pos)
|
||||
VERTEX_IN(1, float4, nor) /* Select flag on the 4th component. */
|
||||
VERTEX_IN(1, int, paint_overlay_flag)
|
||||
PUSH_CONSTANT(float4, ucolor)
|
||||
FRAGMENT_OUT(0, float4, frag_color)
|
||||
VERTEX_SOURCE("overlay_paint_face_vert.glsl")
|
||||
@@ -48,7 +48,7 @@ GPU_SHADER_INTERFACE_END()
|
||||
GPU_SHADER_CREATE_INFO(overlay_paint_point)
|
||||
DO_STATIC_COMPILATION()
|
||||
VERTEX_IN(0, float3, pos)
|
||||
VERTEX_IN(1, float4, nor) /* Select flag on the 4th component. */
|
||||
VERTEX_IN(1, int, paint_overlay_flag)
|
||||
VERTEX_OUT(overlay_overlay_paint_point_iface)
|
||||
FRAGMENT_OUT(0, float4, frag_color)
|
||||
VERTEX_SOURCE("overlay_paint_point_vert.glsl")
|
||||
@@ -151,7 +151,7 @@ GPU_SHADER_INTERFACE_END()
|
||||
GPU_SHADER_CREATE_INFO(overlay_paint_wire)
|
||||
DO_STATIC_COMPILATION()
|
||||
VERTEX_IN(0, float3, pos)
|
||||
VERTEX_IN(1, float4, nor) /* flag stored in w */
|
||||
VERTEX_IN(1, int, paint_overlay_flag)
|
||||
VERTEX_OUT(overlay_paint_wire_iface)
|
||||
PUSH_CONSTANT(bool, use_select)
|
||||
FRAGMENT_OUT(0, float4, frag_color)
|
||||
|
||||
@@ -20,8 +20,8 @@ void main()
|
||||
gl_Position.z -= 5e-5f;
|
||||
#endif
|
||||
|
||||
bool is_select = (nor.w > 0.0f);
|
||||
bool is_hidden = (nor.w < 0.0f);
|
||||
bool is_select = (paint_overlay_flag > 0);
|
||||
bool is_hidden = (paint_overlay_flag < 0);
|
||||
|
||||
/* Don't draw faces that are selected. */
|
||||
if (is_hidden || is_select) {
|
||||
|
||||
@@ -12,8 +12,8 @@ VERTEX_SHADER_CREATE_INFO(overlay_paint_point)
|
||||
|
||||
void main()
|
||||
{
|
||||
bool is_select = (nor.w > 0.0f);
|
||||
bool is_hidden = (nor.w < 0.0f);
|
||||
bool is_select = (paint_overlay_flag > 0);
|
||||
bool is_hidden = (paint_overlay_flag < 0);
|
||||
|
||||
float3 world_pos = drw_point_object_to_world(pos);
|
||||
gl_Position = drw_point_world_to_homogenous(world_pos);
|
||||
@@ -26,7 +26,7 @@ void main()
|
||||
}
|
||||
|
||||
final_color = (is_select) ? float4(1.0f) : theme.colors.wire;
|
||||
final_color.a = nor.w;
|
||||
final_color.a = float(paint_overlay_flag);
|
||||
|
||||
gl_PointSize = theme.sizes.vert * 2.0f;
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ VERTEX_SHADER_CREATE_INFO(overlay_paint_wire)
|
||||
|
||||
void main()
|
||||
{
|
||||
bool is_select = (nor.w > 0.0f) && use_select;
|
||||
bool is_hidden = (nor.w < 0.0f) && use_select;
|
||||
bool is_select = (paint_overlay_flag > 0) && use_select;
|
||||
bool is_hidden = (paint_overlay_flag < 0) && use_select;
|
||||
|
||||
float3 world_pos = drw_point_object_to_world(pos);
|
||||
gl_Position = drw_point_world_to_homogenous(world_pos);
|
||||
|
||||
@@ -167,6 +167,12 @@ gpu::Batch *DRW_cache_mesh_all_verts_get(Object *ob)
|
||||
return DRW_mesh_batch_cache_get_all_verts(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_verts_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
return DRW_mesh_batch_cache_get_paint_overlay_verts(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_mesh_all_edges_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
@@ -192,10 +198,17 @@ gpu::Batch *DRW_cache_mesh_surface_get(Object *ob)
|
||||
return DRW_mesh_batch_cache_get_surface(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_mesh_surface_edges_get(Object *ob)
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_surface_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
return DRW_mesh_batch_cache_get_surface_edges(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
return DRW_mesh_batch_cache_get_paint_overlay_surface(
|
||||
DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_edges_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
return DRW_mesh_batch_cache_get_paint_overlay_edges(DRW_object_get_data_for_drawing<Mesh>(*ob));
|
||||
}
|
||||
|
||||
Span<gpu::Batch *> DRW_cache_mesh_surface_shaded_get(Object *ob,
|
||||
|
||||
@@ -52,11 +52,13 @@ gpu::Batch *DRW_cache_object_face_wireframe_get(const Scene *scene, Object *ob);
|
||||
/* Meshes */
|
||||
|
||||
gpu::Batch *DRW_cache_mesh_all_verts_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_verts_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_all_edges_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_loose_edges_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_edge_detection_get(Object *ob, bool *r_is_manifold);
|
||||
gpu::Batch *DRW_cache_mesh_surface_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_surface_edges_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_surface_get(Object *ob);
|
||||
gpu::Batch *DRW_cache_mesh_paint_overlay_edges_get(Object *ob);
|
||||
/**
|
||||
* Return list of batches with length equal to `max(1, totcol)`.
|
||||
*/
|
||||
|
||||
@@ -109,6 +109,7 @@ enum class VBOType : int8_t {
|
||||
Attr15,
|
||||
AttrViewer,
|
||||
VertexNormal,
|
||||
PaintOverlayFlag,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -177,12 +178,13 @@ struct MeshBatchList {
|
||||
/* Individual edges with face normals. */
|
||||
gpu::Batch *wire_edges;
|
||||
/* Loops around faces. no edges between selected faces */
|
||||
gpu::Batch *wire_loops;
|
||||
/* Same as wire_loops but only has uvs. */
|
||||
gpu::Batch *paint_overlay_wire_loops;
|
||||
gpu::Batch *wire_loops_uvs;
|
||||
gpu::Batch *wire_loops_edituvs;
|
||||
gpu::Batch *sculpt_overlays;
|
||||
gpu::Batch *surface_viewer_attribute;
|
||||
gpu::Batch *paint_overlay_verts;
|
||||
gpu::Batch *paint_overlay_surface;
|
||||
};
|
||||
|
||||
#define MBC_BATCH_LEN (sizeof(MeshBatchList) / sizeof(void *))
|
||||
@@ -216,12 +218,14 @@ enum DRWBatchFlag : uint64_t {
|
||||
MBC_LOOSE_EDGES = (1u << MBC_BATCH_INDEX(loose_edges)),
|
||||
MBC_EDGE_DETECTION = (1u << MBC_BATCH_INDEX(edge_detection)),
|
||||
MBC_WIRE_EDGES = (1u << MBC_BATCH_INDEX(wire_edges)),
|
||||
MBC_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(wire_loops)),
|
||||
MBC_PAINT_OVERLAY_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(paint_overlay_wire_loops)),
|
||||
MBC_WIRE_LOOPS_UVS = (1u << MBC_BATCH_INDEX(wire_loops_uvs)),
|
||||
MBC_WIRE_LOOPS_EDITUVS = (1u << MBC_BATCH_INDEX(wire_loops_edituvs)),
|
||||
MBC_SCULPT_OVERLAYS = (1u << MBC_BATCH_INDEX(sculpt_overlays)),
|
||||
MBC_VIEWER_ATTRIBUTE_OVERLAY = (1u << MBC_BATCH_INDEX(surface_viewer_attribute)),
|
||||
MBC_SURFACE_PER_MAT = (1u << MBC_BATCH_LEN),
|
||||
MBC_PAINT_OVERLAY_VERTS = (1u << MBC_BATCH_INDEX(paint_overlay_verts)),
|
||||
MBC_PAINT_OVERLAY_SURFACE = (uint64_t(1u) << MBC_BATCH_INDEX(paint_overlay_surface)),
|
||||
MBC_SURFACE_PER_MAT = (uint64_t(1u) << MBC_BATCH_LEN),
|
||||
};
|
||||
ENUM_OPERATORS(DRWBatchFlag, MBC_SURFACE_PER_MAT);
|
||||
|
||||
|
||||
@@ -275,6 +275,9 @@ void mesh_buffer_cache_create_requested(TaskGraph & /*task_graph*/,
|
||||
case VBOType::VertexNormal:
|
||||
created_vbos[i] = extract_vert_normals(mr);
|
||||
break;
|
||||
case VBOType::PaintOverlayFlag:
|
||||
created_vbos[i] = extract_paint_overlay_flags(mr);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -411,6 +414,10 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
buffers.ibos.add_new(IBOType::FaceDots, std::move(face_dot_ibo));
|
||||
}
|
||||
}
|
||||
if (vbos_to_create.contains(VBOType::PaintOverlayFlag)) {
|
||||
buffers.vbos.add_new(VBOType::PaintOverlayFlag,
|
||||
extract_paint_overlay_flags_subdiv(mr, subdiv_cache));
|
||||
}
|
||||
if (ibos_to_create.contains(IBOType::LinesPaintMask)) {
|
||||
buffers.ibos.add_new(IBOType::LinesPaintMask,
|
||||
extract_lines_paint_mask_subdiv(mr, subdiv_cache));
|
||||
|
||||
@@ -189,11 +189,13 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
|
||||
bool use_hide);
|
||||
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_all_verts(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_verts(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_all_edges(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_loose_edges(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh &mesh, bool *r_is_manifold);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_surface(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_surface_edges(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_surface(Mesh &mesh);
|
||||
blender::gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_edges(Mesh &mesh);
|
||||
Span<gpu::Batch *> DRW_mesh_batch_cache_get_surface_shaded(Object &object,
|
||||
Mesh &mesh,
|
||||
Span<const GPUMaterial *> materials);
|
||||
|
||||
@@ -595,9 +595,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
|
||||
mesh_batch_cache_discard_uvedit_select(cache);
|
||||
break;
|
||||
case BKE_MESH_BATCH_DIRTY_SELECT_PAINT:
|
||||
/* Paint mode selection flag is packed inside the nor attribute.
|
||||
* Note that it can be slow if auto smooth is enabled. (see #63946) */
|
||||
discard_buffers(cache, {VBOType::CornerNormal}, {IBOType::LinesPaintMask});
|
||||
discard_buffers(cache, {VBOType::PaintOverlayFlag}, {IBOType::LinesPaintMask});
|
||||
break;
|
||||
case BKE_MESH_BATCH_DIRTY_ALL:
|
||||
cache.is_dirty = true;
|
||||
@@ -720,6 +718,13 @@ gpu::Batch *DRW_mesh_batch_cache_get_all_verts(Mesh &mesh)
|
||||
return DRW_batch_request(&cache.batch.all_verts);
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_verts(Mesh &mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
cache.batch_requested |= MBC_PAINT_OVERLAY_VERTS;
|
||||
return DRW_batch_request(&cache.batch.paint_overlay_verts);
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_all_edges(Mesh &mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
@@ -735,6 +740,13 @@ gpu::Batch *DRW_mesh_batch_cache_get_surface(Mesh &mesh)
|
||||
return cache.batch.surface;
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_surface(Mesh &mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
cache.batch_requested |= MBC_PAINT_OVERLAY_SURFACE;
|
||||
return DRW_batch_request(&cache.batch.paint_overlay_surface);
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_loose_edges(Mesh &mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
@@ -1065,11 +1077,11 @@ gpu::Batch *DRW_mesh_batch_cache_get_edituv_wireframe(Object &object, Mesh &mesh
|
||||
return DRW_batch_request(&cache.batch.wire_loops_edituvs);
|
||||
}
|
||||
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_surface_edges(Mesh &mesh)
|
||||
gpu::Batch *DRW_mesh_batch_cache_get_paint_overlay_edges(Mesh &mesh)
|
||||
{
|
||||
MeshBatchCache &cache = *mesh_batch_cache_get(mesh);
|
||||
cache.batch_requested |= MBC_WIRE_LOOPS;
|
||||
return DRW_batch_request(&cache.batch.wire_loops);
|
||||
cache.batch_requested |= MBC_PAINT_OVERLAY_WIRE_LOOPS;
|
||||
return DRW_batch_request(&cache.batch.paint_overlay_wire_loops);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -1321,6 +1333,14 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
|
||||
}
|
||||
batch_info.append(std::move(batch));
|
||||
}
|
||||
if (batches_to_create & MBC_PAINT_OVERLAY_SURFACE) {
|
||||
BatchCreateData batch{*cache.batch.paint_overlay_surface,
|
||||
GPU_PRIM_TRIS,
|
||||
list,
|
||||
IBOType::Tris,
|
||||
{VBOType::Position, VBOType::PaintOverlayFlag}};
|
||||
batch_info.append(std::move(batch));
|
||||
}
|
||||
if (batches_to_create & MBC_VIEWER_ATTRIBUTE_OVERLAY) {
|
||||
batch_info.append({*cache.batch.surface_viewer_attribute,
|
||||
GPU_PRIM_TRIS,
|
||||
@@ -1329,11 +1349,15 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
|
||||
{VBOType::Position, VBOType::AttrViewer}});
|
||||
}
|
||||
if (batches_to_create & MBC_ALL_VERTS) {
|
||||
batch_info.append({*cache.batch.all_verts,
|
||||
batch_info.append(
|
||||
{*cache.batch.all_verts, GPU_PRIM_POINTS, list, std::nullopt, {VBOType::Position}});
|
||||
}
|
||||
if (batches_to_create & MBC_PAINT_OVERLAY_VERTS) {
|
||||
batch_info.append({*cache.batch.paint_overlay_verts,
|
||||
GPU_PRIM_POINTS,
|
||||
list,
|
||||
std::nullopt,
|
||||
{VBOType::Position, VBOType::CornerNormal}});
|
||||
{VBOType::Position, VBOType::PaintOverlayFlag}});
|
||||
}
|
||||
if (batches_to_create & MBC_SCULPT_OVERLAYS) {
|
||||
batch_info.append({*cache.batch.sculpt_overlays,
|
||||
@@ -1367,12 +1391,12 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
|
||||
IBOType::Tris,
|
||||
{VBOType::Position, VBOType::CornerNormal, VBOType::VertexGroupWeight}});
|
||||
}
|
||||
if (batches_to_create & MBC_WIRE_LOOPS) {
|
||||
batch_info.append({*cache.batch.wire_loops,
|
||||
if (batches_to_create & MBC_PAINT_OVERLAY_WIRE_LOOPS) {
|
||||
batch_info.append({*cache.batch.paint_overlay_wire_loops,
|
||||
GPU_PRIM_LINES,
|
||||
list,
|
||||
IBOType::LinesPaintMask,
|
||||
{VBOType::Position, VBOType::CornerNormal}});
|
||||
{VBOType::Position, VBOType::PaintOverlayFlag}});
|
||||
}
|
||||
if (batches_to_create & MBC_WIRE_EDGES) {
|
||||
batch_info.append({*cache.batch.wire_edges,
|
||||
|
||||
@@ -1372,7 +1372,6 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache &cache,
|
||||
GPU_vertbuf_bind_as_ssbo(pos, LOOP_NORMALS_POS_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data,
|
||||
LOOP_NORMALS_EXTRA_COARSE_FACE_DATA_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, LOOP_NORMALS_INPUT_VERT_ORIG_INDEX_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(vert_normals, LOOP_NORMALS_VERT_NORMALS_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(subdiv_corner_verts, LOOP_NORMALS_VERTEX_LOOP_MAP_BUF_SLOT);
|
||||
|
||||
@@ -1388,28 +1387,27 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache &cache,
|
||||
GPU_shader_unbind();
|
||||
}
|
||||
|
||||
void draw_subdiv_build_lnor_buffer_from_custom_normals(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf &interpolated_custom_normals,
|
||||
gpu::VertBuf &lnor)
|
||||
void draw_subdiv_build_paint_overlay_flag_buffer(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf &subdiv_corner_verts,
|
||||
gpu::VertBuf &flags)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_face_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
GPUShader *shader = DRW_shader_subdiv_get(SubdivShaderType::BUFFER_LNOR);
|
||||
GPUShader *shader = DRW_shader_subdiv_get(SubdivShaderType::BUFFER_PAINT_OVERLAY_FLAG);
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
/* Inputs */
|
||||
GPU_vertbuf_bind_as_ssbo(cache.subdiv_face_offset_buffer, SUBDIV_FACE_OFFSET_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(cache.extra_coarse_face_data,
|
||||
NORMALS_FINALIZE_EXTRA_COARSE_FACE_DATA_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(&interpolated_custom_normals, NORMALS_FINALIZE_CUSTOM_NORMALS_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index,
|
||||
NORMALS_FINALIZE_INPUT_VERT_ORIG_INDEX_BUF_SLOT);
|
||||
PAINT_OVERLAY_EXTRA_COARSE_FACE_DATA_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(cache.verts_orig_index, PAINT_OVERLAY_EXTRA_INPUT_VERT_ORIG_INDEX_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(&subdiv_corner_verts, PAINT_OVERLAY_FLAG_VERTEX_LOOP_MAP_BUF_SLOT);
|
||||
|
||||
/* Outputs */
|
||||
GPU_vertbuf_bind_as_ssbo(&lnor, NORMALS_FINALIZE_OUTPUT_LNOR_BUF_SLOT);
|
||||
GPU_vertbuf_bind_as_ssbo(&flags, PAINT_OVERLAY_OUTPUT_FLAG_SLOT);
|
||||
|
||||
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache.num_subdiv_quads);
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ static blender::StringRefNull get_subdiv_shader_info_name(SubdivShaderType shade
|
||||
case SubdivShaderType::BUFFER_NORMALS_ACCUMULATE:
|
||||
return "subdiv_normals_accumulate";
|
||||
|
||||
case SubdivShaderType::BUFFER_CUSTOM_NORMALS_FINALIZE:
|
||||
return "subdiv_custom_normals_finalize";
|
||||
case SubdivShaderType::BUFFER_PAINT_OVERLAY_FLAG:
|
||||
return "subdiv_paint_overlay_flag";
|
||||
|
||||
case SubdivShaderType::BUFFER_LNOR:
|
||||
return "subdiv_loop_normals";
|
||||
|
||||
@@ -34,7 +34,7 @@ enum class SubdivShaderType {
|
||||
BUFFER_TRIS = 4,
|
||||
BUFFER_TRIS_MULTIPLE_MATERIALS = 5,
|
||||
BUFFER_NORMALS_ACCUMULATE = 6,
|
||||
BUFFER_CUSTOM_NORMALS_FINALIZE = 7,
|
||||
BUFFER_PAINT_OVERLAY_FLAG = 7,
|
||||
PATCH_EVALUATION = 8,
|
||||
PATCH_EVALUATION_FVAR = 9,
|
||||
PATCH_EVALUATION_FACE_DOTS = 10,
|
||||
|
||||
@@ -72,14 +72,13 @@
|
||||
#define NORMALS_ACCUMULATE_VERTEX_LOOP_MAP_BUF_SLOT 3
|
||||
#define NORMALS_ACCUMULATE_NORMALS_BUF_SLOT 4
|
||||
|
||||
#define NORMALS_FINALIZE_CUSTOM_NORMALS_BUF_SLOT 1
|
||||
#define NORMALS_FINALIZE_INPUT_VERT_ORIG_INDEX_BUF_SLOT 2
|
||||
#define NORMALS_FINALIZE_EXTRA_COARSE_FACE_DATA_BUF_SLOT 3
|
||||
#define NORMALS_FINALIZE_OUTPUT_LNOR_BUF_SLOT 4
|
||||
#define PAINT_OVERLAY_EXTRA_COARSE_FACE_DATA_BUF_SLOT 1
|
||||
#define PAINT_OVERLAY_EXTRA_INPUT_VERT_ORIG_INDEX_SLOT 2
|
||||
#define PAINT_OVERLAY_FLAG_VERTEX_LOOP_MAP_BUF_SLOT 3
|
||||
#define PAINT_OVERLAY_OUTPUT_FLAG_SLOT 4
|
||||
|
||||
#define LOOP_NORMALS_POS_SLOT 1
|
||||
#define LOOP_NORMALS_EXTRA_COARSE_FACE_DATA_BUF_SLOT 2
|
||||
#define LOOP_NORMALS_INPUT_VERT_ORIG_INDEX_BUF_SLOT 3
|
||||
#define LOOP_NORMALS_VERT_NORMALS_BUF_SLOT 4
|
||||
#define LOOP_NORMALS_VERTEX_LOOP_MAP_BUF_SLOT 5
|
||||
#define LOOP_NORMALS_OUTPUT_LNOR_BUF_SLOT 6
|
||||
#define LOOP_NORMALS_VERT_NORMALS_BUF_SLOT 3
|
||||
#define LOOP_NORMALS_VERTEX_LOOP_MAP_BUF_SLOT 4
|
||||
#define LOOP_NORMALS_OUTPUT_LNOR_BUF_SLOT 5
|
||||
|
||||
@@ -73,11 +73,6 @@ struct Position {
|
||||
float z;
|
||||
};
|
||||
|
||||
struct LoopNormal {
|
||||
float nx, ny, nz;
|
||||
float flag;
|
||||
};
|
||||
|
||||
struct Normal {
|
||||
float x;
|
||||
float y;
|
||||
|
||||
@@ -236,9 +236,9 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf *subdiv_corner_verts,
|
||||
gpu::VertBuf *lnor);
|
||||
|
||||
void draw_subdiv_build_lnor_buffer_from_custom_normals(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf &interpolated_custom_normals,
|
||||
gpu::VertBuf &lnor);
|
||||
void draw_subdiv_build_paint_overlay_flag_buffer(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf &subdiv_corner_verts,
|
||||
gpu::VertBuf &flags);
|
||||
|
||||
void draw_subdiv_build_edituv_stretch_area_buffer(const DRWSubdivCache &cache,
|
||||
gpu::VertBuf *coarse_data,
|
||||
|
||||
@@ -377,4 +377,8 @@ gpu::VertBufPtr extract_attribute_subdiv(const MeshRenderData &mr,
|
||||
StringRef name);
|
||||
gpu::VertBufPtr extract_attr_viewer(const MeshRenderData &mr);
|
||||
|
||||
gpu::VertBufPtr extract_paint_overlay_flags(const MeshRenderData &mr);
|
||||
gpu::VertBufPtr extract_paint_overlay_flags_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache);
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
@@ -74,67 +74,6 @@ static void extract_normals_mesh(const MeshRenderData &mr, MutableSpan<GPUType>
|
||||
}
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_paint_overlay_flags(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
const bool use_face_select = (mr.mesh->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
Span<bool> selection;
|
||||
if (mr.mesh->editflag & ME_EDIT_PAINT_FACE_SEL) {
|
||||
selection = mr.select_poly;
|
||||
}
|
||||
else if (mr.mesh->editflag & ME_EDIT_PAINT_VERT_SEL) {
|
||||
selection = mr.select_vert;
|
||||
}
|
||||
if (selection.is_empty() && mr.hide_poly.is_empty() && (!mr.edit_bmesh || !mr.orig_index_vert)) {
|
||||
return;
|
||||
}
|
||||
const OffsetIndices faces = mr.faces;
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
if (!selection.is_empty()) {
|
||||
if (use_face_select) {
|
||||
for (const int face : range) {
|
||||
if (selection[face]) {
|
||||
for (const int corner : faces[face]) {
|
||||
normals[corner].w = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
if (selection[corner_verts[corner]]) {
|
||||
normals[corner].w = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mr.hide_poly.is_empty()) {
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
for (const int face : range) {
|
||||
if (hide_poly[face]) {
|
||||
for (const int corner : faces[face]) {
|
||||
normals[corner].w = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mr.edit_bmesh && mr.orig_index_vert) {
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> orig_indices(mr.orig_index_vert, mr.verts_num);
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
if (orig_indices[corner_verts[corner]] == ORIGINDEX_NONE) {
|
||||
normals[corner].w = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_vert_normals_bm(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
@@ -219,24 +158,6 @@ static void extract_face_normals_bm(const MeshRenderData &mr, MutableSpan<GPUTyp
|
||||
}
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_edit_flags_bm(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
/* TODO: Return early if there are no hidden faces. */
|
||||
const BMesh &bm = *mr.bm;
|
||||
threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
|
||||
if (BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
|
||||
const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
|
||||
for (GPUType &value : normals.slice(face_range)) {
|
||||
value.w = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename GPUType>
|
||||
static void extract_normals_bm(const MeshRenderData &mr, MutableSpan<GPUType> normals)
|
||||
{
|
||||
@@ -319,11 +240,9 @@ gpu::VertBufPtr extract_normals(const MeshRenderData &mr, const bool use_hq)
|
||||
|
||||
if (mr.extract_type == MeshExtractType::Mesh) {
|
||||
extract_normals_mesh(mr, corners_data);
|
||||
extract_paint_overlay_flags(mr, corners_data);
|
||||
}
|
||||
else {
|
||||
extract_normals_bm(mr, corners_data);
|
||||
extract_edit_flags_bm(mr, corners_data);
|
||||
}
|
||||
|
||||
loose_data.fill(short4(0));
|
||||
@@ -344,11 +263,9 @@ gpu::VertBufPtr extract_normals(const MeshRenderData &mr, const bool use_hq)
|
||||
|
||||
if (mr.extract_type == MeshExtractType::Mesh) {
|
||||
extract_normals_mesh(mr, corners_data);
|
||||
extract_paint_overlay_flags(mr, corners_data);
|
||||
}
|
||||
else {
|
||||
extract_normals_bm(mr, corners_data);
|
||||
extract_edit_flags_bm(mr, corners_data);
|
||||
}
|
||||
|
||||
loose_data.fill(gpu::PackedNormal{});
|
||||
@@ -359,7 +276,7 @@ static const GPUVertFormat &get_normals_format()
|
||||
{
|
||||
static const GPUVertFormat format = []() {
|
||||
GPUVertFormat format{};
|
||||
GPU_vertformat_attr_add(&format, "nor", gpu::VertAttrType::SFLOAT_32_32_32_32);
|
||||
GPU_vertformat_attr_add(&format, "nor", gpu::VertAttrType::SFLOAT_32_32_32);
|
||||
GPU_vertformat_alias_add(&format, "lnor");
|
||||
GPU_vertformat_alias_add(&format, "vnor");
|
||||
return format;
|
||||
@@ -403,11 +320,7 @@ gpu::VertBufPtr extract_normals_subdiv(const MeshRenderData &mr,
|
||||
gpu::VertBufPtr src = gpu::VertBufPtr(GPU_vertbuf_create_with_format(src_normals_format));
|
||||
GPU_vertbuf_data_alloc(*src, coarse_mesh->corners_num);
|
||||
src->data<float3>().copy_from(coarse_mesh->corner_normals());
|
||||
gpu::VertBufPtr dst = gpu::VertBufPtr(
|
||||
GPU_vertbuf_create_on_device(src_normals_format, vbo_size));
|
||||
draw_subdiv_interp_corner_normals(subdiv_cache, *src, *dst);
|
||||
|
||||
draw_subdiv_build_lnor_buffer_from_custom_normals(subdiv_cache, *dst, *lnor);
|
||||
draw_subdiv_interp_corner_normals(subdiv_cache, *src, *lnor);
|
||||
|
||||
update_loose_normals(mr, subdiv_cache, *lnor);
|
||||
return lnor;
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "extract_mesh.hh"
|
||||
|
||||
#include "draw_subdivision.hh"
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
static void extract_paint_overlay_flags(const MeshRenderData &mr, MutableSpan<int> flags)
|
||||
{
|
||||
const bool use_face_select = (mr.mesh->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
Span<bool> selection;
|
||||
if (mr.mesh->editflag & ME_EDIT_PAINT_FACE_SEL) {
|
||||
selection = mr.select_poly;
|
||||
}
|
||||
else if (mr.mesh->editflag & ME_EDIT_PAINT_VERT_SEL) {
|
||||
selection = mr.select_vert;
|
||||
}
|
||||
if (selection.is_empty() && mr.hide_poly.is_empty() && (!mr.edit_bmesh || !mr.orig_index_vert)) {
|
||||
return;
|
||||
}
|
||||
const OffsetIndices faces = mr.faces;
|
||||
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
|
||||
if (selection.is_empty()) {
|
||||
flags.fill(0);
|
||||
}
|
||||
else {
|
||||
if (use_face_select) {
|
||||
for (const int face : range) {
|
||||
flags.slice(faces[face]).fill(selection[face] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
flags[corner] = selection[corner_verts[corner]] ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mr.hide_poly.is_empty()) {
|
||||
const Span<bool> hide_poly = mr.hide_poly;
|
||||
for (const int face : range) {
|
||||
if (hide_poly[face]) {
|
||||
flags.slice(faces[face]).fill(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mr.edit_bmesh && mr.orig_index_vert) {
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> orig_indices(mr.orig_index_vert, mr.verts_num);
|
||||
for (const int face : range) {
|
||||
for (const int corner : faces[face]) {
|
||||
if (orig_indices[corner_verts[corner]] == ORIGINDEX_NONE) {
|
||||
flags[corner] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void extract_edit_flags_bm(const MeshRenderData &mr, MutableSpan<int> flags)
|
||||
{
|
||||
/* TODO: Return early if there are no hidden faces. */
|
||||
const BMesh &bm = *mr.bm;
|
||||
threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
|
||||
for (const int face_index : range) {
|
||||
const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
|
||||
if (BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
|
||||
const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
|
||||
flags.slice(face_range).fill(-1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static const GPUVertFormat &get_paint_overlay_flag_format()
|
||||
{
|
||||
static const GPUVertFormat format = GPU_vertformat_from_attribute("paint_overlay_flag",
|
||||
gpu::VertAttrType::SINT_32);
|
||||
return format;
|
||||
}
|
||||
|
||||
gpu::VertBufPtr extract_paint_overlay_flags(const MeshRenderData &mr)
|
||||
{
|
||||
const int size = mr.corners_num + mr.loose_indices_num;
|
||||
gpu::VertBufPtr vbo = gpu::VertBufPtr(
|
||||
GPU_vertbuf_create_with_format(get_paint_overlay_flag_format()));
|
||||
GPU_vertbuf_data_alloc(*vbo, size);
|
||||
MutableSpan vbo_data = vbo->data<int>();
|
||||
MutableSpan corners_data = vbo_data.take_front(mr.corners_num);
|
||||
MutableSpan loose_data = vbo_data.take_back(mr.loose_indices_num);
|
||||
|
||||
if (mr.extract_type == MeshExtractType::Mesh) {
|
||||
extract_paint_overlay_flags(mr, corners_data);
|
||||
}
|
||||
else {
|
||||
extract_edit_flags_bm(mr, corners_data);
|
||||
}
|
||||
|
||||
loose_data.fill(0);
|
||||
return vbo;
|
||||
}
|
||||
|
||||
static void update_loose_flags(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &flags)
|
||||
{
|
||||
const int vbo_size = subdiv_full_vbo_size(mr, subdiv_cache);
|
||||
const int loose_geom_start = subdiv_cache.num_subdiv_loops;
|
||||
|
||||
/* Push VBO content to the GPU and bind the VBO so that #GPU_vertbuf_update_sub can work. */
|
||||
GPU_vertbuf_use(&flags);
|
||||
|
||||
/* Default to zeroed attribute. The overlay shader should expect this and render engines should
|
||||
* never draw loose geometry. */
|
||||
const int default_value = 0;
|
||||
for (const int i : IndexRange::from_begin_end(loose_geom_start, vbo_size)) {
|
||||
/* TODO(fclem): This has HORRENDOUS performance. Prefer clearing the buffer on device with
|
||||
* something like glClearBufferSubData. */
|
||||
GPU_vertbuf_update_sub(&flags, i * sizeof(int), sizeof(int), &default_value);
|
||||
}
|
||||
}
|
||||
|
||||
gpu::VertBufPtr extract_paint_overlay_flags_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache)
|
||||
{
|
||||
gpu::VertBufPtr flags = gpu::VertBufPtr(GPU_vertbuf_create_on_device(
|
||||
get_paint_overlay_flag_format(), subdiv_full_vbo_size(mr, subdiv_cache)));
|
||||
gpu::VertBufPtr subdiv_corner_verts = gpu::VertBufPtr(draw_subdiv_build_origindex_buffer(
|
||||
subdiv_cache.subdiv_loop_subdiv_vert_index, subdiv_cache.num_subdiv_loops));
|
||||
|
||||
draw_subdiv_build_paint_overlay_flag_buffer(subdiv_cache, *subdiv_corner_verts, *flags);
|
||||
|
||||
update_loose_flags(mr, subdiv_cache, *flags);
|
||||
return flags;
|
||||
}
|
||||
|
||||
} // namespace blender::draw
|
||||
@@ -39,8 +39,8 @@ set(SRC_GLSL_COMP
|
||||
subdiv_vbo_edituv_strech_angle_comp.glsl
|
||||
subdiv_vbo_edituv_strech_area_comp.glsl
|
||||
subdiv_vbo_lnor_comp.glsl
|
||||
subdiv_vbo_paint_overlay_flag_comp.glsl
|
||||
subdiv_normals_accumulate_comp.glsl
|
||||
subdiv_normals_finalize_comp.glsl
|
||||
)
|
||||
|
||||
# Compile shaders with shader code.
|
||||
|
||||
@@ -111,10 +111,9 @@ GPU_SHADER_CREATE_INFO(subdiv_loop_normals)
|
||||
DO_STATIC_COMPILATION()
|
||||
STORAGE_BUF(LOOP_NORMALS_POS_SLOT, read, Position, positions[])
|
||||
STORAGE_BUF(LOOP_NORMALS_EXTRA_COARSE_FACE_DATA_BUF_SLOT, read, uint, extra_coarse_face_data[])
|
||||
STORAGE_BUF(LOOP_NORMALS_INPUT_VERT_ORIG_INDEX_BUF_SLOT, read, int, input_vert_origindex[])
|
||||
STORAGE_BUF(LOOP_NORMALS_VERT_NORMALS_BUF_SLOT, read, Normal, vert_normals[])
|
||||
STORAGE_BUF(LOOP_NORMALS_VERTEX_LOOP_MAP_BUF_SLOT, read, uint, vert_loop_map[])
|
||||
STORAGE_BUF(LOOP_NORMALS_OUTPUT_LNOR_BUF_SLOT, write, LoopNormal, output_lnor[])
|
||||
STORAGE_BUF(LOOP_NORMALS_OUTPUT_LNOR_BUF_SLOT, write, Normal, output_lnor[])
|
||||
COMPUTE_SOURCE("subdiv_vbo_lnor_comp.glsl")
|
||||
ADDITIONAL_INFO(subdiv_polygon_offset_base)
|
||||
GPU_SHADER_CREATE_END()
|
||||
@@ -285,13 +284,19 @@ COMPUTE_SOURCE("subdiv_normals_accumulate_comp.glsl")
|
||||
ADDITIONAL_INFO(subdiv_base)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
GPU_SHADER_CREATE_INFO(subdiv_custom_normals_finalize)
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Paint Overlay Flag
|
||||
* \{ */
|
||||
|
||||
GPU_SHADER_CREATE_INFO(subdiv_paint_overlay_flag)
|
||||
DO_STATIC_COMPILATION()
|
||||
STORAGE_BUF(NORMALS_FINALIZE_CUSTOM_NORMALS_BUF_SLOT, read, Normal, custom_normals[])
|
||||
STORAGE_BUF(NORMALS_FINALIZE_INPUT_VERT_ORIG_INDEX_BUF_SLOT, read, int, input_vert_origindex[])
|
||||
STORAGE_BUF(NORMALS_FINALIZE_EXTRA_COARSE_FACE_DATA_BUF_SLOT, read, uint, extra_coarse_face_data[])
|
||||
STORAGE_BUF(NORMALS_FINALIZE_OUTPUT_LNOR_BUF_SLOT, write, LoopNormal, output_lnor[])
|
||||
COMPUTE_SOURCE("subdiv_normals_finalize_comp.glsl")
|
||||
STORAGE_BUF(PAINT_OVERLAY_EXTRA_COARSE_FACE_DATA_BUF_SLOT, read, uint, extra_coarse_face_data[])
|
||||
STORAGE_BUF(PAINT_OVERLAY_EXTRA_INPUT_VERT_ORIG_INDEX_SLOT, read, int, input_vert_origindex[])
|
||||
STORAGE_BUF(PAINT_OVERLAY_FLAG_VERTEX_LOOP_MAP_BUF_SLOT, read, uint, vert_loop_map[])
|
||||
STORAGE_BUF(PAINT_OVERLAY_OUTPUT_FLAG_SLOT, write, int, flags[])
|
||||
COMPUTE_SOURCE("subdiv_vbo_paint_overlay_flag_comp.glsl")
|
||||
ADDITIONAL_INFO(subdiv_polygon_offset_base)
|
||||
GPU_SHADER_CREATE_END()
|
||||
|
||||
|
||||
@@ -6,28 +6,6 @@
|
||||
|
||||
COMPUTE_SHADER_CREATE_INFO(subdiv_loop_normals)
|
||||
|
||||
bool is_face_selected(uint coarse_quad_index)
|
||||
{
|
||||
return (extra_coarse_face_data[coarse_quad_index] & shader_data.coarse_face_select_mask) != 0;
|
||||
}
|
||||
|
||||
bool is_face_hidden(uint coarse_quad_index)
|
||||
{
|
||||
return (extra_coarse_face_data[coarse_quad_index] & shader_data.coarse_face_hidden_mask) != 0;
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay and normals drawing in edit-mode. */
|
||||
float get_loop_flag(uint coarse_quad_index, int vert_origindex)
|
||||
{
|
||||
if (is_face_hidden(coarse_quad_index) || (shader_data.is_edit_mode && vert_origindex == -1)) {
|
||||
return -1.0f;
|
||||
}
|
||||
if (is_face_selected(coarse_quad_index)) {
|
||||
return 1.0f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
/* We execute for each quad. */
|
||||
@@ -48,16 +26,12 @@ void main()
|
||||
uint subdiv_vert_index = vert_loop_map[start_loop_index + i];
|
||||
Normal vert_normal = vert_normals[subdiv_vert_index];
|
||||
|
||||
int origindex = input_vert_origindex[start_loop_index + i];
|
||||
float flag = get_loop_flag(coarse_quad_index, origindex);
|
||||
Normal normal;
|
||||
normal.x = vert_normal.x;
|
||||
normal.y = vert_normal.y;
|
||||
normal.z = vert_normal.z;
|
||||
|
||||
LoopNormal loop_normal;
|
||||
loop_normal.nx = vert_normal.x;
|
||||
loop_normal.ny = vert_normal.y;
|
||||
loop_normal.nz = vert_normal.z;
|
||||
loop_normal.flag = flag;
|
||||
|
||||
output_lnor[start_loop_index + i] = loop_normal;
|
||||
output_lnor[start_loop_index + i] = normal;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -78,16 +52,13 @@ void main()
|
||||
|
||||
face_normal = normalize(face_normal);
|
||||
|
||||
LoopNormal loop_normal;
|
||||
loop_normal.nx = face_normal.x;
|
||||
loop_normal.ny = face_normal.y;
|
||||
loop_normal.nz = face_normal.z;
|
||||
Normal normal;
|
||||
normal.x = face_normal.x;
|
||||
normal.y = face_normal.y;
|
||||
normal.z = face_normal.z;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int origindex = input_vert_origindex[start_loop_index + i];
|
||||
loop_normal.flag = get_loop_flag(coarse_quad_index, origindex);
|
||||
|
||||
output_lnor[start_loop_index + i] = loop_normal;
|
||||
output_lnor[start_loop_index + i] = normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
/* SPDX-FileCopyrightText: 2021-2022 Blender Authors
|
||||
/* SPDX-FileCopyrightText: 2021-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/* Finalize normals after accumulating or interpolation.
|
||||
*
|
||||
* Custom normals are interpolated from coarse face corners to subdivided face corners
|
||||
* by the generic custom data interpolation process. This shader is necessary to combine
|
||||
* them with the interleaved flag in the final buffer.
|
||||
*
|
||||
* TODO: Move the currently interleaved flag to a separate buffer so this is unnecessary.
|
||||
*/
|
||||
|
||||
#include "subdiv_lib.glsl"
|
||||
|
||||
COMPUTE_SHADER_CREATE_INFO(subdiv_custom_normals_finalize)
|
||||
COMPUTE_SHADER_CREATE_INFO(subdiv_paint_overlay_flag)
|
||||
|
||||
bool is_face_selected(uint coarse_quad_index)
|
||||
{
|
||||
@@ -26,15 +17,15 @@ bool is_face_hidden(uint coarse_quad_index)
|
||||
}
|
||||
|
||||
/* Flag for paint mode overlay and normals drawing in edit-mode. */
|
||||
float get_loop_flag(uint coarse_quad_index, int vert_origindex)
|
||||
int get_loop_flag(uint coarse_quad_index, int vert_origindex)
|
||||
{
|
||||
if (is_face_hidden(coarse_quad_index) || (shader_data.is_edit_mode && vert_origindex == -1)) {
|
||||
return -1.0;
|
||||
return -1;
|
||||
}
|
||||
if (is_face_selected(coarse_quad_index)) {
|
||||
return 1.0;
|
||||
return 1;
|
||||
}
|
||||
return 0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void main()
|
||||
@@ -45,24 +36,17 @@ void main()
|
||||
return;
|
||||
}
|
||||
|
||||
uint coarse_quad_index = coarse_face_index_from_subdiv_quad_index(quad_index,
|
||||
shader_data.coarse_face_count);
|
||||
|
||||
/* The start index of the loop is quad_index * 4. */
|
||||
uint start_loop_index = quad_index * 4;
|
||||
|
||||
uint coarse_quad_index = coarse_face_index_from_subdiv_quad_index(quad_index,
|
||||
shader_data.coarse_face_count);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Normal custom_normal = custom_normals[start_loop_index + i];
|
||||
float3 nor = float3(custom_normal.x, custom_normal.y, custom_normal.z);
|
||||
nor = normalize(nor);
|
||||
|
||||
LoopNormal lnor;
|
||||
lnor.nx = nor.x;
|
||||
lnor.ny = nor.y;
|
||||
lnor.nz = nor.z;
|
||||
uint subdiv_vert_index = vert_loop_map[start_loop_index + i];
|
||||
|
||||
int origindex = input_vert_origindex[start_loop_index + i];
|
||||
lnor.flag = get_loop_flag(coarse_quad_index, origindex);
|
||||
int flag = get_loop_flag(coarse_quad_index, origindex);
|
||||
|
||||
output_lnor[start_loop_index + i] = lnor;
|
||||
flags[start_loop_index + i] = flag;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user