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:
authorBrecht Van Lommel <brecht@blender.org>2021-01-14 18:33:52 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-05-18 17:45:38 +0300
commit342e12d6d92198bba8355562600a2f97bb45fed5 (patch)
treea5f1e10205e7d66e5c6672fb416883a04475782c /intern/opensubdiv
parentf517b3a29568fd43b722973c7c46d3c358ba0dda (diff)
Subdiv: support interpolating orco coordinates in subdivision surfaces
This makes changes to the opensubdiv module to support additional vertex data besides the vertex position, that is smootly interpolated the same way. This is different than varying data which is interpolated linearly. Fixes T96596: wrong generated texture coordinates with GPU subdivision. In that bug lazy subdivision would not interpolate orcos. Later on, this implementation can also be used to remove the modifier stack mechanism where modifiers are evaluated a second time for orcos, which is messy and inefficient. But that's a more risky change, this is just the part to fix the bug in 3.2. Differential Revision: https://developer.blender.org/D14973
Diffstat (limited to 'intern/opensubdiv')
-rw-r--r--intern/opensubdiv/internal/evaluator/eval_output.h64
-rw-r--r--intern/opensubdiv/internal/evaluator/eval_output_cpu.h2
-rw-r--r--intern/opensubdiv/internal/evaluator/eval_output_gpu.cc2
-rw-r--r--intern/opensubdiv/internal/evaluator/eval_output_gpu.h1
-rw-r--r--intern/opensubdiv/internal/evaluator/evaluator_capi.cc29
-rw-r--r--intern/opensubdiv/internal/evaluator/evaluator_impl.cc35
-rw-r--r--intern/opensubdiv/internal/evaluator/evaluator_impl.h9
-rw-r--r--intern/opensubdiv/opensubdiv_evaluator_capi.h20
-rw-r--r--intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc3
9 files changed, 156 insertions, 9 deletions
diff --git a/intern/opensubdiv/internal/evaluator/eval_output.h b/intern/opensubdiv/internal/evaluator/eval_output.h
index a55b89001a4..cff7c8d18c9 100644
--- a/intern/opensubdiv/internal/evaluator/eval_output.h
+++ b/intern/opensubdiv/internal/evaluator/eval_output.h
@@ -46,6 +46,8 @@ class EvalOutputAPI::EvalOutput {
virtual void updateVaryingData(const float *src, int start_vertex, int num_vertices) = 0;
+ virtual void updateVertexData(const float *src, int start_vertex, int num_vertices) = 0;
+
virtual void updateFaceVaryingData(const int face_varying_channel,
const float *src,
int start_vertex,
@@ -70,6 +72,11 @@ class EvalOutputAPI::EvalOutput {
const int num_patch_coords,
float *varying) = 0;
+ // NOTE: vertex_data must point to a memory of at least float*num_vertex_data.
+ virtual void evalPatchesVertexData(const PatchCoord *patch_coord,
+ const int num_patch_coords,
+ float *vertex_data) = 0;
+
virtual void evalPatchesFaceVarying(const int face_varying_channel,
const PatchCoord *patch_coord,
const int num_patch_coords,
@@ -331,11 +338,13 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
const StencilTable *varying_stencils,
const vector<const StencilTable *> &all_face_varying_stencils,
const int face_varying_width,
+ const int vertex_data_width,
const PatchTable *patch_table,
EvaluatorCache *evaluator_cache = NULL,
DEVICE_CONTEXT *device_context = NULL)
: src_desc_(0, 3, 3),
src_varying_desc_(0, 3, 3),
+ src_vertex_data_desc_(0, vertex_data_width, vertex_data_width),
face_varying_width_(face_varying_width),
evaluator_cache_(evaluator_cache),
device_context_(device_context)
@@ -352,6 +361,16 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
device_context_);
varying_stencils_ = convertToCompatibleStencilTable<STENCIL_TABLE>(varying_stencils,
device_context_);
+
+ // Optionally allocate additional data to be subdivided like vertex coordinates.
+ if (vertex_data_width > 0) {
+ src_vertex_data_ = SRC_VERTEX_BUFFER::Create(
+ vertex_data_width, num_total_vertices, device_context_);
+ }
+ else {
+ src_vertex_data_ = NULL;
+ }
+
// Create evaluators for every face varying channel.
face_varying_evaluators.reserve(all_face_varying_stencils.size());
int face_varying_channel = 0;
@@ -370,6 +389,7 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
{
delete src_data_;
delete src_varying_data_;
+ delete src_vertex_data_;
delete patch_table_;
delete vertex_stencils_;
delete varying_stencils_;
@@ -390,6 +410,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
src_varying_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
}
+ void updateVertexData(const float *src, int start_vertex, int num_vertices) override
+ {
+ src_vertex_data_->UpdateData(src, start_vertex, num_vertices, device_context_);
+ }
+
void updateFaceVaryingData(const int face_varying_channel,
const float *src,
int start_vertex,
@@ -426,6 +451,22 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
vertex_stencils_,
eval_instance,
device_context_);
+
+ // Evaluate smoothly interpolated vertex data.
+ if (src_vertex_data_) {
+ BufferDescriptor dst_vertex_data_desc = src_vertex_data_desc_;
+ dst_vertex_data_desc.offset += num_coarse_vertices_ * src_vertex_data_desc_.stride;
+ const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
+ evaluator_cache_, src_vertex_data_desc_, dst_vertex_data_desc, device_context_);
+ EVALUATOR::EvalStencils(src_vertex_data_,
+ src_vertex_data_desc_,
+ src_vertex_data_,
+ dst_vertex_data_desc,
+ vertex_stencils_,
+ eval_instance,
+ device_context_);
+ }
+
// Evaluate varying data.
if (hasVaryingData()) {
BufferDescriptor dst_varying_desc = src_varying_desc_;
@@ -521,6 +562,27 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
device_context_);
}
+ // NOTE: data must point to a memory of at least float*num_vertex_data.
+ void evalPatchesVertexData(const PatchCoord *patch_coord,
+ const int num_patch_coords,
+ float *data) override
+ {
+ RawDataWrapperBuffer<float> vertex_data(data);
+ BufferDescriptor vertex_desc(0, src_vertex_data_desc_.length, src_vertex_data_desc_.length);
+ ConstPatchCoordWrapperBuffer patch_coord_buffer(patch_coord, num_patch_coords);
+ const EVALUATOR *eval_instance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
+ evaluator_cache_, src_vertex_data_desc_, vertex_desc, device_context_);
+ EVALUATOR::EvalPatches(src_vertex_data_,
+ src_vertex_data_desc_,
+ &vertex_data,
+ vertex_desc,
+ patch_coord_buffer.GetNumVertices(),
+ &patch_coord_buffer,
+ patch_table_,
+ eval_instance,
+ device_context_);
+ }
+
void evalPatchesFaceVarying(const int face_varying_channel,
const PatchCoord *patch_coord,
const int num_patch_coords,
@@ -560,9 +622,11 @@ class VolatileEvalOutput : public EvalOutputAPI::EvalOutput {
private:
SRC_VERTEX_BUFFER *src_data_;
SRC_VERTEX_BUFFER *src_varying_data_;
+ SRC_VERTEX_BUFFER *src_vertex_data_;
PATCH_TABLE *patch_table_;
BufferDescriptor src_desc_;
BufferDescriptor src_varying_desc_;
+ BufferDescriptor src_vertex_data_desc_;
int num_coarse_vertices_;
diff --git a/intern/opensubdiv/internal/evaluator/eval_output_cpu.h b/intern/opensubdiv/internal/evaluator/eval_output_cpu.h
index 58bae7a322e..2b3c738d6ab 100644
--- a/intern/opensubdiv/internal/evaluator/eval_output_cpu.h
+++ b/intern/opensubdiv/internal/evaluator/eval_output_cpu.h
@@ -44,6 +44,7 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
const StencilTable *varying_stencils,
const vector<const StencilTable *> &all_face_varying_stencils,
const int face_varying_width,
+ const int vertex_data_width,
const PatchTable *patch_table,
EvaluatorCache *evaluator_cache = NULL)
: VolatileEvalOutput<CpuVertexBuffer,
@@ -54,6 +55,7 @@ class CpuEvalOutput : public VolatileEvalOutput<CpuVertexBuffer,
varying_stencils,
all_face_varying_stencils,
face_varying_width,
+ vertex_data_width,
patch_table,
evaluator_cache)
{
diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc
index b352ed2c014..566071d581b 100644
--- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc
+++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.cc
@@ -45,6 +45,7 @@ GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils,
const StencilTable *varying_stencils,
const vector<const StencilTable *> &all_face_varying_stencils,
const int face_varying_width,
+ const int vertex_data_width,
const PatchTable *patch_table,
VolatileEvalOutput::EvaluatorCache *evaluator_cache)
: VolatileEvalOutput<GLVertexBuffer,
@@ -55,6 +56,7 @@ GpuEvalOutput::GpuEvalOutput(const StencilTable *vertex_stencils,
varying_stencils,
all_face_varying_stencils,
face_varying_width,
+ vertex_data_width,
patch_table,
evaluator_cache)
{
diff --git a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
index dc137e4322e..2306a87b87c 100644
--- a/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
+++ b/intern/opensubdiv/internal/evaluator/eval_output_gpu.h
@@ -40,6 +40,7 @@ class GpuEvalOutput : public VolatileEvalOutput<GLVertexBuffer,
const StencilTable *varying_stencils,
const vector<const StencilTable *> &all_face_varying_stencils,
const int face_varying_width,
+ const int vertex_data_width,
const PatchTable *patch_table,
EvaluatorCache *evaluator_cache = NULL);
diff --git a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc
index 567afd3a763..8a54ed653dc 100644
--- a/intern/opensubdiv/internal/evaluator/evaluator_capi.cc
+++ b/intern/opensubdiv/internal/evaluator/evaluator_capi.cc
@@ -36,6 +36,14 @@ void setCoarsePositions(OpenSubdiv_Evaluator *evaluator,
evaluator->impl->eval_output->setCoarsePositions(positions, start_vertex_index, num_vertices);
}
+void setVertexData(OpenSubdiv_Evaluator *evaluator,
+ const float *vertex_data,
+ const int start_vertex_index,
+ const int num_vertices)
+{
+ evaluator->impl->eval_output->setVertexData(vertex_data, start_vertex_index, num_vertices);
+}
+
void setVaryingData(OpenSubdiv_Evaluator *evaluator,
const float *varying_data,
const int start_vertex_index,
@@ -115,6 +123,15 @@ void evaluatePatchesLimit(OpenSubdiv_Evaluator *evaluator,
patch_coords, num_patch_coords, P, dPdu, dPdv);
}
+void evaluateVertexData(OpenSubdiv_Evaluator *evaluator,
+ const int ptex_face_index,
+ float face_u,
+ float face_v,
+ float vertex_data[3])
+{
+ evaluator->impl->eval_output->evaluateVertexData(ptex_face_index, face_u, face_v, vertex_data);
+}
+
void evaluateVarying(OpenSubdiv_Evaluator *evaluator,
const int ptex_face_index,
float face_u,
@@ -206,6 +223,7 @@ void wrapFVarSrcBuffer(struct OpenSubdiv_Evaluator *evaluator,
void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
{
evaluator->setCoarsePositions = setCoarsePositions;
+ evaluator->setVertexData = setVertexData;
evaluator->setVaryingData = setVaryingData;
evaluator->setFaceVaryingData = setFaceVaryingData;
@@ -217,6 +235,7 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
evaluator->evaluateLimit = evaluateLimit;
evaluator->evaluateVarying = evaluateVarying;
+ evaluator->evaluateVertexData = evaluateVertexData;
evaluator->evaluateFaceVarying = evaluateFaceVarying;
evaluator->evaluatePatchesLimit = evaluatePatchesLimit;
@@ -239,12 +258,16 @@ void assignFunctionPointers(OpenSubdiv_Evaluator *evaluator)
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
OpenSubdiv_TopologyRefiner *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
- OpenSubdiv_EvaluatorCache *evaluator_cache)
+ OpenSubdiv_EvaluatorCache *evaluator_cache,
+ const OpenSubdiv_EvaluatorSettings *settings)
{
OpenSubdiv_Evaluator *evaluator = MEM_new<OpenSubdiv_Evaluator>(__func__);
assignFunctionPointers(evaluator);
- evaluator->impl = openSubdiv_createEvaluatorInternal(
- topology_refiner, evaluator_type, evaluator_cache ? evaluator_cache->impl : nullptr);
+ evaluator->impl = openSubdiv_createEvaluatorInternal(topology_refiner,
+ evaluator_type,
+ evaluator_cache ? evaluator_cache->impl :
+ nullptr,
+ settings);
evaluator->type = evaluator->impl ? evaluator_type : static_cast<eOpenSubdivEvaluator>(0);
return evaluator;
}
diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc
index 755b8bfbc81..bb9e6e7bd0d 100644
--- a/intern/opensubdiv/internal/evaluator/evaluator_impl.cc
+++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.cc
@@ -182,6 +182,14 @@ void EvalOutputAPI::setVaryingData(const float *varying_data,
implementation_->updateVaryingData(varying_data, start_vertex_index, num_vertices);
}
+void EvalOutputAPI::setVertexData(const float *vertex_data,
+ const int start_vertex_index,
+ const int num_vertices)
+{
+ // TODO(sergey): Add sanity check on indices.
+ implementation_->updateVertexData(vertex_data, start_vertex_index, num_vertices);
+}
+
void EvalOutputAPI::setFaceVaryingData(const int face_varying_channel,
const float *face_varying_data,
const int start_vertex_index,
@@ -286,6 +294,20 @@ void EvalOutputAPI::evaluateVarying(const int ptex_face_index,
implementation_->evalPatchesVarying(&patch_coord, 1, varying);
}
+void EvalOutputAPI::evaluateVertexData(const int ptex_face_index,
+ float face_u,
+ float face_v,
+ float vertex_data[])
+{
+ assert(face_u >= 0.0f);
+ assert(face_u <= 1.0f);
+ assert(face_v >= 0.0f);
+ assert(face_v <= 1.0f);
+ const PatchTable::PatchHandle *handle = patch_map_->FindPatch(ptex_face_index, face_u, face_v);
+ PatchCoord patch_coord(*handle, face_u, face_v);
+ implementation_->evalPatchesVertexData(&patch_coord, 1, vertex_data);
+}
+
void EvalOutputAPI::evaluateFaceVarying(const int face_varying_channel,
const int ptex_face_index,
float face_u,
@@ -403,7 +425,8 @@ OpenSubdiv_EvaluatorImpl::~OpenSubdiv_EvaluatorImpl()
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
OpenSubdiv_TopologyRefiner *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
- OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr)
+ OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr,
+ const OpenSubdiv_EvaluatorSettings *settings)
{
// Only CPU and GLCompute are implemented at the moment.
if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU &&
@@ -422,6 +445,7 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
const bool has_face_varying_data = (num_face_varying_channels != 0);
const int level = topology_refiner->getSubdivisionLevel(topology_refiner);
const bool is_adaptive = topology_refiner->getIsAdaptive(topology_refiner);
+ const int vertex_data_width = settings->num_vertex_data;
// Common settings for stencils and patches.
const bool stencil_generate_intermediate_levels = is_adaptive;
const bool stencil_generate_offsets = true;
@@ -526,12 +550,17 @@ OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
varying_stencils,
all_face_varying_stencils,
2,
+ vertex_data_width,
patch_table,
evaluator_cache);
}
else {
- eval_output = new blender::opensubdiv::CpuEvalOutput(
- vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
+ eval_output = new blender::opensubdiv::CpuEvalOutput(vertex_stencils,
+ varying_stencils,
+ all_face_varying_stencils,
+ 2,
+ vertex_data_width,
+ patch_table);
}
blender::opensubdiv::PatchMap *patch_map = new blender::opensubdiv::PatchMap(*patch_table);
diff --git a/intern/opensubdiv/internal/evaluator/evaluator_impl.h b/intern/opensubdiv/internal/evaluator/evaluator_impl.h
index e24d47cba79..8ecfa4477be 100644
--- a/intern/opensubdiv/internal/evaluator/evaluator_impl.h
+++ b/intern/opensubdiv/internal/evaluator/evaluator_impl.h
@@ -32,6 +32,7 @@
struct OpenSubdiv_Buffer;
struct OpenSubdiv_EvaluatorCacheImpl;
+struct OpenSubdiv_EvaluatorSettings;
struct OpenSubdiv_PatchCoord;
struct OpenSubdiv_TopologyRefiner;
@@ -60,6 +61,8 @@ class EvalOutputAPI {
void setCoarsePositions(const float *positions,
const int start_vertex_index,
const int num_vertices);
+ // Set vertex data from a continuous array of data.
+ void setVertexData(const float *data, const int start_vertex_index, const int num_vertices);
// Set varying data from a continuous array of data.
void setVaryingData(const float *varying_data,
const int start_vertex_index,
@@ -115,6 +118,9 @@ class EvalOutputAPI {
float dPdv[3]);
// Evaluate varying data at a given bilinear coordinate of given ptex face.
+ void evaluateVertexData(const int ptes_face_index, float face_u, float face_v, float data[]);
+
+ // Evaluate varying data at a given bilinear coordinate of given ptex face.
void evaluateVarying(const int ptes_face_index, float face_u, float face_v, float varying[3]);
// Evaluate facee-varying data at a given bilinear coordinate of given
@@ -198,7 +204,8 @@ struct OpenSubdiv_EvaluatorImpl {
OpenSubdiv_EvaluatorImpl *openSubdiv_createEvaluatorInternal(
struct OpenSubdiv_TopologyRefiner *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
- OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr);
+ OpenSubdiv_EvaluatorCacheImpl *evaluator_cache_descr,
+ const OpenSubdiv_EvaluatorSettings *settings);
void openSubdiv_deleteEvaluatorInternal(OpenSubdiv_EvaluatorImpl *evaluator);
diff --git a/intern/opensubdiv/opensubdiv_evaluator_capi.h b/intern/opensubdiv/opensubdiv_evaluator_capi.h
index 1afd3e966f6..98e1db6e323 100644
--- a/intern/opensubdiv/opensubdiv_evaluator_capi.h
+++ b/intern/opensubdiv/opensubdiv_evaluator_capi.h
@@ -69,6 +69,11 @@ typedef struct OpenSubdiv_Evaluator {
const float *positions,
const int start_vertex_index,
const int num_vertices);
+ // Set vertex data from a continuous array of coordinates.
+ void (*setVertexData)(struct OpenSubdiv_Evaluator *evaluator,
+ const float *data,
+ const int start_vertex_index,
+ const int num_vertices);
// Set varying data from a continuous array of data.
void (*setVaryingData)(struct OpenSubdiv_Evaluator *evaluator,
const float *varying_data,
@@ -129,6 +134,13 @@ typedef struct OpenSubdiv_Evaluator {
float dPdu[3],
float dPdv[3]);
+ // Evaluate vertex data at a given bilinear coordinate of given ptex face.
+ void (*evaluateVertexData)(struct OpenSubdiv_Evaluator *evaluator,
+ const int ptex_face_index,
+ float face_u,
+ float face_v,
+ float data[]);
+
// Evaluate varying data at a given bilinear coordinate of given ptex face.
void (*evaluateVarying)(struct OpenSubdiv_Evaluator *evaluator,
const int ptex_face_index,
@@ -215,10 +227,16 @@ typedef struct OpenSubdiv_EvaluatorCache {
struct OpenSubdiv_EvaluatorCacheImpl *impl;
} OpenSubdiv_EvaluatorCache;
+typedef struct OpenSubdiv_EvaluatorSettings {
+ // Number of smoothly interpolated vertex data channels.
+ int num_vertex_data;
+} OpenSubdiv_EvaluatorSettings;
+
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
struct OpenSubdiv_TopologyRefiner *topology_refiner,
eOpenSubdivEvaluator evaluator_type,
- OpenSubdiv_EvaluatorCache *evaluator_cache);
+ OpenSubdiv_EvaluatorCache *evaluator_cache,
+ const OpenSubdiv_EvaluatorSettings *settings);
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator);
diff --git a/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc b/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc
index bc39326b57d..78c1d23d2cc 100644
--- a/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc
+++ b/intern/opensubdiv/stub/opensubdiv_evaluator_stub.cc
@@ -23,7 +23,8 @@
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
struct OpenSubdiv_TopologyRefiner * /*topology_refiner*/,
eOpenSubdivEvaluator /*evaluator_type*/,
- OpenSubdiv_EvaluatorCache * /*evaluator_cache*/)
+ OpenSubdiv_EvaluatorCache * /*evaluator_cache*/,
+ const OpenSubdiv_EvaluatorSettings * /*settings*/)
{
return NULL;
}