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:
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc73
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h13
-rw-r--r--intern/opensubdiv/opensubdiv_converter.cc72
-rw-r--r--intern/opensubdiv/opensubdiv_converter_capi.h8
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc129
-rw-r--r--intern/opensubdiv/opensubdiv_topology_refiner.h6
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c3
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_intern.h5
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c6
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c103
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c84
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c5
12 files changed, 403 insertions, 104 deletions
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 0463982fdf6..e04b23725b1 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -67,6 +67,7 @@
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/far/primvarRefiner.h>
#include "opensubdiv_intern.h"
#include "opensubdiv_topology_refiner.h"
@@ -143,11 +144,69 @@ typedef Mesh<GLVertexBuffer,
GLPatchTable> OsdGLSLComputeMesh;
#endif
+namespace {
+
+struct FVarVertex {
+ float u, v;
+ void Clear() {
+ u = v = 0.0f;
+ }
+ void AddWithWeight(FVarVertex const & src, float weight) {
+ u += weight * src.u;
+ v += weight * src.v;
+ }
+};
+
+static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float> uvs,
+ std::vector<float> &fvar_data) {
+ /* TODO(sergey): Support all FVar channels. */
+ const int channel = 0;
+ /* TODO(sergey): Make it somehow more generic way. */
+ const int fvar_width = 2;
+
+ int max_level = refiner.GetMaxLevel(),
+ num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
+ num_values_total = refiner.GetNumFVarValuesTotal(channel);
+ if (num_values_total <= 0) {
+ return;
+ }
+ OpenSubdiv::Far::PrimvarRefiner primvarRefiner(refiner);
+ if (refiner.IsUniform()) {
+ /* For uniform we only keep the highest level of refinement. */
+ fvar_data.resize(num_values_max * fvar_width);
+ std::vector<FVarVertex> buffer(num_values_total - num_values_max);
+ FVarVertex *src = &buffer[0];
+ memcpy(src, &uvs[0], uvs.size() * sizeof(float));
+ /* Defer the last level to treat separately with its alternate
+ * destination.
+ */
+ for (int level = 1; level < max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
+ primvarRefiner.InterpolateFaceVarying(max_level, src, dst, channel);
+ } else {
+ /* For adaptive we keep all levels. */
+ fvar_data.resize(num_values_total * fvar_width);
+ FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[0]);
+ memcpy(src, &uvs[0], uvs.size() * sizeof(float));
+ for (int level = 1; level <= max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvarRefiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ }
+}
+
+} // namespace
+
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int /*subdivide_uvs*/)
+ int level)
{
using OpenSubdiv::Far::TopologyRefiner;
@@ -213,11 +272,21 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
gl_mesh->topology_refiner = topology_refiner;
+ if (refiner->GetNumFVarChannels() > 0) {
+ std::vector<float> fvar_data;
+ interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
+ openSubdiv_osdGLAllocFVar(gl_mesh, &fvar_data[0]);
+ }
+ else {
+ gl_mesh->fvar_data = NULL;
+ }
+
return gl_mesh;
}
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
{
+ openSubdiv_osdGLDestroyFVar(gl_mesh);
switch (gl_mesh->evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
case OPENSUBDIV_EVALUATOR_ ## type: \
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index b40505b197d..0410083304e 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -32,16 +32,19 @@ extern "C" {
// Types declaration.
struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_GLMeshFVarData;
struct OpenSubdiv_TopologyRefinerDescr;
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
#ifdef __cplusplus
struct OpenSubdiv_GLMeshDescr;
+
typedef struct OpenSubdiv_GLMesh {
int evaluator_type;
OpenSubdiv_GLMeshDescr *descriptor;
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_GLMeshFVarData *fvar_data;
} OpenSubdiv_GLMesh;
#endif
@@ -66,8 +69,7 @@ enum {
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int subdivide_uvs);
+ int level);
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
@@ -129,8 +131,7 @@ void openSubdiv_evaluateVarying(OpenSubdiv_EvaluatorDescr *evaluator_descr,
*
* TODO(sergey): Some of the stuff could be initialized once for all meshes.
*/
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
- int active_uv_index);
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl);
/* Draw specified patches. */
void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
@@ -138,6 +139,10 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
int start_patch,
int num_patches);
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data);
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
+
/* ** Utility functions ** */
int openSubdiv_supportGPUDisplay(void);
int openSubdiv_getAvailableEvaluators(void);
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index e718d6b4dc8..e6c8985e947 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -488,6 +488,39 @@ inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
printf("OpenSubdiv Error: %s\n", msg);
}
+template <>
+inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignFaceVaryingTopology(
+ TopologyRefiner& refiner,
+ const OpenSubdiv_Converter& conv)
+{
+ if (conv.get_num_uv_layers(&conv) <= 0) {
+ /* No UV maps, we can skip any face-varying data. */
+ return true;
+ }
+ /* Count overall number of UV data.
+ * NOTE: We only do single UV layer here, and we don't "merge" loops
+ * together as it is done in OpenSubdiv examples.x
+ */
+ const int num_faces = getNumBaseFaces(refiner);
+ int num_uvs = 0;
+ for (int face = 0; face < num_faces; ++face) {
+ IndexArray face_verts = getBaseFaceVertices(refiner, face);
+ num_uvs += face_verts.size();
+ }
+ /* Fill in actual UV offsets. */
+ const int channel = createBaseFVarChannel(refiner, num_uvs);
+ for (int face = 0, offset = 0; face < num_faces; ++face) {
+ Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
+ face,
+ channel);
+ for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
+ dst_face_uvs[corner] = offset;
+ ++offset;
+ }
+ }
+ return true;
+}
+
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -508,6 +541,33 @@ OpenSubdiv::Sdc::SchemeType get_capi_scheme_type(OpenSubdiv_SchemeType type)
return OpenSubdiv::Sdc::SCHEME_CATMARK;
}
+static void import_fvar_data(OpenSubdiv_TopologyRefinerDescr *result,
+ const OpenSubdiv_Converter& conv)
+{
+ const int num_layers = conv.get_num_uv_layers(&conv),
+ num_faces = conv.get_num_faces(&conv);
+ /* Pre-allocate values in one go. */
+ int num_fvar_values = 0;
+ for (int layer = 0; layer < num_layers; ++layer) {
+ num_fvar_values = result->osd_refiner->GetNumFVarValuesTotal();
+ }
+ result->uvs.resize(num_fvar_values * 2);
+ /* Fill in all channels. */
+ for (int layer = 0, offset = 0; layer < num_layers; ++layer) {
+ for (int face = 0; face < num_faces; ++face) {
+ const int num_verts = conv.get_num_face_verts(&conv, face);
+ for (int vert = 0; vert < num_verts; ++vert) {
+ float uv[2];
+ conv.get_face_corner_uv(&conv, face, vert, uv);
+ result->uvs[offset++] = uv[0];
+ result->uvs[offset++] = uv[1];
+ }
+ }
+ /* TODO(sergey): Currently we only support first layer only. */
+ break;
+ }
+}
+
} /* namespace */
struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
@@ -536,6 +596,18 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
*converter,
topology_options);
+
+ if (result->osd_refiner->GetNumFVarChannels() > 0) {
+ /* Import face varrying data now since later we wouldn't have
+ * access to the converter.
+ *
+ * TODO(sergey): This is so-called "for now", for until we'll
+ * find better way to plug OSD to Blender or for until something
+ * happens inside of OSD API.
+ */
+ import_fvar_data(result, *converter);
+ }
+
return result;
}
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index 1f09fa074d8..47c8dab49de 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -83,6 +83,14 @@ typedef struct OpenSubdiv_Converter {
int vert,
int *vert_faces);
+ /* Face-varying data. */
+
+ int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
+ void (*get_face_corner_uv)(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner,
+ float r_uv[2]);
+
void (*free_user_data)(const OpenSubdiv_Converter *converter);
void *user_data;
} OpenSubdiv_Converter;
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 63cf390276f..84984e8bd7e 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -42,6 +42,10 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <opensubdiv/osd/cpuEvaluator.h>
+#include "MEM_guardedalloc.h"
+
+#include "opensubdiv_capi.h"
+
using OpenSubdiv::Osd::GLMeshInterface;
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
@@ -78,7 +82,6 @@ typedef struct Transform {
} Transform;
static bool g_use_osd_glsl = false;
-static int g_active_uv_index = -1;
static GLuint g_flat_fill_solid_program = 0;
static GLuint g_flat_fill_texture2d_program = 0;
@@ -90,6 +93,59 @@ static GLuint g_lighting_ub = 0;
static Lighting g_lighting_data;
static Transform g_transform;
+struct OpenSubdiv_GLMeshFVarData
+{
+ OpenSubdiv_GLMeshFVarData() :
+ texture_buffer(0) {
+ }
+
+ ~OpenSubdiv_GLMeshFVarData()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ if (texture_buffer) {
+ glDeleteTextures(1, &texture_buffer);
+ }
+ texture_buffer = 0;
+ }
+
+ void Create(const OpenSubdiv::Far::PatchTable *patch_table,
+ int fvarWidth,
+ const float *fvar_src_data)
+ {
+ Release();
+ OpenSubdiv::Far::ConstIndexArray indices = patch_table->GetFVarValues();
+
+ // expand fvardata to per-patch array
+ std::vector<float> data;
+ data.reserve(indices.size() * fvarWidth);
+
+ for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
+ int index = indices[fvert] * fvarWidth;
+ for (int i = 0; i < fvarWidth; ++i) {
+ data.push_back(fvar_src_data[index++]);
+ }
+ }
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
+ &data[0], GL_STATIC_DRAW);
+
+ glGenTextures(1, &texture_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glDeleteBuffers(1, &buffer);
+ }
+ GLuint texture_buffer;
+};
+
/* TODO(sergey): This is actually duplicated code from BLI. */
namespace {
void copy_m3_m3(float m1[3][3], float m2[3][3])
@@ -307,8 +363,7 @@ GLuint linkProgram(const char *version, const char *define)
return program;
}
-void bindProgram(GLMeshInterface * /*mesh*/,
- int program)
+void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
{
glUseProgram(program);
@@ -352,23 +407,16 @@ void bindProgram(GLMeshInterface * /*mesh*/,
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
}
- /* TODO(sergey): Bring face varying back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
+ if (gl_mesh->fvar_data != NULL && gl_mesh->fvar_data->texture_buffer) {
glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
glActiveTexture(GL_TEXTURE0);
}
-#endif
-
- /* TODO(sergey): Bring face varying back. */
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
- 0/* * mesh->GetFVarCount()*/);
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- g_active_uv_index * 2);
+ /* See notes below about why we use such values. */
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 2);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
} /* namespace */
@@ -455,11 +503,9 @@ void openSubdiv_osdGLDisplayDeinit(void)
}
}
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
- int active_uv_index)
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl)
{
g_use_osd_glsl = use_osd_glsl != 0;
- g_active_uv_index = active_uv_index;
/* Update transformation matrices. */
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@@ -516,7 +562,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
}
}
-static GLuint prepare_patchDraw(GLMeshInterface *mesh,
+static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
bool fill_quads)
{
GLint program = 0;
@@ -531,28 +577,31 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
glUniform1i(location, model == GL_FLAT);
}
- /* TODO(sergey): Bring this back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
+ if (gl_mesh->fvar_data != NULL &&
+ gl_mesh->fvar_data->texture_buffer)
+ {
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
+ gl_mesh->fvar_data->texture_buffer);
glActiveTexture(GL_TEXTURE0);
GLint location = glGetUniformLocation(program, "osd_fvar_count");
if (location != -1) {
- glUniform1i(location, mesh->GetFVarCount());
+ /* TODO(sergey): This is width of FVar data, which happened to be 2. */
+ glUniform1i(location, 2);
}
location = glGetUniformLocation(program, "osd_active_uv_offset");
if (location != -1) {
- glUniform1i(location,
- g_active_uv_index * 2);
+ /* TODO(sergey): Since we only store single UV channel
+ * we can always suuppose offset is 0.
+ *
+ * Ideally it should be active UV index times 2.
+ */
+ glUniform1i(location, 0);
}
}
-#endif
-
}
return program;
}
@@ -584,7 +633,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
program = g_wireframe_program;
}
- bindProgram(mesh, program);
+ bindProgram(gl_mesh, program);
return program;
}
@@ -645,7 +694,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
const int num_draw_patches = std::min(num_remained_patches,
num_block_patches - start_draw_patch);
perform_drawElements(program,
- i,
+ i + start_draw_patch,
num_draw_patches * num_control_verts,
patch.GetIndexBase() + start_draw_patch * num_control_verts);
num_remained_patches -= num_draw_patches;
@@ -691,7 +740,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
}
/* Setup GLSL/OpenGL to draw patches in current context. */
- GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
+ GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
if (start_patch != -1) {
draw_partition_patches_range(mesh,
@@ -706,3 +755,21 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
/* Finish patch drawing by restoring all changes to the OpenGL context. */
finish_patchDraw(fill_quads != 0);
}
+
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data)
+{
+ GLMeshInterface *mesh =
+ (GLMeshInterface *)(gl_mesh->descriptor);
+ gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
+ gl_mesh->fvar_data->Create(mesh->GetFarPatchTable(),
+ 2,
+ fvar_data);
+}
+
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
+{
+ if (gl_mesh->fvar_data != NULL) {
+ OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
+ }
+}
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner.h b/intern/opensubdiv/opensubdiv_topology_refiner.h
index 5c299ac5df5..b00f6a54201 100644
--- a/intern/opensubdiv/opensubdiv_topology_refiner.h
+++ b/intern/opensubdiv/opensubdiv_topology_refiner.h
@@ -30,6 +30,12 @@
typedef struct OpenSubdiv_TopologyRefinerDescr {
OpenSubdiv::Far::TopologyRefiner *osd_refiner;
+
+ /* TODO(sergey): For now only, need to find better place
+ * after revisiting whole OSD drawing pipeline and Blender
+ * integration.
+ */
+ std::vector<float> uvs;
} OpenSubdiv_TopologyRefinerDescr;
#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 828a6bb16ac..c4886a21740 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -313,9 +313,6 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a
ss->osd_vao = 0;
ss->skip_grids = false;
ss->osd_compute = 0;
- ss->osd_uvs_invalid = true;
- ss->osd_subsurf_uv = 0;
- ss->osd_uv_index = -1;
ss->osd_next_face_ptex_index = 0;
ss->osd_coarse_coords = NULL;
ss->osd_num_coarse_coords = 0;
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
index 0cdf3acf075..7e8059e62fc 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_intern.h
+++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h
@@ -254,11 +254,6 @@ struct CCGSubSurf {
* to fill in PTex index of CCGFace.
*/
int osd_next_face_ptex_index;
-
- /* ** Needs review. ** */
- bool osd_subsurf_uv;
- int osd_uv_index;
- bool osd_uvs_invalid;
#endif
};
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index 2bb55c2d1ed..c715c1fa1ee 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -190,7 +190,6 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm)
/* ** Make sure both GPU and CPU backends are properly reset. ** */
ss->osd_coarse_coords_invalid = true;
- ss->osd_uvs_invalid = true;
/* Reset GPU part. */
ss->osd_mesh_invalid = true;
@@ -256,8 +255,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner(
ss->osd_topology_refiner,
compute_type,
- ss->subdivLevels,
- ss->osd_subsurf_uv);
+ ss->subdivLevels);
ss->osd_topology_refiner = NULL;
if (UNLIKELY(ss->osd_mesh == NULL)) {
@@ -290,7 +288,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
ss->osd_coarse_coords_invalid = false;
}
- openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
+ openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl);
return true;
}
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
index c4317f4d740..72e5f9f1346 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
@@ -62,6 +62,11 @@ typedef struct ConvDMStorage {
*vert_poly_mem,
*edge_poly_mem;
#endif
+
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mpoly;
+ MLoopUV *mloopuv;
} ConvDMStorage;
static OpenSubdiv_SchemeType conv_dm_get_type(
@@ -99,9 +104,7 @@ static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
int face)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
return mpoly->totloop;
}
@@ -110,13 +113,10 @@ static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
int *face_verts)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- face_verts[loop] = ml[mpoly->loopstart + loop].v;
+ face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v;
}
}
@@ -125,13 +125,10 @@ static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
int *face_edges)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
- const MPoly *mpoly = &mp[face];
+ const MPoly *mpoly = &storage->mpoly[face];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- face_edges[loop] = ml[mpoly->loopstart + loop].e;
+ face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e;
}
}
@@ -140,9 +137,7 @@ static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
int *edge_verts)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &storage->medge[edge];
edge_verts[0] = medge->v1;
edge_verts[1] = medge->v2;
}
@@ -153,14 +148,12 @@ static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
++num;
break;
@@ -180,14 +173,12 @@ static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->e == edge) {
edge_faces[num++] = poly;
break;
@@ -205,9 +196,8 @@ static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
int edge)
{
ConvDMStorage *storage = converter->user_data;
- DerivedMesh *dm = storage->dm;
CCGSubSurf *ss = storage->ss;
- const MEdge *medge = dm->getEdgeArray(dm);
+ const MEdge *medge = storage->medge;
return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
}
@@ -217,10 +207,9 @@ static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
++num;
}
@@ -238,10 +227,9 @@ static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MEdge *me = dm->getEdgeArray(dm);
int num = 0, edge;
for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
- const MEdge *medge = &me[edge];
+ const MEdge *medge = &user_data->medge[edge];
if (medge->v1 == vert || medge->v2 == vert) {
vert_edges[num++] = edge;
}
@@ -259,14 +247,12 @@ static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &user_data->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
++num;
break;
@@ -286,14 +272,12 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
ConvDMStorage *storage = converter->user_data;
#ifndef USE_MESH_ELEMENT_MAPPING
DerivedMesh *dm = storage->dm;
- const MLoop *ml = dm->getLoopArray(dm);
- const MPoly *mp = dm->getPolyArray(dm);
int num = 0, poly;
for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
- const MPoly *mpoly = &mp[poly];
+ const MPoly *mpoly = &storage->mpoly[poly];
int loop;
for (loop = 0; loop < mpoly->totloop; loop++) {
- const MLoop *mloop = &ml[mpoly->loopstart + loop];
+ const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
if (mloop->v == vert) {
vert_faces[num++] = poly;
break;
@@ -307,6 +291,24 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
#endif
}
+static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter)
+{
+ ConvDMStorage *storage = converter->user_data;
+ DerivedMesh *dm = storage->dm;
+ return CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
+}
+
+static void conv_dm_get_face_corner_uv(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner,
+ float r_uv[2])
+{
+ ConvDMStorage *storage = converter->user_data;
+ MPoly *mpoly = &storage->mpoly[face];
+ MLoopUV *mloopuv = &storage->mloopuv[mpoly->loopstart + corner];
+ copy_v2_v2(r_uv, mloopuv->uv);
+}
+
static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
{
ConvDMStorage *user_data = converter->user_data;
@@ -348,9 +350,18 @@ void ccgSubSurf_converter_setup_from_derivedmesh(
converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
converter->get_vert_faces = conv_dm_get_vert_faces;
+ converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
+ converter->get_face_corner_uv = conv_dm_get_face_corner_uv;
+
user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
user_data->ss = ss;
user_data->dm = dm;
+
+ user_data->medge = dm->getEdgeArray(dm);
+ user_data->mloop = dm->getLoopArray(dm);
+ user_data->mpoly = dm->getPolyArray(dm);
+ user_data->mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV);
+
converter->free_user_data = conv_dm_free_user_data;
converter->user_data = user_data;
@@ -548,6 +559,19 @@ static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
}
}
+static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter))
+{
+ return 0;
+}
+
+static void conv_ccg_get_face_corner_uv(const OpenSubdiv_Converter * UNUSED(converter),
+ int UNUSED(face),
+ int UNUSED(corner),
+ float r_uv[2])
+{
+ zero_v2(r_uv);
+}
+
void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
OpenSubdiv_Converter *converter)
{
@@ -571,6 +595,9 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
converter->get_vert_faces = conv_ccg_get_vert_faces;
+ converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
+ converter->get_face_corner_uv = conv_ccg_get_face_corner_uv;
+
converter->free_user_data = NULL;
converter->user_data = ss;
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index f73dbd8078f..b9efe23a4b3 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3386,19 +3386,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
int mat_index;
int tot_element, start_element, tot_drawn;
-#ifdef WITH_OPENSUBDIV
- if (ccgdm->useGpuBackend) {
- if (ccgSubSurf_prepareGLMesh(ss, true) == false) {
- return;
- }
- ccgSubSurf_drawGLMesh(ss, true, -1, -1);
- return;
- }
-#endif
-
- CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
-
if (use_colors) {
colType = CD_TEXTURE_MLOOPCOL;
mloopcol = dm->getLoopDataArray(dm, colType);
@@ -3412,6 +3399,77 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
}
}
+#ifdef WITH_OPENSUBDIV
+ if (ccgdm->useGpuBackend) {
+ if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) {
+ return;
+ }
+ if (drawParams == NULL) {
+ ccgSubSurf_drawGLMesh(ss, true, -1, -1);
+ return;
+ }
+ const int level = ccgSubSurf_getSubdivisionLevels(ss);
+ const int face_side = 1 << level;
+ const int grid_side = 1 << (level - 1);
+ const int face_patches = face_side * face_side;
+ const int grid_patches = grid_side * grid_side;
+ const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
+ int current_patch = 0;
+ int mat_nr = -1;
+ int start_draw_patch = 0, num_draw_patches = 0;
+ for (i = 0; i < num_base_faces; ++i) {
+ const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
+ const int num_patches = (num_face_verts == 4) ? face_patches
+ : num_face_verts * grid_patches;
+ if (faceFlags) {
+ mat_nr = faceFlags[i].mat_nr + 1;
+ }
+ else {
+ mat_nr = 0;
+ }
+
+ if (drawParams != NULL) {
+ MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL;
+ draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
+ }
+ else {
+ draw_option = (drawParamsMapped)
+ ? drawParamsMapped(userData, i, mat_nr)
+ : DM_DRAW_OPTION_NORMAL;
+ }
+
+ flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1);
+
+ if (!flush && compareDrawOptions) {
+ flush |= compareDrawOptions(userData, i, min_ii(i + 1, num_base_faces - 1)) == 0;
+ }
+
+ current_patch += num_patches;
+
+ if (flush) {
+ if (draw_option != DM_DRAW_OPTION_SKIP) {
+ num_draw_patches += num_patches;
+ }
+ if (num_draw_patches != 0) {
+ ccgSubSurf_drawGLMesh(ss,
+ true,
+ start_draw_patch,
+ num_draw_patches);
+ }
+ start_draw_patch = current_patch;
+ num_draw_patches = 0;
+ }
+ else {
+ num_draw_patches += num_patches;
+ }
+ }
+ return;
+ }
+#endif
+
+ CCG_key_top_level(&key, ss);
+ ccgdm_pbvh_update(ccgdm);
+
GPU_vertex_setup(dm);
GPU_normal_setup(dm);
GPU_triangle_setup(dm);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 3c028ff0805..8ec932f4184 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -868,14 +868,12 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
/* Generate varying assignments. */
- /* TODO(sergey): Disabled for now, needs revisit. */
-#if 0
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_MTFACE) {
BLI_dynstr_appendf(ds,
- "\tINTERP_FACE_VARYING_2(var%d, "
+ "\t// INTERP_FACE_VARYING_2(var%d, "
"fvar%d_offset, st);\n",
input->attribid,
input->attribid);
@@ -883,7 +881,6 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
}
}
}
-#endif
BLI_dynstr_append(ds, "}\n");
code = BLI_dynstr_get_cstring(ds);