diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-12-08 02:03:49 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-12-08 02:03:49 +0400 |
commit | a5fb261016f0dd9a1393da4aadc76272a0c248b0 (patch) | |
tree | 473c21d434b885fd1b8e8eb8004f4242ff0a9d88 /source | |
parent | 5310ee5e2cd4c16ff9dbdc205db1404982ad1551 (diff) |
Fix #29520: issue drawing with VBO + GLSL + alpha pass. Includes some refactoring
to hopefully make alpha material drawing code more clear.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 7 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 12 | ||||
-rw-r--r-- | source/blender/gpu/GPU_draw.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_draw.c | 57 |
4 files changed, 45 insertions, 33 deletions
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index aade98ec9da..d4d83fec0eb 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1243,11 +1243,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, } } } - if(!dodraw) { - continue; - } - if( numdata != 0 ) { + if(dodraw && numdata != 0 ) { offset = 0; if(attribs.totorco) { copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]); @@ -1289,7 +1286,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, } curface++; if(mface->v4) { - if( numdata != 0 ) { + if(dodraw && numdata != 0 ) { offset = 0; if(attribs.totorco) { copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 9505ea5098d..f6f2c35163f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -265,7 +265,7 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt) return (scene->gm.matmode == GAME_MAT_GLSL) && (dt > OB_SOLID); } -static int check_material_alpha(Base *base, int glsl) +static int check_alpha_pass(Base *base) { if(base->flag & OB_FROMDUPLI) return 0; @@ -273,7 +273,7 @@ static int check_material_alpha(Base *base, int glsl) if(G.f & G_PICKSEL) return 0; - return (glsl || (base->object->dtx & OB_DRAWTRANSP)); + return (base->object->dtx & OB_DRAWTRANSP); } /***/ @@ -3294,7 +3294,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D Object *obedit= scene->obedit; Mesh *me= ob->data; EditMesh *em= me->edit_mesh; - int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i; + int do_alpha_after= 0, drawlinked= 0, retval= 0, glsl, check_alpha, i; /* If we are drawing shadows and any of the materials don't cast a shadow, * then don't draw the object */ @@ -3339,11 +3339,11 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ if(me->totface<=4 || ED_view3d_boundbox_clip(rv3d, ob->obmat, (ob->bb)? ob->bb: me->bb)) { glsl = draw_glsl_material(scene, ob, v3d, dt); - check_alpha = check_material_alpha(base, glsl); + check_alpha = check_alpha_pass(base); if(dt==OB_SOLID || glsl) { GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, - (check_alpha)? &do_alpha_pass: NULL); + (check_alpha)? &do_alpha_after: NULL); } draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, flag); @@ -3355,7 +3355,7 @@ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } /* GPU_begin_object_materials checked if this is needed */ - if(do_alpha_pass) { + if(do_alpha_after) { if(ob->dtx & OB_DRAWXRAY) { add_view3d_after(&v3d->afterdraw_xraytransp, base, flag); } diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index dc1f80ca903..f73bd402167 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -69,7 +69,7 @@ void GPU_state_print(void); * - after drawing, the material must be disabled again */ void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, - struct Scene *scene, struct Object *ob, int glsl, int *do_alpha_pass); + struct Scene *scene, struct Object *ob, int glsl, int *do_alpha_after); void GPU_end_object_materials(void); int GPU_enable_material(int nr, void *attribs); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index afd22fb70a0..3cd3cde8aad 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -942,7 +942,7 @@ static struct GPUMaterialState { GPUBlendMode *alphablend; GPUBlendMode alphablend_fixed[FIXEDMAT]; - int alphapass; + int use_alpha_pass, is_alpha_pass; int lastmatnr, lastretval; GPUBlendMode lastalphablend; @@ -993,7 +993,7 @@ static Material *gpu_active_node_material(Material *ma) return ma; } -void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_pass) +void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, int glsl, int *do_alpha_after) { Material *ma; GPUMaterial *gpumat; @@ -1015,9 +1015,15 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.gviewmat= rv3d->viewmat; GMS.gviewinv= rv3d->viewinv; - GMS.alphapass = (v3d && v3d->transp); - if(do_alpha_pass) - *do_alpha_pass = 0; + /* alpha pass setup. there's various cases to handle here: + * object transparency on: only solid materials draw in the first pass, + and only transparent in the second 'alpha' pass. + * object transparency off: for glsl we draw both in a single pass, and + for solid we don't use transparency at all. */ + GMS.use_alpha_pass = (do_alpha_after != NULL); + GMS.is_alpha_pass = (v3d && v3d->transp); + if(GMS.use_alpha_pass) + *do_alpha_after = 0; if(GMS.totmat > FIXEDMAT) { GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf"); @@ -1064,20 +1070,23 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O /* fixed function opengl materials */ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); - alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; - if(do_alpha_pass && GMS.alphapass) + if(GMS.use_alpha_pass) { GMS.matbuf[a].diff[3]= ma->alpha; - else + alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + } + else { GMS.matbuf[a].diff[3]= 1.0f; + alphablend = GPU_BLEND_SOLID; + } } - /* setting do_alpha_pass = 1 indicates this object needs to be + /* setting do_alpha_after = 1 indicates this object needs to be * drawn in a second alpha pass for improved blending */ - if(do_alpha_pass) { - GMS.alphablend[a]= alphablend; - if(ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT) && !GMS.alphapass) - *do_alpha_pass= 1; - } + if(GMS.use_alpha_pass && !GMS.is_alpha_pass) + if(ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) + *do_alpha_after= 1; + + GMS.alphablend[a]= alphablend; } /* let's start with a clean state */ @@ -1122,20 +1131,26 @@ int GPU_enable_material(int nr, void *attribs) /* unbind glsl material */ if(GMS.gboundmat) { - if(GMS.alphapass) glDepthMask(0); + if(GMS.is_alpha_pass) glDepthMask(0); GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); GMS.gboundmat= NULL; } /* draw materials with alpha in alpha pass */ GMS.lastmatnr = nr; - GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); - if(GMS.alphapass) - GMS.lastretval = !GMS.lastretval; + GMS.lastretval = 1; + + if(GMS.use_alpha_pass) { + GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); + if(GMS.is_alpha_pass) + GMS.lastretval = !GMS.lastretval; + } + else + GMS.lastretval = !GMS.is_alpha_pass; if(GMS.lastretval) { /* for alpha pass, use alpha blend */ - alphablend = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID; + alphablend = GMS.alphablend[nr]; if(gattribs && GMS.gmatbuf[nr]) { /* bind glsl material and get attributes */ @@ -1152,7 +1167,7 @@ int GPU_enable_material(int nr, void *attribs) if(mat->game.alpha_blend != GPU_BLEND_SOLID) alphablend= mat->game.alpha_blend; - if(GMS.alphapass) glDepthMask(1); + if(GMS.is_alpha_pass) glDepthMask(1); } else { /* or do fixed function opengl material */ @@ -1188,7 +1203,7 @@ void GPU_disable_material(void) GMS.lastretval= 1; if(GMS.gboundmat) { - if(GMS.alphapass) glDepthMask(0); + if(GMS.is_alpha_pass) glDepthMask(0); GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); GMS.gboundmat= NULL; } |