Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2012-10-06 20:52:52 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2012-10-06 20:52:52 +0400
commit0c0fa7dde66269f451d5b6ebe95860dd9e913d5f (patch)
tree4deabf5be6cbbf8772de494fe9094cf5b0084c65 /source/blender/gpu
parent1df170bb96158abebc123256df04cebe6a5f8f08 (diff)
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.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c112
1 files changed, 91 insertions, 21 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index a0a379c3cee..201162262b2 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -1397,28 +1397,88 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert,
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;
-
- 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);
+ /* 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);
+ }
+ }
+ }
+ 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++;
+ }
+ }
}
}
@@ -1454,8 +1514,11 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4],
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 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4],
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 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers)
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 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
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,7 +2068,9 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
}
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;
@@ -2027,6 +2091,8 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
}
}
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 GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial)
(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);