diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-08-25 16:05:28 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2015-08-25 16:11:56 +0300 |
commit | f1e68474e051667b85ac804bded8fa2c8e0ff374 (patch) | |
tree | 9e3470179f56bff64807d944ad8af32141fcbc45 /source/blender/blenkernel/intern | |
parent | 50917edad54d2be0f5e3a6630382e28ab1fd32e0 (diff) |
OpenSubdiv: Support for multiple materials in solid shading mode
Implementation is less optimal compared to non-opensubdiv drawing but
it is now as good as we can do it without affecting on how patches are
being created by OpenSubdiv.
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/CCGSubSurf.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c | 25 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subsurf_ccg.c | 79 |
3 files changed, 94 insertions, 16 deletions
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index e9ad4c52531..a825cffe7a0 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -215,6 +215,12 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl); void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads, int start_partition, int num_partitions); +/* Get number of base faces in a particular GL mesh. */ +int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss); + +/* Get number of vertices in base faces in a particular GL mesh. */ +int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face); + /* Controls whether CCG are needed (Cmeaning CPU evaluation) or fully GPU compute * and draw is allowed. */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c index eb7c3bf6ffd..fcc46308efa 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c @@ -308,6 +308,31 @@ void ccgSubSurf_drawGLMesh(CCGSubSurf *ss, bool fill_quads, } } +int ccgSubSurf_getNumGLMeshBaseFaces(CCGSubSurf *ss) +{ + const OpenSubdiv_TopologyRefinerDescr *topology_refiner; + if (ss->osd_topology_refiner != NULL) { + topology_refiner = ss->osd_topology_refiner; + } + else { + topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh); + } + return openSubdiv_topologyRefinerGetNumFaces(topology_refiner); +} + +/* Get number of vertices in base faces in a particular GL mesh. */ +int ccgSubSurf_getNumGLMeshBaseFaceVerts(CCGSubSurf *ss, int face) +{ + const OpenSubdiv_TopologyRefinerDescr *topology_refiner; + if (ss->osd_topology_refiner != NULL) { + topology_refiner = ss->osd_topology_refiner; + } + else { + topology_refiner = openSubdiv_getGLMeshTopologyRefiner(ss->osd_mesh); + } + return openSubdiv_topologyRefinerGetNumFaceVerts(topology_refiner, face); +} + void ccgSubSurf_setSkipGrids(CCGSubSurf *ss, bool skip_grids) { ss->skip_grids = skip_grids; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e38d62cd9bc..867065b060d 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -2622,24 +2622,72 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) #ifdef WITH_OPENSUBDIV if (ccgdm->useGpuBackend) { CCGSubSurf *ss = ccgdm->ss; - DMFlagMat *faceFlags = ccgdm->faceFlags; - int new_matnr; - bool draw_smooth; + const DMFlagMat *faceFlags = ccgdm->faceFlags; + const int level = ccgSubSurf_getSubdivisionLevels(ss); + const int face_side = 1 << level; + const int grid_side = 1 << (level - 1); + const int face_patches = face_side * face_side; + const int grid_patches = grid_side * grid_side; + const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss); + int i, current_patch = 0; + int mat_nr = -1; + bool draw_smooth = false; + int start_draw_patch = -1, num_draw_patches = 0; if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL) == false)) { return; } - /* TODO(sergey): Single matierial currently. */ - if (faceFlags) { - draw_smooth = (faceFlags[0].flag & ME_SMOOTH); - new_matnr = (faceFlags[0].mat_nr + 1); - } - else { - draw_smooth = true; - new_matnr = 1; + if (setMaterial == NULL) { + ccgSubSurf_drawGLMesh(ss, + true, + -1, + -1); + return; } - if (setMaterial && setMaterial(new_matnr, NULL)) { - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, true, -1, -1); + for (i = 0; i < num_base_faces; ++i) { + const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i); + const int num_patches = (num_face_verts == 4) ? face_patches + : num_face_verts * grid_patches; + int new_matnr; + bool new_draw_smooth; + if (faceFlags) { + new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH); + new_matnr = (faceFlags[i].mat_nr + 1); + } + else { + new_draw_smooth = true; + new_matnr = 1; + } + if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) { + if (num_draw_patches != 0) { + bool do_draw = setMaterial == NULL || + setMaterial(mat_nr, NULL); + if (do_draw) { + glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); + ccgSubSurf_drawGLMesh(ss, + true, + start_draw_patch, + num_draw_patches); + } + } + start_draw_patch = current_patch; + num_draw_patches = num_patches; + mat_nr = new_matnr; + draw_smooth = new_draw_smooth; + } + else { + num_draw_patches += num_patches; + } + current_patch += num_patches; + } + if (num_draw_patches != 0) { + bool do_draw = setMaterial(mat_nr, NULL); + if (do_draw) { + glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); + ccgSubSurf_drawGLMesh(ss, + true, + start_draw_patch, + num_draw_patches); + } } return; } @@ -4528,8 +4576,7 @@ static void set_ccgdm_gpu_geometry(CCGDerivedMesh *ccgdm, DerivedMesh *dm) for (index = 0; index < totface; index++) { faceFlags->flag = mpoly ? mpoly[index].flag : 0; - /* faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0; */ - faceFlags->mat_nr = 0; + faceFlags->mat_nr = mpoly ? mpoly[index].mat_nr : 0; faceFlags++; } |