[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [51119] trunk/blender/source/blender/gpu/ intern/gpu_buffers.c: Improve flat-shaded VBO drawing for sculpt meshes

Nicholas Bishop nicholasbishop at gmail.com
Sat Oct 6 18:52:52 CEST 2012


Revision: 51119
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=51119
Author:   nicholasbishop
Date:     2012-10-06 16:52:52 +0000 (Sat, 06 Oct 2012)
Log Message:
-----------
Improve flat-shaded VBO drawing for sculpt meshes

Separate vertex copies are now made for flat-shading, such that the
normal is correctly flat-shaded. The element index buffer is not
created in this case.

Modified Paths:
--------------
    trunk/blender/source/blender/gpu/intern/gpu_buffers.c

Modified: trunk/blender/source/blender/gpu/intern/gpu_buffers.c
===================================================================
--- trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2012-10-06 16:42:11 UTC (rev 51118)
+++ trunk/blender/source/blender/gpu/intern/gpu_buffers.c	2012-10-06 16:52:52 UTC (rev 51119)
@@ -1397,31 +1397,91 @@
                              int *vert_indices, int totvert, const float *vmask)
 {
 	VertexBufferFormat *vert_data;
-	int i;
+	int i, j, k;
 
 	buffers->vmask = vmask;
 
 	if (buffers->vert_buf) {
+		int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
+
 		/* Build VBO */
 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
 		glBufferDataARB(GL_ARRAY_BUFFER_ARB,
-		                sizeof(VertexBufferFormat) * totvert,
-		                NULL, GL_STATIC_DRAW_ARB);
+						sizeof(VertexBufferFormat) * totelem,
+						NULL, GL_STATIC_DRAW_ARB);
+
 		vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
 
 		if (vert_data) {
-			for (i = 0; i < totvert; ++i) {
-				MVert *v = mvert + vert_indices[i];
-				VertexBufferFormat *out = vert_data + i;
+			/* Vertex data is shared if smooth-shaded, but seperate
+			   copies are made for flat shading because normals
+			   shouldn't be shared. */
+			if (buffers->smooth) {
+				for (i = 0; i < totvert; ++i) {
+					MVert *v = mvert + vert_indices[i];
+					VertexBufferFormat *out = vert_data + i;
 
-				copy_v3_v3(out->co, v->co);
-				memcpy(out->no, v->no, sizeof(short) * 3);
-				if (vmask) {
-					gpu_color_from_mask_copy(vmask[vert_indices[i]],
-					                         out->color);
+					copy_v3_v3(out->co, v->co);
+					memcpy(out->no, v->no, sizeof(short) * 3);
+					if (vmask) {
+						gpu_color_from_mask_copy(vmask[vert_indices[i]],
+												 out->color);
+					}
 				}
 			}
+			else {
+				for (i = 0; i < buffers->totface; ++i) {
+					const MFace *f = &buffers->mface[buffers->face_indices[i]];
+					const unsigned int *fv = &f->v1;
+					const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}};
+					float fno[3];
+					short no[3];
 
+					float fmask;
+
+					/* Face normal and mask */
+					if (f->v4) {
+						normal_quad_v3(fno,
+									   mvert[fv[0]].co,
+									   mvert[fv[1]].co,
+									   mvert[fv[2]].co,
+									   mvert[fv[3]].co);
+						if (vmask) {
+							fmask = (vmask[fv[0]] +
+									 vmask[fv[1]] +
+									 vmask[fv[2]] +
+									 vmask[fv[3]]) * 0.25;
+						}
+					}
+					else {
+						normal_tri_v3(fno,
+									  mvert[fv[0]].co,
+									  mvert[fv[1]].co,
+									  mvert[fv[2]].co);
+						if (vmask) {
+							fmask = (vmask[fv[0]] +
+									 vmask[fv[1]] +
+									 vmask[fv[2]]) / 3.0f;
+						}
+					}
+					normal_float_to_short_v3(no, fno);
+
+					for (j = 0; j < (f->v4 ? 2 : 1); j++) {
+						for (k = 0; k < 3; k++) {
+							const MVert *v = &mvert[fv[vi[j][k]]];
+							VertexBufferFormat *out = vert_data;
+
+							copy_v3_v3(out->co, v->co);
+							memcpy(out->no, no, sizeof(short) * 3);
+							if (vmask)
+								gpu_color_from_mask_copy(fmask, out->color);
+
+							vert_data++;
+						}
+					}
+				}
+			}
+
 			glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
 		}
 		else {
@@ -1454,8 +1514,11 @@
 		if (!paint_is_face_hidden(f, mvert))
 			tottri += f->v4 ? 2 : 1;
 	}
-	
-	if (gpu_vbo_enabled())
+
+	/* An element index buffer is used for smooth shading, but flat
+	   shading requires separate vertex normals so an index buffer is
+	   can't be used there. */
+	if (gpu_vbo_enabled() && buffers->smooth)
 		glGenBuffersARB(1, &buffers->index_buf);
 
 	if (buffers->index_buf) {
@@ -1499,7 +1562,7 @@
 		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 	}
 
-	if (buffers->index_buf)
+	if (buffers->index_buf || !buffers->smooth)
 		glGenBuffersARB(1, &buffers->vert_buf);
 
 	buffers->tot_tri = tottri;
@@ -1979,7 +2042,6 @@
 void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
 {
 	const int has_mask = (buffers->vmask || buffers->gridkey.has_mask);
-	int smooth = 0;
 
 	if (buffers->totface) {
 		const MFace *f = &buffers->mface[buffers->face_indices[0]];
@@ -1992,9 +2054,9 @@
 			return;
 	}
 
-	glShadeModel(buffers->smooth ? GL_SMOOTH : GL_FLAT);
+	glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT);
 
-	if (buffers->vert_buf && buffers->index_buf) {
+	if (buffers->vert_buf) {
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glEnableClientState(GL_NORMAL_ARRAY);
 		if (has_mask) {
@@ -2006,8 +2068,10 @@
 		}
 
 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
-		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
 
+		if (buffers->index_buf)
+			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+
 		if (buffers->tot_quad) {
 			char *offset = 0;
 			int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
@@ -2027,6 +2091,8 @@
 			}
 		}
 		else {
+			int totelem = buffers->tot_tri * 3;
+
 			glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
 			                (void *)offsetof(VertexBufferFormat, co));
 			glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
@@ -2036,11 +2102,15 @@
 				               (void *)offsetof(VertexBufferFormat, color));
 			}
 
-			glDrawElements(GL_TRIANGLES, buffers->tot_tri * 3, buffers->index_type, 0);
+			if (buffers->index_buf)
+				glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0);
+			else
+				glDrawArrays(GL_TRIANGLES, 0, totelem);
 		}
 
 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
-		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+		if (buffers->index_buf)
+			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 
 		glDisableClientState(GL_VERTEX_ARRAY);
 		glDisableClientState(GL_NORMAL_ARRAY);




More information about the Bf-blender-cvs mailing list