[Bf-blender-cvs] [6cc71ba] opensubdiv-modifier: OpenSubdiv: Support of multiple UVs for GLSL shading

Sergey Sharybin noreply at git.blender.org
Wed Jul 30 13:49:25 CEST 2014


Commit: 6cc71ba4d27db7e1491151eb6434942a6883b892
Author: Sergey Sharybin
Date:   Wed Jul 30 13:46:28 2014 +0600
Branches: opensubdiv-modifier
https://developer.blender.org/rB6cc71ba4d27db7e1491151eb6434942a6883b892

OpenSubdiv: Support of multiple UVs for GLSL shading

Now OSD mesh is being constructed with all the UV maps
passed as fave-varying variables making it possible:

- Switch active UV layers without re-building OSD GL mesh
- Access any of the UV maps from the shader

This is quite straightforward change apart from one
aspect, which is updating offset of UV map in the face
varying variables buffer.

The thing here is that the same material can be used
by several meshes which could have different order of
UV maps (hence different offsets). Another issue here
is that binding uniforms knows nothing about mesh itself
so it can't get needed layer indices that easy.

because of this reasons there's now some utility functions
which are used by OSD mesh display.

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

M	intern/opensubdiv/gpu_shader_opensubd_display.glsl
M	intern/opensubdiv/opensubdiv_capi.h
M	intern/opensubdiv/opensubdiv_gpu_capi.cc
M	intern/opensubdiv/opensubdiv_partitioned.h
M	source/blender/blenkernel/intern/CCGSubSurf.c
M	source/blender/blenkernel/intern/subsurf_ccg.c
M	source/blender/gpu/GPU_draw.h
M	source/blender/gpu/GPU_material.h
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_draw.c
M	source/blender/gpu/intern/gpu_material.c
M	source/blender/gpu/shaders/gpu_shader_geometry.glsl

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

diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index d407c88..0481265 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -71,6 +71,8 @@ layout(line_strip, max_vertices = 8) out;
 uniform mat4 modelViewMatrix;
 uniform mat4 projectionMatrix;
 uniform int PrimitiveIdBase;
+uniform int osd_fvar_count;
+uniform int osd_active_uv_offset;
 
 in block {
 	VertexData v;
@@ -81,7 +83,7 @@ in block {
 		vec2 v[4]; \
 		int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
 		for (int i = 0; i < 4; ++i) { \
-			int index = (primOffset + i) * 2 + fvarOffset; \
+			int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
 			v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
 			            texelFetch(FVarDataBuffer, index + 1).s); \
 		} \
@@ -106,7 +108,7 @@ void emit(int index, vec3 normal)
 	vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
 	vec2 st = quadst[index];
 
-	INTERP_FACE_VARYING_2(outpt.v.uv, 0, st);
+	INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
 
 	gl_Position = projectionMatrix * inpt[index].v.position;
 	EmitVertex();
@@ -130,7 +132,7 @@ void emit(int index)
 	vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
 	vec2 st = quadst[index];
 
-	INTERP_FACE_VARYING_2(outpt.v.uv, 0, st);
+	INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
 
 	gl_Position = projectionMatrix * inpt[index].v.position;
 	EmitVertex();
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index b20e95a..4727cfd 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -93,7 +93,8 @@ void openSubdiv_osdGLDisplayDeinit(void);
  *
  * TODO(sergey): Some of the stuff could be initialized once for all meshes.
  */
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl);
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
+                                        int active_uv_index);
 
 /* Draw patches which corresponds to a given partition. */
 void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 4b4b681..a3e98fd 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -84,6 +84,7 @@ typedef struct Transform {
 } Transform;
 
 static bool g_use_osd_glsl = false;
+static bool g_active_uv_index = -1;
 
 static GLuint g_flat_fill_program = 0;
 static GLuint g_smooth_fill_program = 0;
@@ -357,6 +358,12 @@ void bindProgram(PartitionedGLMeshInterface *mesh,
 		              mesh->GetDrawContext()->GetFvarDataTextureBuffer());
 		glActiveTexture(GL_TEXTURE0);
 	}
+
+	glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+	            mesh->GetFVarCount());
+
+	glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+	            g_active_uv_index * 2);
 }
 
 }  /* namespace */
@@ -397,9 +404,11 @@ void openSubdiv_osdGLDisplayDeinit(void)
 	}
 }
 
-void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl)
+void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
+                                        int active_uv_index)
 {
 	g_use_osd_glsl = use_osd_glsl != 0;
+	g_active_uv_index = active_uv_index;
 
 	/* Update transformation matricies. */
 	glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@@ -475,6 +484,11 @@ static GLuint preapre_patchDraw(PartitionedGLMeshInterface *mesh,
 				glBindTexture(GL_TEXTURE_BUFFER,
 				              mesh->GetDrawContext()->GetFvarDataTextureBuffer());
 				glActiveTexture(GL_TEXTURE0);
+
+				GLint location = glGetUniformLocation(program, "osd_fvar_count");
+				if (location != -1) {
+					glUniform1i(location, mesh->GetFVarCount());
+				}
 			}
 
 		}
diff --git a/intern/opensubdiv/opensubdiv_partitioned.h b/intern/opensubdiv/opensubdiv_partitioned.h
index 612dfd9..2378d18 100644
--- a/intern/opensubdiv/opensubdiv_partitioned.h
+++ b/intern/opensubdiv/opensubdiv_partitioned.h
@@ -40,6 +40,7 @@ class PartitionedMeshInterface : public OsdMeshInterface<DRAW_CONTEXT> {
 	typedef typename DrawContext::PatchArrayVector PatchArrayVector;
 
 public:
+	virtual int GetFVarCount() const = 0;
 	virtual int GetNumPartitions() const = 0;
 	virtual PatchArrayVector const &GetPatchArrays(int partition) const = 0;
 };
@@ -57,7 +58,7 @@ public:
 	typedef typename Inherited::ComputeController ComputeController;
 	typedef typename Inherited::ComputeContext ComputeContext;
 	typedef typename Inherited::DrawContext DrawContext;
-    typedef typename Inherited::VertexBufferBinding VertexBufferBinding;
+	typedef typename Inherited::VertexBufferBinding VertexBufferBinding;
 	typedef typename DrawContext::PatchArrayVector PatchArrayVector;
 
 	PartitionedMesh(ComputeController *computeController,
@@ -148,6 +149,16 @@ public:
 		return _partitionedOsdPatchArrays[partition];
 	}
 
+	virtual int GetFVarCount() const {
+		const FarMesh<OsdVertex> *farMesh = this->GetFarMesh();
+		/* TODO(sergey): We assume all the patches have the same
+		 * number of face-varying variables.
+		 *
+		 * TODO(sergey): Check for empty patch tables here.
+		 */
+		return farMesh->GetPatchTables()[0].GetFVarData().GetFVarWidth();
+	}
+
 private:
 	Inherited inherited_impl_;
 	std::vector<PatchArrayVector> _partitionedOsdPatchArrays;
@@ -169,7 +180,7 @@ public:
 	typedef typename Inherited::ComputeController ComputeController;
 	typedef typename Inherited::ComputeContext ComputeContext;
 	typedef typename Inherited::DrawContext DrawContext;
-    typedef typename Inherited::VertexBufferBinding VertexBufferBinding;
+	typedef typename Inherited::VertexBufferBinding VertexBufferBinding;
 	typedef typename DrawContext::PatchArrayVector PatchArrayVector;
 
 	PartitionedMesh(OsdCLComputeController *computeController,
@@ -264,6 +275,16 @@ public:
 		return _partitionedOsdPatchArrays[partition];
 	}
 
+	virtual int GetFVarCount() const {
+		const FarMesh<OsdVertex> *farMesh = this->GetFarMesh();
+		/* TODO(sergey): We assume all the patches have the same
+		 * number of face-varying variables.
+		 *
+		 * TODO(sergey): Check for empty patch tables here.
+		 */
+		return farMesh->GetPatchTables()[0].GetFVarData().GetFVarWidth();
+	}
+
 private:
 	Inherited inherited_impl_;
 	std::vector<PatchArrayVector> _partitionedOsdPatchArrays;
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index a8858cf..633b420 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -472,8 +472,8 @@ struct CCGSubSurf {
 	short osd_compute;
 
 	bool osd_uvs_invalid;
-	int osd_uv_index;
 	bool osd_subsurf_uv;
+	int osd_uv_index;
 #endif
 };
 
@@ -938,9 +938,9 @@ 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 = false;
-		ss->osd_uv_index = -1;
+		ss->osd_uvs_invalid = true;
 		ss->osd_subsurf_uv = 0;
+		ss->osd_uv_index = -1;
 #endif
 
 		return ss;
@@ -2402,7 +2402,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl)
 		ss->osd_coords_invalid = false;
 	}
 
-	openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl);
+	openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index);
 
 	return true;
 }
@@ -2550,56 +2550,62 @@ void ccgSubSurf_setUVCoordsFromDM(CCGSubSurf *ss,
                                   DerivedMesh *dm,
                                   bool subdivide_uvs)
 {
-	/* TODO(sergey): Do we have shorter way to do this? */
-	int active = CustomData_get_active_layer(&dm->loopData,
-	                                         CD_MLOOPUV);
-	MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData,
-	                                          CD_MLOOPUV,
-	                                          active);
+	CustomData *loop_data = &dm->loopData;
+	int layer, num_layer = CustomData_number_of_layers(loop_data, CD_MLOOPUV);
 	bool mpoly_allocated;
-	MPoly *mpoly = DM_get_poly_array(dm, &mpoly_allocated);
-	int i;
+	MPoly *mpoly;
 
-	if (active != ss->osd_uv_index) {
-		ss->osd_uvs_invalid = true;
-	}
+	ss->osd_uv_index = CustomData_get_active_layer(&dm->loopData,
+	                                               CD_MLOOPUV);
 
 	if (subdivide_uvs != ss->osd_subsurf_uv) {
 		ss->osd_uvs_invalid = true;
 	}
 
-	if (mloopuv == NULL || !ss->osd_uvs_invalid) {
+	if (num_layer == 0 || !ss->osd_uvs_invalid) {
 		return;
 	}
 
 	ss->osd_uvs_invalid = false;
-	ss->osd_uv_index = active;
 	ss->osd_subsurf_uv = subdivide_uvs;
 	if (ss->osd_mesh) {
 		ss->osd_mesh_invalid = true;
 	}
 
+	mpoly = DM_get_poly_array(dm, &mpoly_allocated);
+
 	openSubdiv_evaluatorFVDataClear(ss->osd_evaluator);
-	for (i = 0; i < ss->fMap->curSize; i++) {
-		CCGFace *face = (CCGFace *) ss->fMap->buckets[i];
-		for (; face; face = face->next) {
-			int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(face));
-			MPoly *mp = &mpoly[index];
-			int S;
-			BLI_assert(face->numVerts == mp->totloop);
-			for (S = 0; S < face->numVerts; ++S) {
-				MLoopUV *loopuv = &mloopuv[mp->loopstart + S];
-				openSubdiv_evaluatorFVDataPush(ss->osd_evaluator,
-				                               loopuv->uv[0]);
-				openSubdiv_evaluatorFVDataPush(ss->osd_evaluator,
-				                               loopuv->uv[1]);
+
+	for (layer = 0; layer < num_layer; ++layer) {
+		openSubdiv_evaluatorFVNamePush(ss->osd_evaluator, "u");
+		openSubdiv_evaluatorFVNamePush(ss->osd_evaluator, "v");
+	}
+
+	{
+		int i;
+		for (i = 0; i < ss->fMap->curSize; ++i) {
+			CCGFace *face = (CCGFace *) ss->fMap->buckets[i];
+			for (; face; face = face->next) {
+				int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(face));
+				MPoly *mp = &mpoly[index];
+				int S;
+				for (S = 0; S < face->numVerts; ++S) {
+					for (layer = 0; layer < num_layer; ++layer) {
+						MLoopUV *mloopuv = CustomData_get_layer_n(loop_data,
+						                                          CD_MLOOPUV,
+						                                          layer);
+
+						MLoopU

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list