[Bf-blender-cvs] [f07ca03] gooseberry: Initial VBO code for GPU subsurf.

Antony Riakiotakis noreply at git.blender.org
Mon Feb 9 14:36:09 CET 2015


Commit: f07ca0318502e07c8f38096de23377c9b2d47770
Author: Antony Riakiotakis
Date:   Mon Dec 15 19:54:50 2014 +0100
Branches: gooseberry
https://developer.blender.org/rBf07ca0318502e07c8f38096de23377c9b2d47770

Initial VBO code for GPU subsurf.

This commit adds a few generalizations to the VBO
code so that modifiers can create and populate their own GPU objects.

The VBO code originally supported CDDerivedMesh only. The design moves slightly
towards the viewport refactor where the rendering system requests data from the
modifiers.

In this commit only basic support for vertices and normals is provided and
some features from blender's VBO system, suchs as mapping to original faces,
unique element indices for vertices and loose vertex/edge support are missing.
Also, the quick navigation feature of the subsurf modifier won't be supported
for now.

What we do have is full support for solid shading with multiple materials,
flat/smooth shading and a big performance boost.

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

M	release/scripts/modules/sys_info.py
M	source/blender/blenkernel/BKE_DerivedMesh.h
M	source/blender/blenkernel/intern/cdderivedmesh.c
M	source/blender/blenkernel/intern/subsurf_ccg.c
M	source/blender/gpu/GPU_buffers.h
M	source/blender/gpu/intern/gpu_buffers.c

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

diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 74a6f4c..4ffc7c2 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -167,8 +167,11 @@ def write_sysinfo(op):
         output.write("\nImplementation Dependent OpenGL Limits:\n")
         output.write(lilies)
         limit = bgl.Buffer(bgl.GL_INT, 1)
+        limit_fl = bgl.Buffer(bgl.GL_FLOAT, 2)
         bgl.glGetIntegerv(bgl.GL_MAX_TEXTURE_UNITS, limit)
         output.write("Maximum Fixed Function Texture Units:\t%d\n" % limit[0])
+        bgl.glGetFloatv(bgl.GL_MAX_TEXTURE_UNITS, limit_fl)
+        output.write("Point Sprite Size Range:\t Max: %f Min: %f\n" % (limit_fl[0], limit_fl[1]))
 
         output.write("\nGLSL:\n")
         if version[0] > '1':
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 0425164..40ed57d 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -471,6 +471,10 @@ struct DerivedMesh {
 	                           void (*setMaterial)(void *userData, int matnr, void *attribs),
 	                           bool (*setFace)(void *userData, int index), void *userData);
 
+	struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm);
+	void (*copy_gpu_data)(DerivedMesh *dm, int type, float *varray, int *index,
+	                      int *mat_orig_to_new, void *user_data);
+	
 	/** Release reference to the DerivedMesh. This function decides internally
 	 * if the DerivedMesh will be freed, or cached for later use. */
 	void (*release)(DerivedMesh *dm);
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 2554151..2a38418 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -395,7 +395,7 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
 	MEdge *medge = cddm->medge;
 	int i;
 	int prevstart = 0;
-	int prevdraw = 1;
+	bool prevdraw = true;
 	bool draw = true;
 	
 	if (cddm->pbvh && cddm->pbvh_draw &&
@@ -417,14 +417,14 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
 			draw = false;
 		}
 		if (prevdraw != draw) {
-			if (prevdraw > 0 && (i - prevstart) > 0) {
+			if (prevdraw && (i - prevstart) > 0) {
 				GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
 			}
 			prevstart = i;
 		}
 		prevdraw = draw;
 	}
-	if (prevdraw > 0 && (i - prevstart) > 0) {
+	if (prevdraw && (i - prevstart) > 0) {
 		GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2);
 	}
 	GPU_buffer_unbind();
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 9519c7b..c5a2e02 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -72,6 +72,7 @@
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_glew.h"
+#include "GPU_buffers.h"
 
 #include "CCGSubSurf.h"
 
@@ -1730,12 +1731,25 @@ static void ccgDM_drawLooseEdges(DerivedMesh *dm)
 	}
 }
 
+static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3])
+{
+	float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
+	float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
+
+	no[0] = b_dY * a_cZ - b_dZ * a_cY;
+	no[1] = b_dZ * a_cX - b_dX * a_cZ;
+	no[2] = b_dX * a_cY - b_dY * a_cX;
+	
+	normalize_v3(no);
+}
+
+
 static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 {
 	float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2];
 	float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2];
 	float no[3];
-
+	
 	no[0] = b_dY * a_cZ - b_dZ * a_cY;
 	no[1] = b_dZ * a_cX - b_dX * a_cZ;
 	no[2] = b_dX * a_cY - b_dY * a_cX;
@@ -1745,7 +1759,8 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
 }
 
 /* Only used by non-editmesh types */
-static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial)
+static void ccgDM_prepare_normal_data(DerivedMesh *dm, float *varray, int *vindex,
+                                    int *mat_orig_to_new, void *UNUSED(user_data))
 {
 	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
 	CCGSubSurf *ss = ccgdm->ss;
@@ -1754,13 +1769,277 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)
 	int gridSize = ccgSubSurf_getGridSize(ss);
 	int gridFaces = gridSize - 1;
 	DMFlagMat *faceFlags = ccgdm->faceFlags;
-	int step = (fast) ? gridSize - 1 : 1;
 	int i, totface = ccgSubSurf_getNumFaces(ss);
-	int drawcurrent = 0, matnr = -1, shademodel = -1;
+	int matnr, shademodel;
+	int start;
 
 	CCG_key_top_level(&key, ss);
 	ccgdm_pbvh_update(ccgdm);
 
+	for (i = 0; i < totface; i++) {
+		CCGFace *f = ccgdm->faceMap[i].face;
+		int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+		int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+		short (*ln)[4][3] = NULL;
+
+		if (faceFlags) {
+			shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT;
+			matnr = faceFlags[index].mat_nr;
+		}
+		else {
+			shademodel = GL_SMOOTH;
+			matnr = 0;
+		}
+
+		if (lnors) {
+			ln = lnors;
+			lnors += gridFaces * gridFaces * numVerts;
+		}
+
+		for (S = 0; S < numVerts; S++) {
+			CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+
+			if (ln) {
+				/* Can't use quad strips here... */
+				glBegin(GL_QUADS);
+				for (y = 0; y < gridFaces; y ++) {
+					for (x = 0; x < gridFaces; x ++) {
+						start = vindex[mat_orig_to_new[matnr]];
+						
+						normal_short_to_float_v3(&varray[start], ln[0][1]);
+						normal_short_to_float_v3(&varray[start + 3], ln[0][2]);
+						normal_short_to_float_v3(&varray[start + 6], ln[0][3]);
+				
+						normal_short_to_float_v3(&varray[start + 9], ln[0][3]);
+						normal_short_to_float_v3(&varray[start + 12], ln[0][1]);
+						normal_short_to_float_v3(&varray[start + 15], ln[0][0]);
+						
+						vindex[mat_orig_to_new[matnr]] += 18;
+						
+						ln ++;
+					}
+				}
+				glEnd();
+			}
+			else if (shademodel == GL_SMOOTH) {
+				for (y = 0; y < gridFaces; y ++) {
+					for (x = 0; x < gridFaces; x ++) {
+						float *a = CCG_grid_elem_no(&key, faceGridData, x, y );
+						float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y);
+						float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1);
+						float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1);
+
+						start = vindex[mat_orig_to_new[matnr]];
+						
+						copy_v3_v3(&varray[start], d);
+						copy_v3_v3(&varray[start + 3], c);
+						copy_v3_v3(&varray[start + 6], b);
+				
+						copy_v3_v3(&varray[start + 9], b);
+						copy_v3_v3(&varray[start + 12], d);
+						copy_v3_v3(&varray[start + 15], a);
+						
+						vindex[mat_orig_to_new[matnr]] += 18;
+					}
+				}
+			}
+			else {
+				for (y = 0; y < gridFaces; y ++) {
+					for (x = 0; x < gridFaces; x ++) {
+						float no[3];
+						float *a = CCG_grid_elem_co(&key, faceGridData, x, y );
+						float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y );
+						float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+						float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+						ccgDM_NormalFast(a, b, c, d, no);
+	
+						start = vindex[mat_orig_to_new[matnr]];
+						
+						copy_v3_v3(&varray[start], no);
+						copy_v3_v3(&varray[start + 3], no);
+						copy_v3_v3(&varray[start + 6], no);
+				
+						copy_v3_v3(&varray[start + 9], no);
+						copy_v3_v3(&varray[start + 12], no);
+						copy_v3_v3(&varray[start + 15], no);
+						
+						vindex[mat_orig_to_new[matnr]] += 18;
+					}
+				}
+			}
+		}
+	}
+}
+
+/* Only used by non-editmesh types */
+static void ccgDM_prepare_vertex_data(DerivedMesh *dm, float *varray, int *vindex,
+                                      int *mat_orig_to_new, void *UNUSED(user_data))
+{
+	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+	CCGSubSurf *ss = ccgdm->ss;
+	CCGKey key;
+	int gridSize = ccgSubSurf_getGridSize(ss);
+	int gridFaces = gridSize - 1;
+	DMFlagMat *faceFlags = ccgdm->faceFlags;
+	int i, totface = ccgSubSurf_getNumFaces(ss);
+	int matnr = -1, start;
+	
+	CCG_key_top_level(&key, ss);
+	ccgdm_pbvh_update(ccgdm);
+	
+	for (i = 0; i < totface; i++) {
+		CCGFace *f = ccgdm->faceMap[i].face;
+		int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f);
+		int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
+		
+		if (faceFlags) {
+			matnr = faceFlags[index].mat_nr;
+		}
+		else {
+			matnr = 0;
+		}
+		
+		for (S = 0; S < numVerts; S++) {
+			CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S);
+			for (y = 0; y < gridFaces; y++) {
+				for (x = 0; x < gridFaces; x++) {
+					float *a = CCG_grid_elem_co(&key, faceGridData, x, y);
+					float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y);
+					float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1);
+					float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1);
+
+					start = vindex[mat_orig_to_new[matnr]];
+					
+					copy_v3_v3(&varray[start], d);
+					copy_v3_v3(&varray[start + 3], c);
+					copy_v3_v3(&varray[start + 6], b);
+			
+					copy_v3_v3(&varray[start + 9], b);
+					copy_v3_v3(&varray[start + 12], d);
+					copy_v3_v3(&varray[start + 15], a);
+					
+					vindex[mat_orig_to_new[matnr]] += 18;
+				}
+			}
+		}
+	}
+}
+
+static void ccgDM_copy_gpu_data(DerivedMesh *dm, int type, float *varray, int *index,
+                         int *mat_orig_to_new, void *UNUSED(user_data))
+{	
+	switch(type) {
+		case GPU_BUFFER_VERTEX:
+			ccgDM_prepare_vertex_data(dm, varray, index, mat_orig_to_new, NULL);
+			break;
+		case GPU_BUFFER_NORMAL:
+			ccgDM_prepare_normal_data(dm, varray, index, mat_orig_to_new, NULL);
+			break;
+		default:
+			break;
+	}
+}
+
+static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) {
+//	GPUBufferMaterial *mat;
+	int *mat_orig_to_new;
+	CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
+	CCGSubSurf *ss = ccgdm->ss;
+	GPUDrawObject *gdo;
+	DMFlagMat *faceFlags 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list