[Bf-blender-cvs] [1d09197] opensubdiv-modifier: Implement smooth shading for OpenSubdiv

Sergey Sharybin noreply at git.blender.org
Thu Jul 3 12:38:35 CEST 2014


Commit: 1d09197f52f3a8adc7d213a7c66aa45de1b9db29
Author: Sergey Sharybin
Date:   Thu Jul 3 16:30:11 2014 +0600
https://developer.blender.org/rB1d09197f52f3a8adc7d213a7c66aa45de1b9db29

Implement smooth shading for OpenSubdiv

This is rather an experiment commit which places all
the needed bits for the smooth shading in viewport.

Approach is similar to the simpleCpu example application,
which computes lo-res normal on CPU and passes them
to OpenSubdiv. Then the shader then have access to
vertex normals and passes them to the fragment shader.

At this point all the shading is smooth currently,
flat shading will be landed when all the material from
Blender are taken into account.

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

M	intern/opensubdiv/gpu_shader_opensubd_display.glsl
M	intern/opensubdiv/opensubdiv_capi.cc
M	intern/opensubdiv/opensubdiv_gpu_capi.cc
M	source/blender/blenkernel/intern/CCGSubSurf.c

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

diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index a57e2a1..b7daa45 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -25,16 +25,21 @@
 
 /* ***** Vertex shader ***** */
 
+#version 130
+
 #ifdef VERTEX_SHADER
 
-varying vec3 varying_normal;
-varying vec3 varying_position;
+in vec3 normal;
+in vec3 position;
+
+out vec3 varying_normal;
+out vec3 varying_position;
 
 void main()
 {
-	vec4 co = gl_ModelViewMatrix * gl_Vertex;
+	vec4 co = gl_ModelViewMatrix * vec4(position, 1.0);
 
-	varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+	varying_normal = normalize(gl_NormalMatrix * normal);
 	varying_position = co.xyz;
 
 	gl_Position = gl_ProjectionMatrix * co;
@@ -54,15 +59,16 @@ void main()
 
 #define NUM_SOLID_LIGHTS 3
 
-varying vec3 varying_normal;
-varying vec3 varying_position;
-varying vec4 varying_vertex_color;
+in vec3 varying_normal;
+in vec3 varying_position;
 
 void main()
 {
 	/* Compute normal. */
-	vec3 N = normalize(cross(dFdx(varying_position),
-	                         dFdy(varying_position)));
+	vec3 N = varying_normal;
+
+	if (!gl_FrontFacing)
+		N = -N;
 
 	/* Compute diffuse and specular lighting. */
 	vec3 L_diffuse = vec3(0.0);
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index c5fe795..c80df7f 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -276,7 +276,7 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromEvaluator(
 	bits.set(OpenSubdiv::MeshAdaptive, 0);
 	bits.set(OpenSubdiv::MeshFVarData, 1);
 
-	int num_vertex_elements = 3;
+	int num_vertex_elements = 6;
 	int num_varying_elements = 0;
 
 	OsdGLMeshInterface *mesh = NULL;
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 3a409c0..f83ab42 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -125,6 +125,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh)
 
 	const OsdDrawContext::PatchArrayVector &patches = mesh->GetDrawContext()->patchArrays;
 
+	glShadeModel(GL_FLAT);
 	for (int i = 0; i < (int)patches.size(); ++i) {
 		OpenSubdiv::OsdDrawContext::PatchArray const &patch = patches[i];
 		OpenSubdiv::OsdDrawContext::PatchDescriptor desc = patch.GetDescriptor();
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 3f23fff..4f5df8b 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -2285,18 +2285,22 @@ static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss)
 	 */
 	float (*positions)[3];
 	int vertDataSize = ss->meshIFC.vertDataSize;
+	int normalDataOffset = ss->normalDataOffset;
 	int num_basis_verts = ss->vMap->numEntries;
 	int i;
 
 	BLI_assert(ss->meshIFC.numLayers == 3);
 
-	positions = MEM_mallocN(3 * sizeof(float) * num_basis_verts, "OpenSubdiv coarse points");
+	positions = MEM_callocN(2 * sizeof(*positions) * num_basis_verts,
+	                        "OpenSubdiv coarse points");
 	for (i = 0; i < ss->vMap->curSize; i++) {
 		CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
 		for (; v; v = v->next) {
 			float *co = VERT_getCo(v, 0);
+			float *no = VERT_getNo(v, 0);
 			BLI_assert(v->osd_index < ss->vMap->numEntries);
-			VertDataCopy(positions[v->osd_index], co, ss);
+			VertDataCopy(positions[v->osd_index * 2], co, ss);
+			VertDataCopy(positions[v->osd_index * 2 + 1], no, ss);
 		}
 	}
 
@@ -2353,18 +2357,17 @@ void ccgSubSurf_prepareGLMesh(CCGSubSurf *ss)
 		openSubdiv_osdGLMeshSynchronize(ss->osd_mesh);
 
 		glBindVertexArray(ss->osd_vao);
-
-		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
-		             openSubdiv_getOsdGLMeshPatchIndexBuffer(ss->osd_mesh));
 		glBindBuffer(GL_ARRAY_BUFFER,
 		             openSubdiv_bindOsdGLMeshVertexBuffer(ss->osd_mesh));
-
 		glEnableVertexAttribArray(0);
-		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 3, 0);
-
-		glDisableVertexAttribArray(1);
+		glEnableVertexAttribArray(1);
+		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+		                      sizeof (GLfloat) * 6, 0);
+		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+		                      sizeof (GLfloat) * 6, (float*)12);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
+		             openSubdiv_getOsdGLMeshPatchIndexBuffer(ss->osd_mesh));
 		glBindBuffer(GL_ARRAY_BUFFER, 0);
-		glBindVertexArray(0);
 
 		ss->osd_compute = U.opensubdiv_compute_type;
 	}
@@ -2636,6 +2639,57 @@ static void opensubdiv_updateCoarsePositions(CCGSubSurf *ss)
 	MEM_freeN(positions);
 }
 
+static void opensubdiv_updateCoarseNormals(CCGSubSurf *ss)
+{
+	int i;
+	int normalDataOffset = ss->normalDataOffset;
+	int vertDataSize = ss->meshIFC.vertDataSize;
+
+	if (ss->meshIFC.numLayers != 3) {
+		return;
+	}
+
+	for (i = 0; i < ss->vMap->curSize; ++i) {
+		CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
+		for (; v; v = v->next) {
+			float *no = VERT_getNo(v, 0);
+			zero_v3(no);
+		}
+	}
+
+	for (i = 0; i < ss->fMap->curSize; ++i) {
+		CCGFace *f = (CCGFace *) ss->fMap->buckets[i];
+		for (; f; f = f->next) {
+			int S;
+			float face_no[3] = {0.0f, 0.0f, 0.0f};
+			CCGVert *v_prev = FACE_getVerts(f)[f->numVerts - 1];
+			float *co_prev = VERT_getCo(v_prev, 0);
+			for (S = 0; S < f->numVerts; S++) {
+				CCGVert *v_curr = FACE_getVerts(f)[S];
+				float *co_curr = VERT_getCo(v_curr, 0);
+				add_newell_cross_v3_v3v3(face_no, co_prev, co_curr);
+				co_prev = co_curr;
+			}
+			if (UNLIKELY(normalize_v3(face_no) == 0.0f)) {
+				face_no[2] = 1.0f; /* other axis set to 0.0 */
+			}
+			for (S = 0; S < f->numVerts; S++) {
+				CCGVert *v = FACE_getVerts(f)[S];
+				float *no = VERT_getNo(v, 0);
+				add_v3_v3(no, face_no);
+			}
+		}
+	}
+
+	for (i = 0; i < ss->vMap->curSize; ++i) {
+		CCGVert *v = (CCGVert *) ss->vMap->buckets[i];
+		for (; v; v = v->next) {
+			float *no = VERT_getNo(v, 0);
+			normalize_v3(no);
+		}
+	}
+}
+
 static void opensubdiv_evaluateQuadFaceGrids(CCGSubSurf *ss,
                                              CCGFace *face,
                                              const int osd_face_index)
@@ -2916,6 +2970,9 @@ static void ccgSubSurf__syncOpenSubdiv(CCGSubSurf *ss)
 			/* Evaluate opensubdiv mesh into the CCG grids. */
 			opensubdiv_evaluateGrids(ss);
 		}
+		else {
+			opensubdiv_updateCoarseNormals(ss);
+		}
 	}
 	else {
 		BLI_assert(!"OpenSubdiv initializetion failed, should not happen.");




More information about the Bf-blender-cvs mailing list