Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/intern/gpu_buffers.c
| Show First 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | |||||
| /* -1 - undefined, 0 - vertex arrays, 1 - VBOs */ | /* -1 - undefined, 0 - vertex arrays, 1 - VBOs */ | ||||
| static int useVBOs = -1; | static int useVBOs = -1; | ||||
| static GPUBufferState GLStates = 0; | static GPUBufferState GLStates = 0; | ||||
| static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; | static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; | ||||
| static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER; | static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER; | ||||
| #define BUFFER_OFFSET(n) ((GLubyte *)NULL + n) | |||||
| /* stores recently-deleted buffers so that new buffers won't have to | /* stores recently-deleted buffers so that new buffers won't have to | ||||
| * be recreated as often | * be recreated as often | ||||
| * | * | ||||
| * only one instance of this pool is created, stored in | * only one instance of this pool is created, stored in | ||||
| * gpu_buffer_pool | * gpu_buffer_pool | ||||
| * | * | ||||
| * note that the number of buffers in the pool is usually limited to | * note that the number of buffers in the pool is usually limited to | ||||
| * MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily | * MAX_FREE_GPU_BUFFERS, but this limit may be exceeded temporarily | ||||
| ▲ Show 20 Lines • Show All 1,250 Lines • ▼ Show 20 Lines | struct GPU_PBVH_Buffers { | ||||
| const DMFlagMat *grid_flag_mats; | const DMFlagMat *grid_flag_mats; | ||||
| BLI_bitmap * const *grid_hidden; | BLI_bitmap * const *grid_hidden; | ||||
| int *grid_indices; | int *grid_indices; | ||||
| int totgrid; | int totgrid; | ||||
| int has_hidden; | int has_hidden; | ||||
| int use_bmesh; | int use_bmesh; | ||||
| unsigned int tot_tri, tot_quad; | unsigned int tot_tri, tot_grid_quad, tot_quad; | ||||
| /* The PBVH ensures that either all faces in the node are | /* The PBVH ensures that either all faces in the node are | ||||
| * smooth-shaded or all faces are flat-shaded */ | * smooth-shaded or all faces are flat-shaded */ | ||||
| int smooth; | int smooth; | ||||
| int show_diffuse_color; | int show_diffuse_color; | ||||
| float diffuse_color[4]; | float diffuse_color[4]; | ||||
| }; | }; | ||||
| ▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | static void gpu_color_from_mask_quad_set(const CCGKey *key, | ||||
| glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); | glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color); | ||||
| } | } | ||||
| void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert, | void GPU_update_mesh_pbvh_buffers(GPU_PBVH_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) | int (*face_vert_indices)[4], int show_diffuse_color) | ||||
| { | { | ||||
| VertexBufferFormat *vert_data; | VertexBufferFormat *vert_data; | ||||
| int i, j, k; | int i, k; | ||||
| buffers->vmask = vmask; | buffers->vmask = vmask; | ||||
| buffers->show_diffuse_color = show_diffuse_color; | buffers->show_diffuse_color = show_diffuse_color; | ||||
| if (buffers->vert_buf) { | if (buffers->vert_buf) { | ||||
| int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); | int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3 + buffers->tot_quad * 4)); | ||||
| float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; | float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; | ||||
| if (buffers->show_diffuse_color) { | if (buffers->show_diffuse_color) { | ||||
| MFace *f = buffers->mface + buffers->face_indices[0]; | MFace *f = buffers->mface + buffers->face_indices[0]; | ||||
| GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); | GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color); | ||||
| } | } | ||||
| Show All 36 Lines | #define UPDATE_VERTEX(face, vertex, index, diffuse_color) \ | ||||
| UPDATE_VERTEX(i, f->v2, 1, diffuse_color); | UPDATE_VERTEX(i, f->v2, 1, diffuse_color); | ||||
| UPDATE_VERTEX(i, f->v3, 2, diffuse_color); | UPDATE_VERTEX(i, f->v3, 2, diffuse_color); | ||||
| if (f->v4) | if (f->v4) | ||||
| UPDATE_VERTEX(i, f->v4, 3, diffuse_color); | UPDATE_VERTEX(i, f->v4, 3, diffuse_color); | ||||
| } | } | ||||
| #undef UPDATE_VERTEX | #undef UPDATE_VERTEX | ||||
| } | } | ||||
| else { | else { | ||||
| VertexBufferFormat *vert_data_quad = vert_data + buffers->tot_tri * 3; | |||||
| for (i = 0; i < buffers->totface; ++i) { | for (i = 0; i < buffers->totface; ++i) { | ||||
| const MFace *f = &buffers->mface[buffers->face_indices[i]]; | const MFace *f = &buffers->mface[buffers->face_indices[i]]; | ||||
| const unsigned int *fv = &f->v1; | const unsigned int *fv = &f->v1; | ||||
| const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}}; | |||||
| float fno[3]; | float fno[3]; | ||||
| short no[3]; | short no[3]; | ||||
| float fmask; | float fmask; | ||||
| if (paint_is_face_hidden(f, mvert)) | if (paint_is_face_hidden(f, mvert)) | ||||
| continue; | continue; | ||||
| Show All 19 Lines | #undef UPDATE_VERTEX | ||||
| if (vmask) { | if (vmask) { | ||||
| fmask = (vmask[fv[0]] + | fmask = (vmask[fv[0]] + | ||||
| vmask[fv[1]] + | vmask[fv[1]] + | ||||
| vmask[fv[2]]) / 3.0f; | vmask[fv[2]]) / 3.0f; | ||||
| } | } | ||||
| } | } | ||||
| normal_float_to_short_v3(no, fno); | normal_float_to_short_v3(no, fno); | ||||
| for (j = 0; j < (f->v4 ? 2 : 1); j++) { | if (f->v4) { | ||||
| for (k = 0; k < 4; k++) { | |||||
| const MVert *v = &mvert[fv[k]]; | |||||
| VertexBufferFormat *out = vert_data_quad; | |||||
| copy_v3_v3(out->co, v->co); | |||||
| memcpy(out->no, no, sizeof(short) * 3); | |||||
| if (vmask) | |||||
| gpu_color_from_mask_copy(fmask, diffuse_color, out->color); | |||||
| else | |||||
| rgb_float_to_uchar(out->color, diffuse_color); | |||||
| vert_data_quad++; | |||||
| } | |||||
| } | |||||
| else { | |||||
| for (k = 0; k < 3; k++) { | for (k = 0; k < 3; k++) { | ||||
| const MVert *v = &mvert[fv[vi[j][k]]]; | const MVert *v = &mvert[fv[k]]; | ||||
| VertexBufferFormat *out = vert_data; | VertexBufferFormat *out = vert_data; | ||||
| copy_v3_v3(out->co, v->co); | copy_v3_v3(out->co, v->co); | ||||
| memcpy(out->no, no, sizeof(short) * 3); | memcpy(out->no, no, sizeof(short) * 3); | ||||
| if (vmask) | if (vmask) | ||||
| gpu_color_from_mask_copy(fmask, diffuse_color, out->color); | gpu_color_from_mask_copy(fmask, diffuse_color, out->color); | ||||
| else | else | ||||
| Show All 19 Lines | |||||
| } | } | ||||
| GPU_PBVH_Buffers *GPU_build_pbvh_mesh_buffers(int (*face_vert_indices)[4], | GPU_PBVH_Buffers *GPU_build_pbvh_mesh_buffers(int (*face_vert_indices)[4], | ||||
| MFace *mface, MVert *mvert, | MFace *mface, MVert *mvert, | ||||
| int *face_indices, | int *face_indices, | ||||
| int totface) | int totface) | ||||
| { | { | ||||
| GPU_PBVH_Buffers *buffers; | GPU_PBVH_Buffers *buffers; | ||||
| unsigned short *tri_data; | int i, k, tottri = 0, totquad = 0; | ||||
| int i, j, k, tottri; | |||||
| buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); | buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); | ||||
| buffers->index_type = GL_UNSIGNED_SHORT; | buffers->index_type = GL_UNSIGNED_SHORT; | ||||
| buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; | buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH; | ||||
| buffers->show_diffuse_color = FALSE; | buffers->show_diffuse_color = FALSE; | ||||
| /* Count the number of visible triangles */ | /* Count the number of visible triangles */ | ||||
| for (i = 0, tottri = 0; i < totface; ++i) { | for (i = 0; i < totface; ++i) { | ||||
| const MFace *f = &mface[face_indices[i]]; | const MFace *f = &mface[face_indices[i]]; | ||||
| if (!paint_is_face_hidden(f, mvert)) | if (!paint_is_face_hidden(f, mvert)) | ||||
| tottri += f->v4 ? 2 : 1; | (f->v4)? totquad++ : tottri++; | ||||
| } | } | ||||
| /* An element index buffer is used for smooth shading, but flat | /* An element index buffer is used for smooth shading, but flat | ||||
| * shading requires separate vertex normals so an index buffer is | * shading requires separate vertex normals so an index buffer is | ||||
| * can't be used there. */ | * can't be used there. */ | ||||
| if (gpu_vbo_enabled() && buffers->smooth) | if (gpu_vbo_enabled() && buffers->smooth) | ||||
| glGenBuffersARB(1, &buffers->index_buf); | glGenBuffersARB(1, &buffers->index_buf); | ||||
| if (buffers->index_buf) { | if (buffers->index_buf) { | ||||
| unsigned short *tri_data; | |||||
| unsigned short *quad_data; | |||||
| /* Generate index buffer object */ | /* Generate index buffer object */ | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | ||||
| glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, | glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, | ||||
| sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB); | sizeof(unsigned short) * (tottri * 3 + totquad * 4), NULL, GL_STATIC_DRAW_ARB); | ||||
| /* Fill the triangle buffer */ | /* Fill the triangle buffer */ | ||||
| tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | ||||
| quad_data = tri_data + tottri * 3; | |||||
| if (tri_data) { | if (tri_data) { | ||||
| for (i = 0; i < totface; ++i) { | for (i = 0; i < totface; ++i) { | ||||
| const MFace *f = mface + face_indices[i]; | const MFace *f = mface + face_indices[i]; | ||||
| int v[3]; | |||||
| /* Skip hidden faces */ | /* Skip hidden faces */ | ||||
| if (paint_is_face_hidden(f, mvert)) | if (paint_is_face_hidden(f, mvert)) | ||||
| continue; | continue; | ||||
| v[0] = 0; | if (f->v4) { | ||||
| v[1] = 1; | for (k = 0; k < 4; ++k) { | ||||
| v[2] = 2; | *quad_data = face_vert_indices[i][k]; | ||||
| quad_data++; | |||||
| for (j = 0; j < (f->v4 ? 2 : 1); ++j) { | } | ||||
| } | |||||
| else { | |||||
| for (k = 0; k < 3; ++k) { | for (k = 0; k < 3; ++k) { | ||||
| *tri_data = face_vert_indices[i][v[k]]; | *tri_data = face_vert_indices[i][k]; | ||||
| tri_data++; | tri_data++; | ||||
| } | } | ||||
| v[0] = 3; | |||||
| v[1] = 0; | |||||
| v[2] = 2; | |||||
| } | } | ||||
| } | } | ||||
| glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); | glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); | ||||
| } | } | ||||
| else { | else { | ||||
| glDeleteBuffersARB(1, &buffers->index_buf); | glDeleteBuffersARB(1, &buffers->index_buf); | ||||
| buffers->index_buf = 0; | buffers->index_buf = 0; | ||||
| } | } | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | ||||
| } | } | ||||
| if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) | if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth)) | ||||
| glGenBuffersARB(1, &buffers->vert_buf); | glGenBuffersARB(1, &buffers->vert_buf); | ||||
| buffers->tot_tri = tottri; | buffers->tot_tri = tottri; | ||||
| buffers->tot_quad = totquad; | |||||
| buffers->mface = mface; | buffers->mface = mface; | ||||
| buffers->face_indices = face_indices; | buffers->face_indices = face_indices; | ||||
| buffers->totface = totface; | buffers->totface = totface; | ||||
| return buffers; | return buffers; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 247 Lines • ▼ Show 20 Lines | GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid, | ||||
| buffers->totgrid = totgrid; | buffers->totgrid = totgrid; | ||||
| buffers->show_diffuse_color = FALSE; | buffers->show_diffuse_color = FALSE; | ||||
| /* Count the number of quads */ | /* Count the number of quads */ | ||||
| totquad = gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); | totquad = gpu_count_grid_quads(grid_hidden, grid_indices, totgrid, gridsize); | ||||
| if (totquad == fully_visible_totquad) { | if (totquad == fully_visible_totquad) { | ||||
| buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad); | buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_grid_quad); | ||||
| buffers->has_hidden = 0; | buffers->has_hidden = 0; | ||||
| } | } | ||||
| else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) { | else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) { | ||||
| /* Build new VBO */ | /* Build new VBO */ | ||||
| glGenBuffersARB(1, &buffers->index_buf); | glGenBuffersARB(1, &buffers->index_buf); | ||||
| if (buffers->index_buf) { | if (buffers->index_buf) { | ||||
| buffers->tot_quad = totquad; | buffers->tot_grid_quad = totquad; | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | ||||
| if (totgrid * gridsize * gridsize < USHRT_MAX) { | if (totgrid * gridsize * gridsize < USHRT_MAX) { | ||||
| buffers->index_type = GL_UNSIGNED_SHORT; | buffers->index_type = GL_UNSIGNED_SHORT; | ||||
| FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf); | FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf); | ||||
| } | } | ||||
| else { | else { | ||||
| ▲ Show 20 Lines • Show All 499 Lines • ▼ Show 20 Lines | if (buffers->vert_buf) { | ||||
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); | glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf); | ||||
| if (buffers->index_buf) | if (buffers->index_buf) | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf); | ||||
| if (wireframe) | if (wireframe) | ||||
| glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | ||||
| if (buffers->tot_quad) { | if (buffers->tot_grid_quad) { | ||||
| char *offset = 0; | char *offset = 0; | ||||
| int i, last = buffers->has_hidden ? 1 : buffers->totgrid; | int i, last = buffers->has_hidden ? 1 : buffers->totgrid; | ||||
| for (i = 0; i < last; i++) { | for (i = 0; i < last; i++) { | ||||
| glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), | glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), | ||||
| offset + offsetof(VertexBufferFormat, co)); | offset + offsetof(VertexBufferFormat, co)); | ||||
| glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), | glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), | ||||
| offset + offsetof(VertexBufferFormat, no)); | offset + offsetof(VertexBufferFormat, no)); | ||||
| glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), | glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), | ||||
| offset + offsetof(VertexBufferFormat, color)); | offset + offsetof(VertexBufferFormat, color)); | ||||
| glDrawElements(GL_QUADS, buffers->tot_quad * 4, buffers->index_type, 0); | glDrawElements(GL_QUADS, buffers->tot_grid_quad * 4, buffers->index_type, 0); | ||||
| offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat); | offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| int totelem = buffers->tot_tri * 3; | |||||
| glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), | glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat), | ||||
| (void *)offsetof(VertexBufferFormat, co)); | (void *)offsetof(VertexBufferFormat, co)); | ||||
| glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), | glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat), | ||||
| (void *)offsetof(VertexBufferFormat, no)); | (void *)offsetof(VertexBufferFormat, no)); | ||||
| glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), | glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat), | ||||
| (void *)offsetof(VertexBufferFormat, color)); | (void *)offsetof(VertexBufferFormat, color)); | ||||
| if (buffers->index_buf) | if (buffers->index_buf) { | ||||
| glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0); | int totelem_tri = buffers->tot_tri * 3; | ||||
| else | int totelem_quad = buffers->tot_quad * 4; | ||||
| glDrawArrays(GL_TRIANGLES, 0, totelem); | short offset_size = (buffers->index_type == GL_UNSIGNED_SHORT) ? sizeof(short) : sizeof(int); | ||||
| if (totelem_tri) | |||||
| glDrawElements(GL_TRIANGLES, totelem_tri, buffers->index_type, 0); | |||||
| if (totelem_quad) | |||||
| glDrawElements(GL_QUADS, totelem_quad, buffers->index_type, BUFFER_OFFSET(offset_size * totelem_tri)); | |||||
| } | |||||
| else { | |||||
| int totelem_tri = buffers->tot_tri * 3; | |||||
| int totelem_quad = buffers->tot_quad * 4; | |||||
| if (totelem_tri) | |||||
| glDrawArrays(GL_TRIANGLES, 0, totelem_tri); | |||||
| if (totelem_quad) | |||||
| glDrawArrays(GL_QUADS, buffers->tot_tri * 3, totelem_quad); | |||||
| } | |||||
| } | } | ||||
| if (wireframe) | if (wireframe) | ||||
| glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||||
| glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); | glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); | ||||
| if (buffers->index_buf) | if (buffers->index_buf) | ||||
| glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | ||||
| ▲ Show 20 Lines • Show All 90 Lines • Show Last 20 Lines | |||||