diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-05-22 10:19:55 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-05-22 10:19:55 +0300 |
commit | 9d9f2f1a0356d2049ea2ce4820c61fdebbdf50ca (patch) | |
tree | 402d7a7e1bda5a9516e43e09f5e9b8ba8a6205ff /intern/opensubdiv | |
parent | 45ed325443a3a3afb57da25ad01d636a94bf6cee (diff) |
GPU subdiv: smoothly interpolate orco layer
This uses the recently introduced evaluator's vertex
data to smoothly interpolate original coordinates instead
of using linear interpolation.
The orcos are interpolated at the same time as positions
and as such, the specific subdivision routine for the
orco extractor has been removed. The patch evaluation
shader uses a definition to enable code specific to
orco evaluation.
Since the orco layer may not have been requested on first
render, and since orco data is now stored in the OpenSubDiv
evaluator, the evaluator needs to be recreated if an
orco layer is suddenly available. For this, a callback
to check if the evaluator has the data was added. This is
added to the evaluator as the `Subdiv` cache stored in the
modifier is invalidated less often than the Mesh batch cache
and so leads to fewer evaluator recreations.
Differential Revision: https://developer.blender.org/D14999
Diffstat (limited to 'intern/opensubdiv')
7 files changed, 64 insertions, 0 deletions
diff --git a/intern/opensubdiv/internal/evaluator/eval_output.h b/intern/opensubdiv/internal/evaluator/eval_output.h index bc5494bfe41..c0da108edca 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output.h +++ b/intern/opensubdiv/internal/evaluator/eval_output.h @@ -103,6 +103,10 @@ class EvalOutputAPI::EvalOutput { { } + virtual void wrapSrcVertexDataBuffer(OpenSubdiv_Buffer * /*src_buffer*/) + { + } + virtual void fillFVarPatchArraysBuffer(const int /*face_varying_channel*/, OpenSubdiv_Buffer * /*patch_arrays_buffer*/) { @@ -122,6 +126,11 @@ class EvalOutputAPI::EvalOutput { OpenSubdiv_Buffer * /*src_buffer*/) { } + + virtual bool hasVertexData() const + { + return false; + } }; namespace { @@ -437,6 +446,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { return face_varying_evaluators_.size() != 0; } + bool hasVertexData() const override + { + return src_vertex_data_ != nullptr; + } + void refine() override { // Evaluate vertex positions. @@ -599,6 +613,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput { return src_data_; } + SRC_VERTEX_BUFFER *getSrcVertexDataBuffer() const + { + return src_vertex_data_; + } + PATCH_TABLE *getPatchTable() const { return patch_table_; diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc index 566071d581b..274772b2c37 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc +++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc @@ -86,6 +86,12 @@ void GpuEvalOutput::wrapSrcBuffer(OpenSubdiv_Buffer *src_buffer) src_buffer->wrap_device_handle(src_buffer, vertex_buffer->BindVBO()); } +void GpuEvalOutput::wrapSrcVertexDataBuffer(OpenSubdiv_Buffer *src_buffer) +{ + GLVertexBuffer *vertex_buffer = getSrcVertexDataBuffer(); + src_buffer->wrap_device_handle(src_buffer, vertex_buffer->BindVBO()); +} + void GpuEvalOutput::fillFVarPatchArraysBuffer(const int face_varying_channel, OpenSubdiv_Buffer *patch_arrays_buffer) { diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h index 2306a87b87c..8a4950dd3bc 100644 --- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h +++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h @@ -52,6 +52,8 @@ class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer, void wrapSrcBuffer(OpenSubdiv_Buffer *src_buffer) override; + void wrapSrcVertexDataBuffer(OpenSubdiv_Buffer *src_buffer) override; + void fillFVarPatchArraysBuffer(const int face_varying_channel, OpenSubdiv_Buffer *patch_arrays_buffer) override; diff --git a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc index 8a54ed653dc..5a3a2ff131c 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc @@ -191,6 +191,12 @@ void wrapSrcBuffer(struct OpenSubdiv_Evaluator *evaluator, struct OpenSubdiv_Buf evaluator->impl->eval_output->wrapSrcBuffer(src_buffer); } +void wrapSrcVertexDataBuffer(struct OpenSubdiv_Evaluator *evaluator, + struct OpenSubdiv_Buffer *src_buffer) +{ + evaluator->impl->eval_output->wrapSrcVertexDataBuffer(src_buffer); +} + void fillFVarPatchArraysBuffer(struct OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, struct OpenSubdiv_Buffer *patch_array_buffer) @@ -220,6 +226,11 @@ void wrapFVarSrcBuffer(struct OpenSubdiv_Evaluator *evaluator, evaluator->impl->eval_output->wrapFVarSrcBuffer(face_varying_channel, src_buffer); } +bool hasVertexData(struct OpenSubdiv_Evaluator *evaluator) +{ + return evaluator->impl->eval_output->hasVertexData(); +} + void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator) { evaluator->setCoarsePositions = setCoarsePositions; @@ -246,11 +257,14 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator) evaluator->wrapPatchIndexBuffer = wrapPatchIndexBuffer; evaluator->wrapPatchParamBuffer = wrapPatchParamBuffer; evaluator->wrapSrcBuffer = wrapSrcBuffer; + evaluator->wrapSrcVertexDataBuffer = wrapSrcVertexDataBuffer; evaluator->fillFVarPatchArraysBuffer = fillFVarPatchArraysBuffer; evaluator->wrapFVarPatchIndexBuffer = wrapFVarPatchIndexBuffer; evaluator->wrapFVarPatchParamBuffer = wrapFVarPatchParamBuffer; evaluator->wrapFVarSrcBuffer = wrapFVarSrcBuffer; + + evaluator->hasVertexData = hasVertexData; } } // namespace diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc index bb9e6e7bd0d..a5273cad13a 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc @@ -383,6 +383,11 @@ void EvalOutputAPI::wrapSrcBuffer(OpenSubdiv_Buffer *src_buffer) implementation_->wrapSrcBuffer(src_buffer); } +void EvalOutputAPI::wrapSrcVertexDataBuffer(OpenSubdiv_Buffer *src_buffer) +{ + implementation_->wrapSrcVertexDataBuffer(src_buffer); +} + void EvalOutputAPI::fillFVarPatchArraysBuffer(const int face_varying_channel, OpenSubdiv_Buffer *patch_arrays_buffer) { @@ -407,6 +412,11 @@ void EvalOutputAPI::wrapFVarSrcBuffer(const int face_varying_channel, implementation_->wrapFVarSrcBuffer(face_varying_channel, src_buffer); } +bool EvalOutputAPI::hasVertexData() const +{ + return implementation_->hasVertexData(); +} + } // namespace opensubdiv } // namespace blender diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.h b/intern/opensubdiv/internal/evaluator/evaluator_impl.h index 8ecfa4477be..df8ef70cc01 100644 --- a/intern/opensubdiv/internal/evaluator/evaluator_impl.h +++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.h @@ -163,6 +163,9 @@ class EvalOutputAPI { // Wrap the buffer used by OpenSubDiv for the source data with the given buffer. void wrapSrcBuffer(OpenSubdiv_Buffer *src_buffer); + // Wrap the buffer used by OpenSubDiv for the extra source data with the given buffer. + void wrapSrcVertexDataBuffer(OpenSubdiv_Buffer *src_buffer); + // Copy the patch arrays buffer used by OpenSubDiv for the face varying channel with the given // buffer. void fillFVarPatchArraysBuffer(const int face_varying_channel, @@ -181,6 +184,9 @@ class EvalOutputAPI { // Wrap thebuffer used by OpenSubDiv for the face varying channel with the given buffer. void wrapFVarSrcBuffer(const int face_varying_channel, OpenSubdiv_Buffer *src_buffer); + // Return true if source vertex data has been set. + bool hasVertexData() const; + protected: PatchMap *patch_map_; EvalOutput *implementation_; diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.h b/intern/opensubdiv/opensubdiv_evaluator_capi.h index 98e1db6e323..094244c4681 100644 --- a/intern/opensubdiv/opensubdiv_evaluator_capi.h +++ b/intern/opensubdiv/opensubdiv_evaluator_capi.h @@ -195,6 +195,10 @@ typedef struct OpenSubdiv_Evaluator { void (*wrapSrcBuffer)(struct OpenSubdiv_Evaluator *evaluator, struct OpenSubdiv_Buffer *src_buffer); + // Fill the given buffer with data from the evaluator's extra source buffer. + void (*wrapSrcVertexDataBuffer)(struct OpenSubdiv_Evaluator *evaluator, + struct OpenSubdiv_Buffer *src_buffer); + // Fill the given buffer with data from the evaluator's face varying patch array buffer. void (*fillFVarPatchArraysBuffer)(struct OpenSubdiv_Evaluator *evaluator, const int face_varying_channel, @@ -215,6 +219,9 @@ typedef struct OpenSubdiv_Evaluator { const int face_varying_channel, struct OpenSubdiv_Buffer *src_buffer); + // Return true if the evaluator has source vertex data set. + bool (*hasVertexData)(struct OpenSubdiv_Evaluator *evaluator); + // Implementation of the evaluator. struct OpenSubdiv_EvaluatorImpl *impl; |