[Bf-blender-cvs] [f81d237] opensubdiv-modifier: OpenSubdiv: Support multi-textured faces in a solid view

Sergey Sharybin noreply at git.blender.org
Tue Jul 8 12:13:11 CEST 2014


Commit: f81d237102dc9de59b6659d64e5ab59f8681f9e3
Author: Sergey Sharybin
Date:   Tue Jul 8 12:53:06 2014 +0600
https://developer.blender.org/rBf81d237102dc9de59b6659d64e5ab59f8681f9e3

OpenSubdiv: Support multi-textured faces in a solid view

This means that if faces have different materials assigned to them
they'll be textured accordingly to a diffuse settings when viewing
them in solid shading mode.

It uses approach based on the pertitioned mesh from OpenSubdiv and
currently it creates partition for every single coarse face. This
might backfire in performance for a bit because it increases number
of glDrawElements() calls. But likely partitioning will stay like
this (to avoid re-partitioning when changing material settings)
and we'll just do some conjunction of partitions when actually
drawing faces into the viewport.

Currently it's like 20% speed loss, don't get too much disappointed
on this, it's to be addressed. Just a bit later. For now 1st prio is
to have all the shading/texturing bits in place.

===================================================================

M	intern/opensubdiv/opensubdiv_capi.cc
M	intern/opensubdiv/opensubdiv_capi.h
M	intern/opensubdiv/opensubdiv_gpu_capi.cc
A	intern/opensubdiv/opensubdiv_partitioned.h
M	source/blender/blenkernel/intern/CCGSubSurf.c
M	source/blender/blenkernel/intern/CCGSubSurf.h
M	source/blender/blenkernel/intern/subsurf_ccg.c

===================================================================

diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 17ec173..86c0bad 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -73,6 +73,10 @@
 #  include <opensubdiv/osd/glVertexBuffer.h>
 #endif
 
+#include <opensubdiv/osdutil/patchPartitioner.h>
+
+#include "opensubdiv_partitioned.h"
+
 #include "MEM_guardedalloc.h"
 
 // **************** Types declaration ****************
@@ -93,6 +97,7 @@ using OpenSubdiv::OsdUtilSubdivTopology;
 using OpenSubdiv::OsdVertex;
 
 typedef OpenSubdiv::HbrMesh<OsdVertex> OsdHbrMesh;
+typedef OpenSubdiv::HbrFace<OpenSubdiv::OsdVertex> OsdHbrFace;
 
 #if defined(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK) || \
     defined(OPENSUBDIV_HAS_GLSL_COMPUTE)
@@ -100,29 +105,30 @@ using OpenSubdiv::OsdGLVertexBuffer;
 #endif
 
 using OpenSubdiv::OsdGLDrawContext;
+using OpenSubdiv::PartitionedMesh;
 
 // CPU backend
 using OpenSubdiv::OsdCpuGLVertexBuffer;
 using OpenSubdiv::OsdCpuComputeController;
 static OpenSubdiv_ComputeController *g_cpuComputeController = NULL;
-typedef OsdMesh<OsdCpuGLVertexBuffer,
-                OsdCpuComputeController,
-                OsdGLDrawContext> OsdCpuMesh;
+typedef PartitionedMesh<OsdCpuGLVertexBuffer,
+                        OsdCpuComputeController,
+                        OsdGLDrawContext> OsdCpuMesh;
 
 #ifdef OPENSUBDIV_HAS_OPENMP
 using OpenSubdiv::OsdOmpComputeController;
 static OpenSubdiv_ComputeController *g_ompComputeController = NULL;
-typedef OsdMesh<OsdCpuGLVertexBuffer,
-                OsdOmpComputeController,
-                OsdGLDrawContext> OsdOmpMesh;
+typedef PartitionedMesh<OsdCpuGLVertexBuffer,
+                        OsdOmpComputeController,
+                        OsdGLDrawContext> OsdOmpMesh;
 #endif
 
 #ifdef OPENSUBDIV_HAS_OPENCL
 using OpenSubdiv::OsdCLGLVertexBuffer;
 using OpenSubdiv::OsdCLComputeController;
-typedef OsdMesh<OsdCLGLVertexBuffer,
-                OsdCLComputeController,
-                OsdGLDrawContext> OsdCLMesh;
+typedef PartitionedMesh<OsdCLGLVertexBuffer,
+                        OsdCLComputeController,
+                        OsdGLDrawContext> OsdCLMesh;
 static OpenSubdiv_ComputeController *g_clComputeController = NULL;
 static cl_context g_clContext;
 static cl_command_queue g_clQueue;
@@ -131,26 +137,26 @@ static cl_command_queue g_clQueue;
 #ifdef OPENSUBDIV_HAS_CUDA
 using OpenSubdiv::OsdCudaComputeController;
 using OpenSubdiv::OsdCudaGLVertexBuffer;
-typedef OsdMesh<OsdCudaGLVertexBuffer,
-                OsdCudaComputeController,
-                OsdGLDrawContext> OsdCudaMesh;
+typedef PartitionedMesh<OsdCudaGLVertexBuffer,
+                        OsdCudaComputeController,
+                        OsdGLDrawContext> OsdCudaMesh;
 static OpenSubdiv_ComputeController *g_cudaComputeController = NULL;
 static bool g_cudaInitialized = false;
 #endif
 
 #ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
 using OpenSubdiv::OsdGLSLTransformFeedbackComputeController;
-typedef OsdMesh<OsdGLVertexBuffer,
-                OsdGLSLTransformFeedbackComputeController,
-                OsdGLDrawContext> OsdGLSLTransformFeedbackMesh;
+typedef PartitionedMesh<OsdGLVertexBuffer,
+                        OsdGLSLTransformFeedbackComputeController,
+                        OsdGLDrawContext> OsdGLSLTransformFeedbackMesh;
 static OpenSubdiv_ComputeController *g_glslTransformFeedbackComputeController = NULL;
 #endif
 
 #ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
 using OpenSubdiv::OsdGLSLComputeController;
-typedef OsdMesh<OsdGLVertexBuffer,
-                OsdGLSLComputeController,
-                OsdGLDrawContext> OsdGLSLComputeMesh;
+typedef PartitionedMesh<OsdGLVertexBuffer,
+                        OsdGLSLComputeController,
+                        OsdGLDrawContext> OsdGLSLComputeMesh;
 static OpenSubdiv_ComputeController *g_glslOComputeComputeController = NULL;
 #endif
 
@@ -260,6 +266,54 @@ static OpenSubdiv::OsdUtilMesh<OsdVertex>::Scheme get_osd_scheme(int scheme)
 	}
 }
 
+/* TODO(sergey): Currently we use single coarse face per partition,
+ * which allows to have per-face material assignment but which also
+ * increases number of glDrawElements() calls.
+ *
+ * Ideally here we need to partition like this, but do some conjunction
+ * at draw time, so adjacent faces with the same material are displayed
+ * in a single chunk.
+ */
+static void get_partition_per_face(OsdHbrMesh &hmesh,
+                                   std::vector<int> *idsOnPtexFaces)
+{
+	int numFaces = hmesh.GetNumCoarseFaces();
+
+	// First, assign partition ID to each coarse face.
+	std::vector<int> idsOnCoarseFaces;
+	for (int i = 0; i < numFaces; ++i) {
+		int partitionID = i;
+		idsOnCoarseFaces.push_back(partitionID);
+	}
+
+	// Create ptex index to coarse face index mapping.
+	OsdHbrFace *lastFace = hmesh.GetFace(numFaces - 1);
+	int numPtexFaces = lastFace->GetPtexIndex();
+	numPtexFaces += (hmesh.GetSubdivision()->FaceIsExtraordinary(&hmesh,
+	                                                             lastFace) ?
+	                 lastFace->GetNumVertices() : 1);
+
+	// TODO(sergey): Duplicated logic to simpleHbr.
+	std::vector<int> ptexIndexToFaceMapping(numPtexFaces);
+	int ptexIndex = 0;
+	for (int i = 0; i < numFaces; ++i) {
+		OsdHbrFace *f = hmesh.GetFace(i);
+		ptexIndexToFaceMapping[ptexIndex++] = i;
+		int numVerts = f->GetNumVertices();
+		if (numVerts != 4 ) {
+			for (int j = 0; j < numVerts-1; ++j) {
+				ptexIndexToFaceMapping[ptexIndex++] = i;
+			}
+		}
+	}
+	assert((int)ptexIndexToFaceMapping.size() == numPtexFaces);
+
+	// Convert ID array from coarse face index space to ptex index space.
+	for (int i = 0; i < numPtexFaces; ++i) {
+		idsOnPtexFaces->push_back(idsOnCoarseFaces[ptexIndexToFaceMapping[i]]);
+	}
+}
+
 struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
     OpenSubdiv_EvaluatorDescr *evaluator_descr,
     int controller_type,
@@ -286,6 +340,9 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
 
 	OsdHbrMesh *hmesh = util_mesh.GetHbrMesh();
 
+	std::vector<int> idsOnPtexFaces;
+	get_partition_per_face(*hmesh, &idsOnPtexFaces);
+
 	OsdMeshBitset bits;
 	/* TODO(sergey): Adaptive subdivisions are not currently
 	 * possible because of the lack of tessellation shader.
@@ -308,7 +365,8 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
 					num_vertex_elements, \
 					num_varying_elements, \
 					level, \
-					bits); \
+					bits, \
+					idsOnPtexFaces); \
 			break;
 		CHECK_CONTROLLER_TYPE(CPU, OsdCpuMesh, OsdCpuComputeController)
 
@@ -327,7 +385,8 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
 					level,
 					bits,
 					g_clContext,
-					g_clQueue);
+					g_clQueue,
+					idsOnPtexFaces);
 			break;
 #endif
 
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index 4c48dda..2050de4 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -36,6 +36,9 @@ extern "C" {
 struct OpenSubdiv_EvaluatorDescr;
 struct OpenSubdiv_GLMesh;
 
+typedef struct OpenSubdiv_EvaluatorDescr OpenSubdiv_EvaluatorDescr;
+typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
+
 #ifdef __cplusplus
 struct OpenSubdiv_GLMeshDescr;
 typedef struct OpenSubdiv_GLMesh {
@@ -62,23 +65,26 @@ enum {
 	OPENSUBDIV_SCHEME_LOOP,
 };
 
-struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
-    struct OpenSubdiv_EvaluatorDescr *evaluator_descr,
+OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
+    OpenSubdiv_EvaluatorDescr *evaluator_descr,
     int controller_type,
     int level,
     int scheme);
 
-void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh);
-unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(struct OpenSubdiv_GLMesh *gl_mesh);
-unsigned int openSubdiv_getOsdGLMeshVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshUpdateVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh,
+void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
+unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
+        OpenSubdiv_GLMesh *gl_mesh);
+unsigned int openSubdiv_getOsdGLMeshVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshUpdateVertexBuffer(OpenSubdiv_GLMesh *gl_mesh,
                                             const float *vertex_data,
                                             int start_vertex,
                                             int num_verts);
-void openSubdiv_osdGLMeshRefine(struct OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshSynchronize(struct OpenSubdiv_GLMesh *gl_mesh);
-void openSubdiv_osdGLMeshDisplay(struct OpenSubdiv_GLMesh *gl_mesh, int fill_quads);
-void openSubdiv_osdGLMeshBindVertexBuffer(struct OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshRefine(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshSynchronize(OpenSubdiv_GLMesh *gl_mesh);
+void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
+                                 int fill_quads,
+                                 int material);
+void openSubdiv_osdGLMeshBindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh);
 
 int openSubdiv_getAvailableControllers(void);
 
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index ec8a2b5..ce2c932 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -43,6 +43,12 @@
 #  include <opensubdiv/osd/cudaGLVertexBuffer.h>
 #endif
 
+#include <opensubdiv/osd/cpuGLVertexBuffer.h>
+#include <opensubdiv/osd/cpuComputeContext.h>
+#include <opensubdiv/osd/cpuComputeController.h>
+
+#include "opensubdiv_partitioned.h"
+
 using OpenSubdiv::OsdGLMeshInterface;
 
 extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
@@ -115,14 +121,15 @@ static GLuint linkProgram(const char *define)
 }
 #endif
 
-void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh, int fill_quads)
+void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
+                                 int fill_quads,
+                                 int material)
 {
 #ifndef OPENSUBDIV_LEGACY_DRAW
 	static GLuint flat_fill_program;
 	static GLuint smooth_fill_program;
 	static GL

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list