diff --git a/polymer/eduke32/build/include/palette.h b/polymer/eduke32/build/include/palette.h index 73da013c5..19f283906 100644 --- a/polymer/eduke32/build/include/palette.h +++ b/polymer/eduke32/build/include/palette.h @@ -71,6 +71,37 @@ static inline void bricolor(palette_t *wpptr, int32_t dacol) wpptr->b = britable[curbrightness][curpalette[dacol].b]; } } + +enum +{ + BLENDFACTOR_ZERO = 0, + BLENDFACTOR_ONE, + BLENDFACTOR_SRC_COLOR, + BLENDFACTOR_ONE_MINUS_SRC_COLOR, + BLENDFACTOR_SRC_ALPHA, + BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + BLENDFACTOR_DST_ALPHA, + BLENDFACTOR_ONE_MINUS_DST_ALPHA, + BLENDFACTOR_DST_COLOR, + BLENDFACTOR_ONE_MINUS_DST_COLOR, + NUMBLENDFACTORS, +}; + +typedef struct glblenddef_ +{ + float alpha; + uint8_t src, dst, flags; +} glblenddef_t; + +typedef struct glblend_ +{ + glblenddef_t def[2]; +} glblend_t; + +extern glblend_t const nullglblend, defaultglblend; +extern glblend_t glblend[MAXBLENDTABS]; + +extern void handle_blend(uint8_t enable, uint8_t blend, uint8_t def); #endif #ifdef __cplusplus diff --git a/polymer/eduke32/build/include/polymost.h b/polymer/eduke32/build/include/polymost.h index cd62fd11c..88cac7960 100644 --- a/polymer/eduke32/build/include/polymost.h +++ b/polymer/eduke32/build/include/polymost.h @@ -33,7 +33,7 @@ void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt, coltype *pic, ve void polymost_drawsprite(int32_t snum); void polymost_drawmaskwall(int32_t damaskwallcnt); void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, - int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid); + int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid); void polymost_fillpolygon(int32_t npoints); void polymost_initosdfuncs(void); void polymost_drawrooms(void); diff --git a/polymer/eduke32/build/src/defs.c b/polymer/eduke32/build/src/defs.c index e056df7d2..7c26c3380 100644 --- a/polymer/eduke32/build/src/defs.c +++ b/polymer/eduke32/build/src/defs.c @@ -112,6 +112,12 @@ enum scripttoken_t T_NUMALPHATABS, T_UNDEF, T_UNDEFBASEPALETTERANGE, T_UNDEFPALOOKUPRANGE, T_UNDEFBLENDTABLERANGE, + T_GLBLEND, T_FORWARD, T_REVERSE, T_BOTH, T_SRC, T_DST, T_ALPHA, + T_ZERO, T_ONE, + T_SRC_COLOR, T_ONE_MINUS_SRC_COLOR, + T_SRC_ALPHA, T_ONE_MINUS_SRC_ALPHA, + T_DST_ALPHA, T_ONE_MINUS_DST_ALPHA, + T_DST_COLOR, T_ONE_MINUS_DST_COLOR, }; static int32_t lastmodelid = -1, lastvoxid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0; @@ -3214,6 +3220,7 @@ static int32_t defsparser(scriptfile *script) static const tokenlist subtokens[] = { { "raw", T_RAW }, + { "glblend", T_GLBLEND }, { "copy", T_COPY }, { "undef", T_UNDEF }, }; @@ -3343,6 +3350,10 @@ static int32_t defsparser(scriptfile *script) setblendtab(id, sourcetable); didLoadTransluc = 1; + +#ifdef USE_OPENGL + glblend[id] = glblend[source]; +#endif break; } case T_UNDEF: @@ -3352,8 +3363,129 @@ static int32_t defsparser(scriptfile *script) didLoadTransluc = 0; if (id == 0) paletteloaded &= ~PALETTE_TRANSLUC; + +#ifdef USE_OPENGL + glblend[id] = defaultglblend; +#endif break; } + case T_GLBLEND: + { + char *glblendblockend; + + static const tokenlist glblendtokens[] = + { + { "forward", T_FORWARD }, + { "reverse", T_REVERSE }, + { "both", T_BOTH }, + }; + + if (scriptfile_getbraces(script,&glblendblockend)) + break; + +#ifdef USE_OPENGL + glblend_t * const glb = glblend + id; + *glb = nullglblend; +#endif + + while (script->textptr < glblendblockend) + { + int32_t glblendtoken = getatoken(script,glblendtokens,ARRAY_SIZE(glblendtokens)); + switch (glblendtoken) + { + case T_FORWARD: + case T_REVERSE: + case T_BOTH: + { + char *glblenddefblockend; + + static const tokenlist glblenddeftokens[] = + { + { "src", T_SRC }, + { "sfactor", T_SRC }, + { "top", T_SRC }, + + { "dst", T_DST }, + { "dfactor", T_DST }, + { "bottom", T_DST }, + + { "alpha", T_ALPHA }, + }; + + if (scriptfile_getbraces(script,&glblenddefblockend)) + break; + +#ifdef USE_OPENGL + glblenddef_t * const glbdef = glb->def + (glblendtoken == T_REVERSE); +#endif + + while (script->textptr < glblenddefblockend) + { + int32_t glblenddeftoken = getatoken(script,glblenddeftokens,ARRAY_SIZE(glblenddeftokens)); + switch (glblenddeftoken) + { + case T_SRC: + case T_DST: + { + static const tokenlist glBlendFuncTokens[] = + { + { "ZERO", T_ZERO }, + { "ONE", T_ONE }, + { "SRC_COLOR", T_SRC_COLOR }, + { "ONE_MINUS_SRC_COLOR", T_ONE_MINUS_SRC_COLOR }, + { "SRC_ALPHA", T_SRC_ALPHA }, + { "ONE_MINUS_SRC_ALPHA", T_ONE_MINUS_SRC_ALPHA }, + { "DST_ALPHA", T_DST_ALPHA }, + { "ONE_MINUS_DST_ALPHA", T_ONE_MINUS_DST_ALPHA }, + { "DST_COLOR", T_DST_COLOR }, + { "ONE_MINUS_DST_COLOR", T_ONE_MINUS_DST_COLOR }, + }; + + int32_t factortoken = getatoken(script,glBlendFuncTokens,ARRAY_SIZE(glBlendFuncTokens)); + +#ifdef USE_OPENGL + uint8_t * const factor = glblenddeftoken == T_SRC ? &glbdef->src : &glbdef->dst; + switch (factortoken) + { + case T_ZERO: *factor = BLENDFACTOR_ZERO; break; + case T_ONE: *factor = BLENDFACTOR_ONE; break; + case T_SRC_COLOR: *factor = BLENDFACTOR_SRC_COLOR; break; + case T_ONE_MINUS_SRC_COLOR: *factor = BLENDFACTOR_ONE_MINUS_SRC_COLOR; break; + case T_SRC_ALPHA: *factor = BLENDFACTOR_SRC_ALPHA; break; + case T_ONE_MINUS_SRC_ALPHA: *factor = BLENDFACTOR_ONE_MINUS_SRC_ALPHA; break; + case T_DST_ALPHA: *factor = BLENDFACTOR_DST_ALPHA; break; + case T_ONE_MINUS_DST_ALPHA: *factor = BLENDFACTOR_ONE_MINUS_DST_ALPHA; break; + case T_DST_COLOR: *factor = BLENDFACTOR_DST_COLOR; break; + case T_ONE_MINUS_DST_COLOR: *factor = BLENDFACTOR_ONE_MINUS_DST_COLOR; break; + } +#else + UNREFERENCED_PARAMETER(factortoken); +#endif + + break; + } + case T_ALPHA: + { + double tempalpha; + scriptfile_getdouble(script,&tempalpha); +#ifdef USE_OPENGL + glbdef->alpha = (float)tempalpha; +#endif + break; + } + } + } + +#ifdef USE_OPENGL + if (glblendtoken == T_BOTH) + glb->def[1] = *glbdef; +#endif + + break; + } + } + } + } default: break; } @@ -3373,6 +3505,17 @@ static int32_t defsparser(scriptfile *script) switch (value) { case 0: /*case 1:*/ case 2: case 4: case 8: case 16: case 32: case 64: case 128: +#ifdef USE_OPENGL + for (int32_t a = 1, value2 = value*2; a <= value; ++a) + { + float finv2value = 0.5f/(float)value; + + glblend_t * const glb = glblend + a; + *glb = defaultglblend; + glb->def[0].alpha = (float)(value2-a) * finv2value; + glb->def[1].alpha = (float)a * finv2value; + } +#endif numalphatabs = value; break; default: diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index db7222d8a..a9fb0a410 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -6503,7 +6503,7 @@ static void dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t #ifdef USE_OPENGL if (getrendermode() >= REND_POLYMOST && in3dmode()) { - polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,daalpha,cx1,cy1,cx2,cy2,uniqid); + polymost_dorotatesprite(sx,sy,z,a,picnum,dashade,dapalnum,dastat,daalpha,dablend,cx1,cy1,cx2,cy2,uniqid); return; } #else diff --git a/polymer/eduke32/build/src/mdsprite.c b/polymer/eduke32/build/src/mdsprite.c index aa713d5b5..679269b23 100644 --- a/polymer/eduke32/build/src/mdsprite.c +++ b/polymer/eduke32/build/src/mdsprite.c @@ -2202,9 +2202,11 @@ static int32_t polymost_md3draw(md3model_t *m, const uspritetype *tspr) if (have_basepal_tint()) hictinting_apply(pc, MAXPALOOKUPS-1); - pc[3] = (tspr->cstat&2) ? !(tspr->cstat&512) ? (2.f/3.f) : (1.f/3.f) : 1.0f; + pc[3] = (tspr->cstat&2) ? glblend[tspr->blend].def[!!(tspr->cstat&512)].alpha : 1.0f; pc[3] *= 1.0f - sext->alpha; + handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); + if (m->usesalpha) //Sprites with alpha in texture { // bglEnable(GL_BLEND);// bglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); diff --git a/polymer/eduke32/build/src/palette.c b/polymer/eduke32/build/src/palette.c index 68d9fb6a8..287b6b4b4 100644 --- a/polymer/eduke32/build/src/palette.c +++ b/polymer/eduke32/build/src/palette.c @@ -107,6 +107,11 @@ void loadpalette(void) initfastcolorlookup_scale(30, 59, 11); initfastcolorlookup_gridvectors(); +#ifdef USE_OPENGL + for (size_t x = 0; x < MAXBLENDTABS; ++x) + glblend[x] = defaultglblend; +#endif + int32_t fil; if ((fil = kopen4load("palette.dat", 0)) == -1) return; @@ -465,6 +470,51 @@ const char *(getblendtab) (int32_t blend) } #endif +#ifdef USE_OPENGL +glblend_t const nullglblend = +{ + { + { 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 }, + { 1.f, BLENDFACTOR_ONE, BLENDFACTOR_ZERO, 0 }, + }, +}; +glblend_t const defaultglblend = +{ + { + { 2.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 }, + { 1.f/3.f, BLENDFACTOR_SRC_ALPHA, BLENDFACTOR_ONE_MINUS_SRC_ALPHA, 0 }, + }, +}; + +glblend_t glblend[MAXBLENDTABS]; + +void handle_blend(uint8_t enable, uint8_t blend, uint8_t def) +{ + static GLenum const blendFuncTokens[NUMBLENDFACTORS] = + { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + }; + + if (!enable) + { + bglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + return; + } + + glblenddef_t const * const glbdef = glblend[blend].def + def; + bglBlendFunc(blendFuncTokens[glbdef->src], blendFuncTokens[glbdef->dst]); +} +#endif + int32_t setpalookup(int32_t palnum, const uint8_t *shtab) { if (numshades != 32) diff --git a/polymer/eduke32/build/src/polymost.c b/polymer/eduke32/build/src/polymost.c index bdaf8b5e2..e09ee4ecc 100644 --- a/polymer/eduke32/build/src/polymost.c +++ b/polymer/eduke32/build/src/polymost.c @@ -125,7 +125,17 @@ int32_t r_downsizevar = -1; static float fogresult, fogresult2; coltypef fogcol, fogtable[MAXPALOOKUPS]; -static const float float_trans[4] = { 1.0f, 1.0f, 2.f/3.f, 1.f/3.f }; +static float float_trans(uint32_t maskprops, uint8_t blend) +{ + switch (maskprops) + { + case DAMETH_TRANS1: + case DAMETH_TRANS2: + return glblend[blend].def[maskprops-2].alpha; + default: + return 1.0f; + } +} char ptempbuf[MAXWALLSB<<1]; @@ -1623,6 +1633,7 @@ void polymost_setupglowtexture(const int32_t texunits, const int32_t tex) // drawpoly's hack globals static int32_t pow2xsplit = 0, skyclamphack = 0; static float drawpoly_alpha = 0.f; +static uint8_t drawpoly_blend = 0; static inline pthtyp *our_texcache_fetch(int32_t dameth) { @@ -1837,7 +1848,9 @@ static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32 pc[0] = pc[1] = pc[2] = getshadefactor(globalshade); // spriteext full alpha control - pc[3] = float_trans[method & DAMETH_MASKPROPS] * (1.f - drawpoly_alpha); + pc[3] = float_trans(method & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha); + + handle_blend((method & DAMETH_MASKPROPS) > DAMETH_MASK, drawpoly_blend, (method & DAMETH_MASKPROPS) == DAMETH_TRANS2); if (pth) { @@ -2042,6 +2055,8 @@ do bglLoadIdentity(); bglMatrixMode(GL_MODELVIEW); + bglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (getrendermode() != REND_POLYMOST) return; @@ -2157,6 +2172,7 @@ static void polymost_domost(float x0, float y0, float x1, float y1) float const slop = (dm1.y - dm0.y) / (dm1.x - dm0.x); drawpoly_alpha = 0.f; + drawpoly_blend = 0; vec2f_t n0, n1; float spx[4]; @@ -2737,6 +2753,7 @@ static void polymost_internal_nonparallaxed(vec2f_t n0, vec2f_t n1, float ryp0, pow2xsplit = 0; drawpoly_alpha = 0.f; + drawpoly_blend = 0; calc_and_apply_fog(globalpicnum, fogpal_shade(sec, global_cf_shade), sec->visibility, POLYMOST_CHOOSE_FOG_PAL(global_cf_fogpal, global_cf_pal)); @@ -2831,6 +2848,7 @@ static inline int polymost_getclosestpointonwall(vec2_t const * const pos, int32 static void polymost_drawalls(int32_t const bunch) { drawpoly_alpha = 0.f; + drawpoly_blend = 0; int32_t const sectnum = thesector[bunchfirst[bunch]]; usectortype const * const sec = (usectortype *)§or[sectnum]; @@ -4245,6 +4263,7 @@ void polymost_drawmaskwall(int32_t damaskwallcnt) pow2xsplit = 0; skyclamphack = 0; drawpoly_alpha = 0.f; + drawpoly_blend = 0; polymost_drawpoly(dpxy, n, method); } @@ -4365,7 +4384,10 @@ void polymost_drawsprite(int32_t snum) if (tspr->cstat & 2) method = DAMETH_CLAMPED | ((tspr->cstat & 512) ? DAMETH_TRANS2 : DAMETH_TRANS1); + handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); + drawpoly_alpha = spriteext[spritenum].alpha; + drawpoly_blend = tspr->blend; sec = (usectortype *)§or[tspr->sectnum]; @@ -4952,7 +4974,7 @@ EDUKE32_STATIC_ASSERT((int)RS_YFLIP == (int)HUDFLAG_FLIPPED); //cx1,... clip window (actual screen coords) void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, - int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, int32_t uniqid) + int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t uniqid) { float d, cosang, sinang, cosang2, sinang2; float m[4][4]; @@ -5124,6 +5146,7 @@ void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a, } spriteext[tspr.owner].alpha = daalpha * (1.0f / 255.0f); + tspr.blend = dablend; bglDisable(GL_FOG); @@ -5177,12 +5200,12 @@ void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a, } void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, - int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, + int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid) { if (usemodels && tile2model[picnum].hudmem[(dastat&4)>>2]) { - polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, uniqid); + polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, uniqid); return; } @@ -5251,6 +5274,8 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16 method |= DAMETH_MASK; } + handle_blend(!!(dastat & RS_TRANS1), dablend, !!(dastat & RS_TRANS2)); + #ifdef POLYMER if (getrendermode() == REND_POLYMER) { @@ -5264,6 +5289,7 @@ void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16 #endif drawpoly_alpha = daalpha * (1.0f / 255.0f); + drawpoly_blend = dablend; vec2_t const siz = tilesiz[globalpicnum]; vec2_t ofs ={ 0, 0 }; @@ -5595,10 +5621,12 @@ void polymost_fillpolygon(int32_t npoints) float const f = getshadefactor(globalshade); - if (((globalorientation>>7)&3) > 1) + uint8_t const maskprops = (globalorientation>>7)&DAMETH_MASKPROPS; + handle_blend(maskprops > DAMETH_MASK, 0, maskprops == DAMETH_TRANS2); + if (maskprops > DAMETH_MASK) { bglEnable(GL_BLEND); - bglColor4f(f, f, f, float_trans[(globalorientation>>7)&3]); + bglColor4f(f, f, f, float_trans(maskprops, 0)); } else { diff --git a/polymer/eduke32/build/src/voxmodel.c b/polymer/eduke32/build/src/voxmodel.c index b860a762a..628f2fa4f 100644 --- a/polymer/eduke32/build/src/voxmodel.c +++ b/polymer/eduke32/build/src/voxmodel.c @@ -978,9 +978,11 @@ int32_t polymost_voxdraw(voxmodel_t *m, const uspritetype *tspr) (float)(numshades-min(max((globalshade * shadescale)+m->shadeoff, 0), numshades)) / (float)numshades; hictinting_apply(pc, globalpal); - pc[3] = (tspr->cstat&2) ? !(tspr->cstat&512) ? (2.f/3.f) : (1.f/3.f) : 1.0f; + pc[3] = (tspr->cstat&2) ? glblend[tspr->blend].def[!!(tspr->cstat&512)].alpha : 1.0f; pc[3] *= 1.0f - spriteext[tspr->owner].alpha; + handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512)); + if ((tspr->cstat&2) || spriteext[tspr->owner].alpha > 0.f || pc[3] < 1.0f) bglEnable(GL_BLEND); //else bglDisable(GL_BLEND); //------------