Fix #29520: issue drawing with VBO + GLSL + alpha pass. Includes some refactoring
to hopefully make alpha material drawing code more clear.
This commit is contained in:
@@ -1243,11 +1243,8 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!dodraw) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( numdata != 0 ) {
|
if(dodraw && numdata != 0 ) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if(attribs.totorco) {
|
if(attribs.totorco) {
|
||||||
copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
|
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++;
|
curface++;
|
||||||
if(mface->v4) {
|
if(mface->v4) {
|
||||||
if( numdata != 0 ) {
|
if(dodraw && numdata != 0 ) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
if(attribs.totorco) {
|
if(attribs.totorco) {
|
||||||
copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
|
copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
|
||||||
|
@@ -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);
|
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)
|
if(base->flag & OB_FROMDUPLI)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -273,7 +273,7 @@ static int check_material_alpha(Base *base, int glsl)
|
|||||||
if(G.f & G_PICKSEL)
|
if(G.f & G_PICKSEL)
|
||||||
return 0;
|
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;
|
Object *obedit= scene->obedit;
|
||||||
Mesh *me= ob->data;
|
Mesh *me= ob->data;
|
||||||
EditMesh *em= me->edit_mesh;
|
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,
|
/* If we are drawing shadows and any of the materials don't cast a shadow,
|
||||||
* then don't draw the object */
|
* 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 */
|
/* 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)) {
|
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);
|
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) {
|
if(dt==OB_SOLID || glsl) {
|
||||||
GPU_begin_object_materials(v3d, rv3d, scene, ob, 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);
|
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 */
|
/* GPU_begin_object_materials checked if this is needed */
|
||||||
if(do_alpha_pass) {
|
if(do_alpha_after) {
|
||||||
if(ob->dtx & OB_DRAWXRAY) {
|
if(ob->dtx & OB_DRAWXRAY) {
|
||||||
add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
|
add_view3d_after(&v3d->afterdraw_xraytransp, base, flag);
|
||||||
}
|
}
|
||||||
|
@@ -69,7 +69,7 @@ void GPU_state_print(void);
|
|||||||
* - after drawing, the material must be disabled again */
|
* - after drawing, the material must be disabled again */
|
||||||
|
|
||||||
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
|
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);
|
void GPU_end_object_materials(void);
|
||||||
|
|
||||||
int GPU_enable_material(int nr, void *attribs);
|
int GPU_enable_material(int nr, void *attribs);
|
||||||
|
@@ -942,7 +942,7 @@ static struct GPUMaterialState {
|
|||||||
|
|
||||||
GPUBlendMode *alphablend;
|
GPUBlendMode *alphablend;
|
||||||
GPUBlendMode alphablend_fixed[FIXEDMAT];
|
GPUBlendMode alphablend_fixed[FIXEDMAT];
|
||||||
int alphapass;
|
int use_alpha_pass, is_alpha_pass;
|
||||||
|
|
||||||
int lastmatnr, lastretval;
|
int lastmatnr, lastretval;
|
||||||
GPUBlendMode lastalphablend;
|
GPUBlendMode lastalphablend;
|
||||||
@@ -993,7 +993,7 @@ static Material *gpu_active_node_material(Material *ma)
|
|||||||
return 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;
|
Material *ma;
|
||||||
GPUMaterial *gpumat;
|
GPUMaterial *gpumat;
|
||||||
@@ -1015,9 +1015,15 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
|
|||||||
GMS.gviewmat= rv3d->viewmat;
|
GMS.gviewmat= rv3d->viewmat;
|
||||||
GMS.gviewinv= rv3d->viewinv;
|
GMS.gviewinv= rv3d->viewinv;
|
||||||
|
|
||||||
GMS.alphapass = (v3d && v3d->transp);
|
/* alpha pass setup. there's various cases to handle here:
|
||||||
if(do_alpha_pass)
|
* object transparency on: only solid materials draw in the first pass,
|
||||||
*do_alpha_pass = 0;
|
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) {
|
if(GMS.totmat > FIXEDMAT) {
|
||||||
GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf");
|
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 */
|
/* fixed function opengl materials */
|
||||||
gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
|
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(GMS.use_alpha_pass) {
|
||||||
if(do_alpha_pass && GMS.alphapass)
|
|
||||||
GMS.matbuf[a].diff[3]= ma->alpha;
|
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;
|
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 */
|
* drawn in a second alpha pass for improved blending */
|
||||||
if(do_alpha_pass) {
|
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;
|
GMS.alphablend[a]= alphablend;
|
||||||
if(ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT) && !GMS.alphapass)
|
|
||||||
*do_alpha_pass= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* let's start with a clean state */
|
/* let's start with a clean state */
|
||||||
@@ -1122,20 +1131,26 @@ int GPU_enable_material(int nr, void *attribs)
|
|||||||
|
|
||||||
/* unbind glsl material */
|
/* unbind glsl material */
|
||||||
if(GMS.gboundmat) {
|
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));
|
GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
|
||||||
GMS.gboundmat= NULL;
|
GMS.gboundmat= NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* draw materials with alpha in alpha pass */
|
/* draw materials with alpha in alpha pass */
|
||||||
GMS.lastmatnr = nr;
|
GMS.lastmatnr = nr;
|
||||||
|
GMS.lastretval = 1;
|
||||||
|
|
||||||
|
if(GMS.use_alpha_pass) {
|
||||||
GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
|
GMS.lastretval = ELEM(GMS.alphablend[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP);
|
||||||
if(GMS.alphapass)
|
if(GMS.is_alpha_pass)
|
||||||
GMS.lastretval = !GMS.lastretval;
|
GMS.lastretval = !GMS.lastretval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
GMS.lastretval = !GMS.is_alpha_pass;
|
||||||
|
|
||||||
if(GMS.lastretval) {
|
if(GMS.lastretval) {
|
||||||
/* for alpha pass, use alpha blend */
|
/* for alpha pass, use alpha blend */
|
||||||
alphablend = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID;
|
alphablend = GMS.alphablend[nr];
|
||||||
|
|
||||||
if(gattribs && GMS.gmatbuf[nr]) {
|
if(gattribs && GMS.gmatbuf[nr]) {
|
||||||
/* bind glsl material and get attributes */
|
/* 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)
|
if(mat->game.alpha_blend != GPU_BLEND_SOLID)
|
||||||
alphablend= mat->game.alpha_blend;
|
alphablend= mat->game.alpha_blend;
|
||||||
|
|
||||||
if(GMS.alphapass) glDepthMask(1);
|
if(GMS.is_alpha_pass) glDepthMask(1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* or do fixed function opengl material */
|
/* or do fixed function opengl material */
|
||||||
@@ -1188,7 +1203,7 @@ void GPU_disable_material(void)
|
|||||||
GMS.lastretval= 1;
|
GMS.lastretval= 1;
|
||||||
|
|
||||||
if(GMS.gboundmat) {
|
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));
|
GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
|
||||||
GMS.gboundmat= NULL;
|
GMS.gboundmat= NULL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user