diff options
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r-- | source/blender/gpu/intern/gpu_buffers.c | 289 |
1 files changed, 160 insertions, 129 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 8b5b8f491da..1aae8ed2271 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -53,6 +53,7 @@ #include "GPU_buffers.h" #include "GPU_compatibility.h" +#include "GPU_draw.h" typedef enum { GPU_BUFFER_VERTEX_STATE = 1, @@ -706,34 +707,6 @@ static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int * } } - -static void GPU_buffer_copy_color3(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user) -{ - int i, totface; - char *varray = (char *)varray_; - char *mcol = (char *)user; - MFace *f = dm->getTessFaceArray(dm); - - totface = dm->getNumTessFaces(dm); - for (i = 0; i < totface; i++, f++) { - int start = index[mat_orig_to_new[f->mat_nr]]; - - /* v1 v2 v3 */ - copy_v3_v3_char(&varray[start], &mcol[i * 12]); - copy_v3_v3_char(&varray[start + 3], &mcol[i * 12 + 3]); - copy_v3_v3_char(&varray[start + 6], &mcol[i * 12 + 6]); - index[mat_orig_to_new[f->mat_nr]] += 9; - - if (f->v4) { - /* v3 v4 v1 */ - copy_v3_v3_char(&varray[start + 9], &mcol[i * 12 + 6]); - copy_v3_v3_char(&varray[start + 12], &mcol[i * 12 + 9]); - copy_v3_v3_char(&varray[start + 15], &mcol[i * 12]); - index[mat_orig_to_new[f->mat_nr]] += 9; - } - } -} - static void copy_mcol_uc3(unsigned char *v, unsigned char *col) { v[0] = col[3]; @@ -818,28 +791,6 @@ static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(i } } -/* get the DerivedMesh's MCols; choose (in decreasing order of - * preference) from CD_ID_MCOL, CD_PREVIEW_MCOL, or CD_MCOL */ -static MCol *gpu_buffer_color_type(DerivedMesh *dm) -{ - MCol *c; - int type; - - type = CD_ID_MCOL; - c = DM_get_tessface_data_layer(dm, type); - if (!c) { - type = CD_PREVIEW_MCOL; - c = DM_get_tessface_data_layer(dm, type); - if (!c) { - type = CD_MCOL; - c = DM_get_tessface_data_layer(dm, type); - } - } - - dm->drawObject->colType = type; - return c; -} - typedef enum { GPU_BUFFER_VERTEX = 0, GPU_BUFFER_NORMAL, @@ -922,7 +873,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) /* special handling for MCol and UV buffers */ if (type == GPU_BUFFER_COLOR) { - if (!(user_data = gpu_buffer_color_type(dm))) + if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType))) return NULL; } else if (type == GPU_BUFFER_UV) { @@ -942,7 +893,7 @@ static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type) static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type) { GPUBuffer **buf; - + if (!dm->drawObject) dm->drawObject = GPU_drawobject_new(dm); @@ -1004,8 +955,28 @@ void GPU_uv_setup(DerivedMesh *dm) GLStates |= GPU_BUFFER_TEXCOORD_STATE; } -void GPU_color_setup(DerivedMesh *dm) +void GPU_color_setup(DerivedMesh *dm, int colType) { + if (!dm->drawObject) { + /* XXX Not really nice, but we need a valid gpu draw object to set the colType... + * Else we would have to add a new param to gpu_buffer_setup_common. */ + dm->drawObject = GPU_drawobject_new(dm); + dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; + dm->drawObject->colType = colType; + } + /* In paint mode, dm may stay the same during stroke, however we still want to update colors! + * Also check in case we changed color type (i.e. which MCol cdlayer we use). */ + else if ((dm->dirty & DM_DIRTY_MCOL_UPDATE_DRAW) || (colType != dm->drawObject->colType)) { + GPUBuffer **buf = gpu_drawobject_buffer_from_type(dm->drawObject, GPU_BUFFER_COLOR); + /* XXX Freeing this buffer is a bit stupid, as geometry has not changed, size should remain the same. + * Not sure though it would be worth defining a sort of gpu_buffer_update func - nor whether + * it is even possible ! */ + GPU_buffer_free(*buf); + *buf = NULL; + dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW; + dm->drawObject->colType = colType; + } + if (!gpu_buffer_setup_common(dm, GPU_BUFFER_COLOR)) return; @@ -1166,20 +1137,6 @@ void GPU_buffer_unbind(void) glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); } -/* confusion: code in cdderivedmesh calls both GPU_color_setup and - * GPU_color3_upload; both of these set the `colors' buffer, so seems - * like it will just needlessly overwrite? --nicholas */ -void GPU_color3_upload(DerivedMesh *dm, unsigned char *data) -{ - if (dm->drawObject == 0) - dm->drawObject = GPU_drawobject_new(dm); - GPU_buffer_free(dm->drawObject->colors); - - dm->drawObject->colors = gpu_buffer_setup(dm, dm->drawObject, 3, - sizeof(char) * 3 * dm->drawObject->tot_triangle_point, - GL_ARRAY_BUFFER_ARB, data, GPU_buffer_copy_color3); -} - void GPU_color_switch(int mode) { if (mode) { @@ -1270,11 +1227,11 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, * drawing and doesn't interact at all with the buffer code above */ /* Return false if VBO is either unavailable or disabled by the user, - true otherwise */ + * true otherwise */ static int gpu_vbo_enabled(void) { return (GLEW_ARB_vertex_buffer_object && - !(U.gameflags & USER_DISABLE_VBO)); + !(U.gameflags & USER_DISABLE_VBO)); } /* Convenience struct for building the VBO. */ @@ -1316,6 +1273,9 @@ struct GPU_Buffers { /* The PBVH ensures that either all faces in the node are smooth-shaded or all faces are flat-shaded */ int smooth; + + int show_diffuse_color; + float diffuse_color[4]; }; typedef enum { VBO_ENABLED, @@ -1339,23 +1299,24 @@ static void gpu_colors_disable(VBO_State vbo_state) static float gpu_color_from_mask(float mask) { - return (1.0f - mask) * 0.5f + 0.25f; + return 1.0f - mask * 0.75f; } -static void gpu_color_from_mask_copy(float mask, unsigned char out[3]) +static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], unsigned char out[3]) { - unsigned char color; - - color = gpu_color_from_mask(mask) * 255.0f; + float mask_color; + + mask_color = gpu_color_from_mask(mask) * 255.0f; - out[0] = color; - out[1] = color; - out[2] = color; + out[0] = diffuse_color[0] * mask_color; + out[1] = diffuse_color[1] * mask_color; + out[2] = diffuse_color[2] * mask_color; } -static void gpu_color_from_mask_set(float mask) +static void gpu_color_from_mask_set(float mask, float diffuse_color[4]) { - gpuGray3f(gpu_color_from_mask(mask)); + float color = gpu_color_from_mask(mask); + gpuColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); } static float gpu_color_from_mask_quad(const CCGKey *key, @@ -1371,36 +1332,50 @@ static float gpu_color_from_mask_quad(const CCGKey *key, static void gpu_color_from_mask_quad_copy(const CCGKey *key, CCGElem *a, CCGElem *b, CCGElem *c, CCGElem *d, + const float *diffuse_color, unsigned char out[3]) { - unsigned char color = + float mask_color = gpu_color_from_mask((*CCG_elem_mask(key, a) + *CCG_elem_mask(key, b) + *CCG_elem_mask(key, c) + *CCG_elem_mask(key, d)) * 0.25f) * 255.0f; - out[0] = color; - out[1] = color; - out[2] = color; + out[0] = diffuse_color[0] * mask_color; + out[1] = diffuse_color[1] * mask_color; + out[2] = diffuse_color[2] * mask_color; } static void gpu_color_from_mask_quad_set(const CCGKey *key, CCGElem *a, CCGElem *b, - CCGElem *c, CCGElem *d) + CCGElem *c, CCGElem *d, + float diffuse_color[4]) { - gpuGray3f(gpu_color_from_mask_quad(key, a, b, c, d)); + float color = gpu_color_from_mask_quad(key, a, b, c, d); + gpuColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); } void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, - int *vert_indices, int totvert, const float *vmask) + int *vert_indices, int totvert, const float *vmask, + int (*face_vert_indices)[4], int show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k; buffers->vmask = vmask; + buffers->show_diffuse_color = show_diffuse_color; if (buffers->vert_buf) { int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) { + MFace *f = buffers->mface + buffers->face_indices[0]; + + GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + } + + copy_v4_v4(buffers->diffuse_color, diffuse_color); /* Build VBO */ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); @@ -1421,11 +1396,27 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, 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); - } } + +#define UPDATE_VERTEX(face, vertex, index, diffuse_color) \ + { \ + VertexBufferFormat *out = vert_data + face_vert_indices[face][index]; \ + if (vmask) \ + gpu_color_from_mask_copy(vmask[vertex], diffuse_color, out->color); \ + else \ + rgb_float_to_uchar(out->color, diffuse_color); \ + } (void)0 + + for (i = 0; i < buffers->totface; i++) { + MFace *f = buffers->mface + buffers->face_indices[i]; + + UPDATE_VERTEX(i, f->v1, 0, diffuse_color); + UPDATE_VERTEX(i, f->v2, 1, diffuse_color); + UPDATE_VERTEX(i, f->v3, 2, diffuse_color); + if (f->v4) + UPDATE_VERTEX(i, f->v4, 3, diffuse_color); + } +#undef UPDATE_VERTEX } else { for (i = 0; i < buffers->totface; ++i) { @@ -1437,6 +1428,9 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, float fmask; + if (paint_is_face_hidden(f, mvert)) + continue; + /* Face normal and mask */ if (f->v4) { normal_quad_v3(fno, @@ -1448,7 +1442,7 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, fmask = (vmask[fv[0]] + vmask[fv[1]] + vmask[fv[2]] + - vmask[fv[3]]) * 0.25; + vmask[fv[3]]) * 0.25f; } } else { @@ -1471,8 +1465,11 @@ void GPU_update_mesh_buffers(GPU_Buffers *buffers, MVert *mvert, copy_v3_v3(out->co, v->co); memcpy(out->no, no, sizeof(short) * 3); + if (vmask) - gpu_color_from_mask_copy(fmask, out->color); + gpu_color_from_mask_copy(fmask, diffuse_color, out->color); + else + rgb_float_to_uchar(out->color, diffuse_color); vert_data++; } @@ -1506,6 +1503,8 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], buffers->index_type = GL_UNSIGNED_SHORT; buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; + buffers->show_diffuse_color = FALSE; + /* Count the number of visible triangles */ for (i = 0, tottri = 0; i < totface; ++i) { const MFace *f = &mface[face_indices[i]]; @@ -1560,7 +1559,7 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); } - if (buffers->index_buf || !buffers->smooth) + if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) glGenBuffersARB(1, &buffers->vert_buf); buffers->tot_tri = tottri; @@ -1574,16 +1573,27 @@ GPU_Buffers *GPU_build_mesh_buffers(int (*face_vert_indices)[4], void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, const DMFlagMat *grid_flag_mats, int *grid_indices, - int totgrid, const CCGKey *key) + int totgrid, const CCGKey *key, int show_diffuse_color) { VertexBufferFormat *vert_data; int i, j, k, x, y; + buffers->show_diffuse_color = show_diffuse_color; + /* Build VBO */ if (buffers->vert_buf) { int totvert = key->grid_area * totgrid; int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; const int has_mask = key->has_mask; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) { + const DMFlagMat *flags = &grid_flag_mats[grid_indices[0]]; + + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + } + + copy_v4_v4(buffers->diffuse_color, diffuse_color); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); glBufferDataARB(GL_ARRAY_BUFFER_ARB, @@ -1601,12 +1611,11 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, copy_v3_v3(vd->co, CCG_elem_co(key, elem)); if (smooth) { - normal_float_to_short_v3(vd->no, - CCG_elem_no(key, elem)); + normal_float_to_short_v3(vd->no, CCG_elem_no(key, elem)); if (has_mask) { gpu_color_from_mask_copy(*CCG_elem_mask(key, elem), - vd->color); + diffuse_color, vd->color); } } vd++; @@ -1642,6 +1651,7 @@ void GPU_update_grid_buffers(GPU_Buffers *buffers, CCGElem **grids, elems[1], elems[2], elems[3], + diffuse_color, vd->color); } } @@ -1761,7 +1771,7 @@ static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *to /* VBO is disabled; delete the previous buffer (if it exists) and * return an invalid handle */ - if (gpu_vbo_enabled()) { + if (!gpu_vbo_enabled()) { if (buffer) glDeleteBuffersARB(1, &buffer); return 0; @@ -1810,6 +1820,8 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, buffers->grid_hidden = grid_hidden; buffers->totgrid = totgrid; + buffers->show_diffuse_color = FALSE; + /* Count the number of quads */ totquad = gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); @@ -1854,6 +1866,11 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers) const MVert *mvert = buffers->mvert; int i, j; const int has_mask = (buffers->vmask != NULL); + const MFace *face = &buffers->mface[buffers->face_indices[0]]; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) + GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color); if (has_mask) { gpu_colors_enable(VBO_DISABLED); @@ -1874,7 +1891,7 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers) if (buffers->smooth) { for (j = 0; j < S; j++) { if (has_mask) { - gpu_color_from_mask_set(buffers->vmask[fv[j]]); + gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color); } gpuNormal3sv(mvert[fv[j]].no); gpuVertex3fv(mvert[fv[j]].co); @@ -1900,10 +1917,10 @@ static void gpu_draw_buffers_legacy_mesh(GPU_Buffers *buffers) buffers->vmask[fv[1]] + buffers->vmask[fv[2]]); if (f->v4) - fmask = (fmask + buffers->vmask[fv[3]]) * 0.25; + fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f; else fmask /= 3.0f; - gpu_color_from_mask_set(fmask); + gpu_color_from_mask_set(fmask, diffuse_color); } for (j = 0; j < S; j++) @@ -1925,6 +1942,11 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) const CCGKey *key = &buffers->gridkey; int i, j, x, y, gridsize = buffers->gridkey.grid_size; const int has_mask = key->has_mask; + const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]]; + float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + + if (buffers->show_diffuse_color) + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); if (has_mask) { gpu_colors_enable(VBO_DISABLED); @@ -1958,7 +1980,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) if (buffers->smooth) { for (j = 0; j < 4; j++) { if (has_mask) { - gpu_color_from_mask_set(*CCG_elem_mask(key, e[j])); + gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color); } gpuNormal3fv(CCG_elem_no(key, e[j])); @@ -1975,7 +1997,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) gpuNormal3fv(fno); if (has_mask) { - gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3]); + gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color); } for (j = 0; j < 4; j++) @@ -1994,13 +2016,13 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) CCGElem *b = CCG_grid_elem(key, grid, x, y + 1); if (has_mask) { - gpu_color_from_mask_set(*CCG_elem_mask(key, a)); + gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color); } gpuNormal3fv(CCG_elem_no(key, a)); gpuVertex3fv(CCG_elem_co(key, a)); if (has_mask) { - gpu_color_from_mask_set(*CCG_elem_mask(key, b)); + gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color); } gpuNormal3fv(CCG_elem_no(key, b)); @@ -2029,7 +2051,7 @@ static void gpu_draw_buffers_legacy_grids(GPU_Buffers *buffers) gpuNormal3fv(fno); if (has_mask) { - gpu_color_from_mask_quad_set(key, a, b, c, d); + gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color); } } @@ -2050,8 +2072,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); - if (buffers->totface) { const MFace *f = &buffers->mface[buffers->face_indices[0]]; if (!setMaterial(f->mat_nr + 1, NULL)) @@ -2068,13 +2088,7 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) if (buffers->vert_buf) { glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - if (has_mask) { - gpu_colors_enable(VBO_ENABLED); - } - else { - gpu_colors_enable(VBO_DISABLED); - gpuCurrentColor4ub(0xff, 0xff, 0xff, 0xff); - } + gpu_colors_enable(VBO_ENABLED); glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); @@ -2091,10 +2105,8 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) offset + offsetof(VertexBufferFormat, co)); glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), offset + offsetof(VertexBufferFormat, no)); - if (has_mask) { - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), - offset + offsetof(VertexBufferFormat, color)); - } + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), + offset + offsetof(VertexBufferFormat, color)); glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0); @@ -2108,10 +2120,8 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) (void *)offsetof(VertexBufferFormat, co)); glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), (void *)offsetof(VertexBufferFormat, no)); - if (has_mask) { - glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), - (void *)offsetof(VertexBufferFormat, color)); - } + glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), + (void *)offsetof(VertexBufferFormat, color)); if (buffers->index_buf) glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0); @@ -2125,12 +2135,7 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - if (has_mask) { - gpu_colors_disable(VBO_ENABLED); - } - else { - gpu_colors_disable(VBO_DISABLED); - } + gpu_colors_disable(VBO_ENABLED); } /* fallbacks if we are out of memory or VBO is disabled */ else if (buffers->totface) { @@ -2141,6 +2146,32 @@ void GPU_draw_buffers(GPU_Buffers *buffers, DMSetMaterial setMaterial) } } +int GPU_buffers_diffuse_changed(GPU_Buffers *buffers, int show_diffuse_color) +{ + float diffuse_color[4]; + + if (buffers->show_diffuse_color != show_diffuse_color) + return TRUE; + + if (buffers->show_diffuse_color == FALSE) + return FALSE; + + if (buffers->mface) { + MFace *f = buffers->mface + buffers->face_indices[0]; + + GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); + } + else { + const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]]; + + GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color); + } + + return diffuse_color[0] != buffers->diffuse_color[0] || + diffuse_color[1] != buffers->diffuse_color[1] || + diffuse_color[2] != buffers->diffuse_color[2]; +} + void GPU_free_buffers(GPU_Buffers *buffers) { if (buffers) { |