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
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.cc8
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc55
-rw-r--r--source/blender/draw/intern/draw_subdivision.h4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc67
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc18
-rw-r--r--source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl56
7 files changed, 133 insertions, 77 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc
index ec544d8e786..3d44d3d1b3f 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc
@@ -793,7 +793,12 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
/* The order in which extractors are added to the list matters somewhat, as some buffers are
* reused when building others. */
EXTRACT_ADD_REQUESTED(ibo, tris);
- EXTRACT_ADD_REQUESTED(vbo, pos_nor);
+
+ /* Orcos are extracted at the same time as positions. */
+ if (DRW_vbo_requested(mbuflist->vbo.pos_nor) || DRW_vbo_requested(mbuflist->vbo.orco)) {
+ extractors.append(&extract_pos_nor);
+ }
+
EXTRACT_ADD_REQUESTED(vbo, lnor);
for (int i = 0; i < GPU_MAX_ATTR; i++) {
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
@@ -843,7 +848,6 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle);
EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask);
EXTRACT_ADD_REQUESTED(ibo, lines_adjacency);
- EXTRACT_ADD_REQUESTED(vbo, orco);
EXTRACT_ADD_REQUESTED(vbo, vcol);
EXTRACT_ADD_REQUESTED(vbo, weights);
EXTRACT_ADD_REQUESTED(vbo, sculpt_data);
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index cfdf059ca37..dc40e15a450 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -69,6 +69,7 @@ enum {
SHADER_PATCH_EVALUATION,
SHADER_PATCH_EVALUATION_FVAR,
SHADER_PATCH_EVALUATION_FACE_DOTS,
+ SHADER_PATCH_EVALUATION_ORCO,
SHADER_COMP_CUSTOM_DATA_INTERP_1D,
SHADER_COMP_CUSTOM_DATA_INTERP_2D,
SHADER_COMP_CUSTOM_DATA_INTERP_3D,
@@ -107,7 +108,8 @@ static const char *get_shader_code(int shader_type)
}
case SHADER_PATCH_EVALUATION:
case SHADER_PATCH_EVALUATION_FVAR:
- case SHADER_PATCH_EVALUATION_FACE_DOTS: {
+ case SHADER_PATCH_EVALUATION_FACE_DOTS:
+ case SHADER_PATCH_EVALUATION_ORCO: {
return datatoc_common_subdiv_patch_evaluation_comp_glsl;
}
case SHADER_COMP_CUSTOM_DATA_INTERP_1D:
@@ -163,6 +165,9 @@ static const char *get_shader_name(int shader_type)
case SHADER_PATCH_EVALUATION_FACE_DOTS: {
return "subdiv patch evaluation face dots";
}
+ case SHADER_PATCH_EVALUATION_ORCO: {
+ return "subdiv patch evaluation orco";
+ }
case SHADER_COMP_CUSTOM_DATA_INTERP_1D: {
return "subdiv custom data interp 1D";
}
@@ -206,6 +211,12 @@ static GPUShader *get_patch_evaluation_shader(int shader_type)
"#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
"#define FDOTS_EVALUATION\n";
}
+ else if (shader_type == SHADER_PATCH_EVALUATION_ORCO) {
+ defines =
+ "#define OSD_PATCH_BASIS_GLSL\n"
+ "#define OPENSUBDIV_GLSL_COMPUTE_USE_1ST_DERIVATIVES\n"
+ "#define ORCO_EVALUATION\n";
+ }
else {
defines =
"#define OSD_PATCH_BASIS_GLSL\n"
@@ -236,7 +247,8 @@ static GPUShader *get_subdiv_shader(int shader_type, const char *defines)
if (ELEM(shader_type,
SHADER_PATCH_EVALUATION,
SHADER_PATCH_EVALUATION_FVAR,
- SHADER_PATCH_EVALUATION_FACE_DOTS)) {
+ SHADER_PATCH_EVALUATION_FACE_DOTS,
+ SHADER_PATCH_EVALUATION_ORCO)) {
return get_patch_evaluation_shader(shader_type);
}
if (g_subdiv_shaders[shader_type] == nullptr) {
@@ -710,6 +722,23 @@ static DRWSubdivCache *mesh_batch_cache_ensure_subdiv_cache(MeshBatchCache *mbc)
return subdiv_cache;
}
+static void draw_subdiv_invalidate_evaluator_for_orco(Subdiv *subdiv, Mesh *mesh)
+{
+ const bool has_orco = CustomData_has_layer(&mesh->vdata, CD_ORCO);
+ if (has_orco && subdiv->evaluator && !subdiv->evaluator->hasVertexData(subdiv->evaluator)) {
+ /* If we suddenly have/need original coordinates, recreate the evaluator if the extra
+ * source was not created yet. The refiner also has to be recreated as refinement for source
+ * and vertex data is done only once. */
+ openSubdiv_deleteEvaluator(subdiv->evaluator);
+ subdiv->evaluator = nullptr;
+
+ if (subdiv->topology_refiner != nullptr) {
+ openSubdiv_deleteTopologyRefiner(subdiv->topology_refiner);
+ subdiv->topology_refiner = nullptr;
+ }
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1230,7 +1259,9 @@ 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)
+void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
+ GPUVertBuf *pos_nor,
+ GPUVertBuf *orco)
{
if (!draw_subdiv_cache_need_polygon_data(cache)) {
/* Happens on meshes with only loose geometry. */
@@ -1245,6 +1276,14 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_no
get_subdiv_vertex_format());
evaluator->wrapSrcBuffer(evaluator, &src_buffer_interface);
+ GPUVertBuf *src_extra_buffer = nullptr;
+ if (orco) {
+ OpenSubdiv_Buffer src_extra_buffer_interface;
+ src_extra_buffer = create_buffer_and_interface(&src_extra_buffer_interface,
+ get_subdiv_vertex_format());
+ evaluator->wrapSrcVertexDataBuffer(evaluator, &src_extra_buffer_interface);
+ }
+
OpenSubdiv_Buffer patch_arrays_buffer_interface;
GPUVertBuf *patch_arrays_buffer = create_buffer_and_interface(&patch_arrays_buffer_interface,
get_patch_array_format());
@@ -1260,7 +1299,8 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_no
get_patch_param_format());
evaluator->wrapPatchParamBuffer(evaluator, &patch_param_buffer_interface);
- GPUShader *shader = get_patch_evaluation_shader(SHADER_PATCH_EVALUATION);
+ GPUShader *shader = get_patch_evaluation_shader(orco ? SHADER_PATCH_EVALUATION_ORCO :
+ SHADER_PATCH_EVALUATION);
GPU_shader_bind(shader);
int binding_point = 0;
@@ -1273,6 +1313,10 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_no
GPU_vertbuf_bind_as_ssbo(patch_index_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(patch_param_buffer, binding_point++);
GPU_vertbuf_bind_as_ssbo(pos_nor, binding_point++);
+ if (orco) {
+ GPU_vertbuf_bind_as_ssbo(src_extra_buffer, binding_point++);
+ GPU_vertbuf_bind_as_ssbo(orco, binding_point++);
+ }
BLI_assert(binding_point <= MAX_GPU_SUBDIV_SSBOS);
drw_subdiv_compute_dispatch(cache, shader, 0, 0, cache->num_subdiv_quads);
@@ -1289,6 +1333,7 @@ void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_no
GPU_vertbuf_discard(patch_param_buffer);
GPU_vertbuf_discard(patch_arrays_buffer);
GPU_vertbuf_discard(src_buffer);
+ GPU_VERTBUF_DISCARD_SAFE(src_extra_buffer);
}
void draw_subdiv_extract_uvs(const DRWSubdivCache *cache,
@@ -1935,6 +1980,8 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
return false;
}
+ 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)) {
/* This could happen in two situations:
diff --git a/source/blender/draw/intern/draw_subdivision.h b/source/blender/draw/intern/draw_subdivision.h
index 2d24d07e037..7bddd000ecb 100644
--- a/source/blender/draw/intern/draw_subdivision.h
+++ b/source/blender/draw/intern/draw_subdivision.h
@@ -235,7 +235,9 @@ 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);
+void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache,
+ struct GPUVertBuf *pos_nor,
+ struct GPUVertBuf *orco);
void draw_subdiv_interp_custom_data(const DRWSubdivCache *cache,
struct GPUVertBuf *src_data,
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
index 14f61dcd739..fb4b95885fc 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
@@ -236,7 +236,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi
draw_subdiv_get_pos_nor_format(),
subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
- draw_subdiv_extract_pos_nor(subdiv_cache, pos_nor);
+ draw_subdiv_extract_pos_nor(subdiv_cache, pos_nor, nullptr);
}
/* UVs are stored contiguously so we need to compute the offset in the UVs buffer for the active
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
index b45a73a27c0..94674a54f12 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_orco.cc
@@ -7,8 +7,6 @@
#include "extract_mesh.h"
-#include "draw_subdivision.h"
-
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -79,77 +77,12 @@ static void extract_orco_iter_poly_mesh(const MeshRenderData *mr,
}
}
-static void extract_orco_init_subdiv(const DRWSubdivCache *subdiv_cache,
- const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buffer,
- void *UNUSED(data))
-{
- static GPUVertFormat format = {0};
- if (format.attr_len == 0) {
- /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
- * attributes. This is a substantial waste of video-ram and should be done another way.
- * Unfortunately, at the time of writing, I did not found any other "non disruptive"
- * alternative. */
- GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- }
-
- GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer);
- GPU_vertbuf_init_build_on_device(dst_buffer, &format, subdiv_cache->num_subdiv_loops);
-
- GPUVertBuf *coarse_vbo = GPU_vertbuf_calloc();
- /* Dynamic as we upload and interpolate layers one at a time. */
- GPU_vertbuf_init_with_format_ex(coarse_vbo, &format, GPU_USAGE_DYNAMIC);
- GPU_vertbuf_data_alloc(coarse_vbo, mr->loop_len);
-
- float(*coarse_vbo_data)[4] = static_cast<float(*)[4]>(GPU_vertbuf_get_data(coarse_vbo));
-
- CustomData *cd_vdata = &mr->me->vdata;
- const float(*orco)[3] = static_cast<const float(*)[3]>(CustomData_get_layer(cd_vdata, CD_ORCO));
-
- if (mr->extract_type == MR_EXTRACT_MESH) {
- const MLoop *mloop = mr->mloop;
- const MPoly *mp = mr->mpoly;
-
- int ml_index = 0;
- for (int i = 0; i < mr->poly_len; i++, mp++) {
- const MLoop *ml = &mloop[mp->loopstart];
-
- for (int j = 0; j < mp->totloop; j++, ml++, ml_index++) {
- float *loop_orco = coarse_vbo_data[ml_index];
- copy_v3_v3(loop_orco, orco[ml->v]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
- }
- }
- }
- else {
- BMIter iter;
- BMFace *f;
- BM_ITER_MESH (f, &iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter;
- BMLoop *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- const int l_index = BM_elem_index_get(l_iter);
- float *loop_orco = coarse_vbo_data[l_index];
- copy_v3_v3(loop_orco, orco[BM_elem_index_get(l_iter->v)]);
- loop_orco[3] = 0.0; /* Tag as not a generic attribute. */
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- draw_subdiv_interp_custom_data(subdiv_cache, coarse_vbo, dst_buffer, 4, 0, false);
-
- GPU_vertbuf_discard(coarse_vbo);
-}
-
constexpr MeshExtract create_extractor_orco()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_orco_init;
extractor.iter_poly_bm = extract_orco_iter_poly_bm;
extractor.iter_poly_mesh = extract_orco_iter_poly_mesh;
- extractor.init_subdiv = extract_orco_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_Orco_Data);
extractor.use_threading = true;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
index c8c91d45542..f80b33e28f2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -201,7 +201,7 @@ static GPUVertFormat *get_custom_normals_format()
static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
const MeshRenderData *UNUSED(mr),
- struct MeshBatchCache *UNUSED(cache),
+ struct MeshBatchCache *cache,
void *buffer,
void *UNUSED(data))
{
@@ -216,7 +216,21 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
return;
}
- draw_subdiv_extract_pos_nor(subdiv_cache, vbo);
+ GPUVertBuf *orco_vbo = cache->final.buff.vbo.orco;
+
+ if (orco_vbo) {
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
+ * attributes. This is a substantial waste of video-ram and should be done another way.
+ * Unfortunately, at the time of writing, I did not found any other "non disruptive"
+ * alternative. */
+ GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+ GPU_vertbuf_init_build_on_device(orco_vbo, &format, subdiv_cache->num_subdiv_loops);
+ }
+
+ draw_subdiv_extract_pos_nor(subdiv_cache, vbo, orco_vbo);
if (subdiv_cache->use_custom_loop_normals) {
Mesh *coarse_mesh = subdiv_cache->mesh;
diff --git a/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl b/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl
index 65cf4ebb90f..bf1f0f95787 100644
--- a/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl
+++ b/source/blender/draw/intern/shaders/common_subdiv_patch_evaluation_comp.glsl
@@ -89,6 +89,16 @@ layout(std430, binding = 8) writeonly buffer outputVertexData
{
PosNorLoop output_verts[];
};
+# if defined(ORCO_EVALUATION)
+layout(std430, binding = 9) buffer src_extra_buffer
+{
+ float srcExtraVertexBuffer[];
+};
+layout(std430, binding = 10) writeonly buffer outputOrcoData
+{
+ vec4 output_orcos[];
+};
+# endif
#endif
vec2 read_vec2(int index)
@@ -108,6 +118,17 @@ vec3 read_vec3(int index)
return result;
}
+#if defined(ORCO_EVALUATION)
+vec3 read_vec3_extra(int index)
+{
+ vec3 result;
+ result.x = srcExtraVertexBuffer[index * 3];
+ result.y = srcExtraVertexBuffer[index * 3 + 1];
+ result.z = srcExtraVertexBuffer[index * 3 + 2];
+ return result;
+}
+#endif
+
OsdPatchArray GetPatchArray(int arrayIndex)
{
return patchArrayBuffer[arrayIndex];
@@ -290,6 +311,31 @@ void evaluate_patches_limits(
dv += src_vertex * wDv[cv];
}
}
+
+# if defined(ORCO_EVALUATION)
+/* Evaluate the patches limits from the extra source vertex buffer. */
+void evaluate_patches_limits_extra(int patch_index, float u, float v, inout vec3 dst)
+{
+ OsdPatchCoord coord = GetPatchCoord(patch_index, u, v);
+ OsdPatchArray array = GetPatchArray(coord.arrayIndex);
+ OsdPatchParam param = GetPatchParam(coord.patchIndex);
+
+ int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
+
+ float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
+ int nPoints = OsdEvaluatePatchBasis(
+ patchType, param, coord.s, coord.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
+
+ int indexBase = array.indexBase + array.stride * (coord.patchIndex - array.primitiveIdBase);
+
+ for (int cv = 0; cv < nPoints; ++cv) {
+ int index = patchIndexBuffer[indexBase + cv];
+ vec3 src_vertex = read_vec3_extra(index);
+
+ dst += src_vertex * wP[cv];
+ }
+}
+# endif
#endif
/* ------------------------------------------------------------------------------
@@ -407,6 +453,16 @@ void main()
set_vertex_pos(vertex_data, pos);
set_vertex_nor(vertex_data, nor, flag);
output_verts[loop_index] = vertex_data;
+
+# if defined(ORCO_EVALUATION)
+ pos = vec3(0.0);
+ evaluate_patches_limits_extra(patch_co.patch_index, uv.x, uv.y, pos);
+
+ /* Set w = 0.0 to indicate that this is not a generic attribute.
+ * See comments in `extract_mesh_vbo_orco.cc`. */
+ vec4 orco_data = vec4(pos, 0.0);
+ output_orcos[loop_index] = orco_data;
+# endif
}
}
#endif