diff options
Diffstat (limited to 'source')
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 |