Commit b872222b by Jaime Ita Passos

Implement blend modes

parent dfc85ec2
......@@ -655,6 +655,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->flags = LONG(players[i].mo->flags);
rsp->flags2 = LONG(players[i].mo->flags2);
rsp->renderflags = LONG(players[i].mo->renderflags);
rsp->blendmode = LONG(players[i].mo->blendmode);
rsp->radius = LONG(players[i].mo->radius);
rsp->height = LONG(players[i].mo->height);
......@@ -794,7 +795,6 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->flags = LONG(rsp->flags);
players[i].mo->flags2 = LONG(rsp->flags2);
players[i].mo->renderflags = LONG(rsp->renderflags);
players[i].mo->friction = LONG(rsp->friction);
players[i].mo->health = LONG(rsp->health);
players[i].mo->momx = LONG(rsp->momx);
......@@ -809,6 +809,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->frame = LONG(rsp->frame);
players[i].mo->sprite2 = rsp->sprite2;
players[i].mo->anim_duration = SHORT(rsp->anim_duration);
players[i].mo->renderflags = LONG(rsp->renderflags);
players[i].mo->blendmode = LONG(rsp->blendmode);
players[i].mo->spritexscale = LONG(rsp->spritexscale);
players[i].mo->spriteyscale = LONG(rsp->spriteyscale);
......
......@@ -300,6 +300,7 @@ typedef struct
UINT32 flags2;
UINT16 eflags;
UINT32 renderflags;
INT32 blendmode;
fixed_t radius;
fixed_t height;
......
......@@ -9580,6 +9580,15 @@ struct {
{"tr_trans90",tr_trans90},
{"NUMTRANSMAPS",NUMTRANSMAPS},
// Alpha styles (blend modes)
{"AST_COPY",AST_COPY},
{"AST_TRANSLUCENT",AST_TRANSLUCENT},
{"AST_ADD",AST_ADD},
{"AST_SUBTRACT",AST_SUBTRACT},
{"AST_REVERSESUBTRACT",AST_REVERSESUBTRACT},
{"AST_MODULATE",AST_MODULATE},
{"AST_OVERLAY",AST_OVERLAY},
// Render flags
{"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP},
{"RF_VERTICALFLIP",RF_VERTICALFLIP},
......
......@@ -293,7 +293,7 @@ static void F_DoWipe(fademask_t *fademask)
else
{
// pointer to transtable that this mask would use
transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
transtbl = R_GetTranslucencyTable((9 - *mask) + 1);
// DRAWING LOOP
while (draw_linestogo--)
......
......@@ -175,35 +175,32 @@ typedef struct
// You pass a combination of these flags to DrawPolygon()
enum EPolyFlags
{
// the first 5 are mutually exclusive
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pels are discarded (holes in texture)
// Mutually exclusive blend flags
PF_Masked = 0x00000001, // Poly is alpha scaled and 0 alpha pixels are discarded (holes in texture)
PF_Translucent = 0x00000002, // Poly is transparent, alpha = level of transparency
PF_Additive = 0x00000004, // Poly is added to the frame buffer
PF_Environment = 0x00000008, // Poly should be drawn environment mapped.
// Hurdler: used for text drawing
PF_Substractive = 0x00000010, // for splat
PF_NoAlphaTest = 0x00000020, // hiden param
PF_Fog = 0x00000040, // Fog blocks
PF_Blending = (PF_Environment|PF_Additive|PF_Translucent|PF_Masked|PF_Substractive|PF_Fog)&~PF_NoAlphaTest,
// other flag bits
PF_Occlude = 0x00000100, // Update the depth buffer
PF_NoDepthTest = 0x00000200, // Disable the depth test mode
PF_Invisible = 0x00000400, // Disable write to color buffer
PF_Decal = 0x00000800, // Enable polygon offset
PF_Environment = 0x00000004, // Poly should be drawn environment mapped. (Hurdler: used for text drawing)
PF_Additive = 0x00000008, // Additive color blending
PF_AdditiveSource = 0x00000010, // Source blending factor is additive. This is the opposite of regular additive blending.
PF_Subtractive = 0x00000020, // Subtractive color blending
PF_ReverseSubtract = 0x00000040, // Reverse subtract, used in wall splats (decals)
PF_Multiplicative = 0x00000080, // Multiplicative color blending
PF_Fog = 0x20000000, // Fog blocks
PF_NoAlphaTest = 0x40000000, // Disables alpha testing
PF_Blending = (PF_Masked|PF_Translucent|PF_Environment|PF_Additive|PF_AdditiveSource|PF_Subtractive|PF_ReverseSubtract|PF_Multiplicative|PF_Fog) & ~PF_NoAlphaTest,
// other flag bits
PF_Occlude = 0x00000100, // Updates the depth buffer
PF_NoDepthTest = 0x00000200, // Disables the depth test mode
PF_Invisible = 0x00000400, // Disables write to color buffer
PF_Decal = 0x00000800, // Enables polygon offset
PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB)
// When set, pass the color constant into the FSurfaceInfo -> PolyColor
PF_NoTexture = 0x00002000, // Use the small white texture
PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona
PF_Ripple = 0x00008000, // Water shader effect
PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y
PF_ForceWrapX = 0x00020000, // Force repeat texture on X
PF_ForceWrapY = 0x00040000, // Force repeat texture on Y
PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl)
PF_NoZClip = 0x20000000, // in conjonction with PF_Clip
PF_Debug = 0x80000000 // print debug message in driver :)
PF_NoTexture = 0x00002000, // Disables texturing
PF_Corona = 0x00004000, // Tells the renderer we are drawing a corona
PF_Ripple = 0x00008000, // Water effect shader
PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
PF_ForceWrapY = 0x00040000 // Forces repeat texture on Y
};
......
......@@ -571,7 +571,7 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
// But then, the question is: why not 0 instead of PF_Masked ?
// or maybe PF_Environment ??? (like what I said above)
// BP: PF_Environment don't change anything ! and 0 is undifined
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip);
HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest);
}
// ==========================================================================
......
......@@ -35,8 +35,7 @@
#define DL_HIGH_QUALITY
//#define STATICLIGHT //Hurdler: TODO!
//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw
#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip)
#define LIGHTMAPFLAGS (PF_Modulated|PF_AdditiveSource)
#ifdef ALAM_LIGHTING
static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode
......@@ -1056,7 +1055,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr)
HWR_GetPic(coronalumpnum); /// \todo use different coronas
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest);
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_Corona | PF_NoDepthTest);
}
}
#endif
......@@ -1144,7 +1143,7 @@ void HWR_DrawCoronas(void)
light[3].y = cy+size*1.33f;
light[3].s = 0.0f; light[3].t = 1.0f;
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona);
HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_AdditiveSource | PF_NoDepthTest | PF_Corona);
}
}
#endif
......
......@@ -695,28 +695,71 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight)
v3d->z = pv->y;
}
HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts,
PF_Clip|PF_Invisible|PF_NoTexture|PF_Occlude);
HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, PF_Invisible|PF_NoTexture|PF_Occlude);
}
#endif //polysky
#endif //doplanes
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
FBITFIELD HWR_GetBlendModeFlag(INT32 ast)
{
switch (ast)
{
case AST_ADD:
return PF_Additive;
case AST_SUBTRACT:
return PF_Subtractive;
case AST_REVERSESUBTRACT:
return PF_ReverseSubtract;
case AST_MODULATE:
return PF_Multiplicative;
default:
return PF_Translucent;
}
return 0;
}
UINT8 HWR_GetTranstableAlpha(INT32 transtablenum)
{
switch (transtablenum)
{
case 0 : pSurf->PolyColor.s.alpha = 0x00;return PF_Masked;
case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent;
case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent;
case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent;
case tr_trans40 : pSurf->PolyColor.s.alpha = 0x99;return PF_Translucent;
case tr_trans50 : pSurf->PolyColor.s.alpha = 0x80;return PF_Translucent;
case tr_trans60 : pSurf->PolyColor.s.alpha = 0x66;return PF_Translucent;
case tr_trans70 : pSurf->PolyColor.s.alpha = 0x4c;return PF_Translucent;
case tr_trans80 : pSurf->PolyColor.s.alpha = 0x33;return PF_Translucent;
case tr_trans90 : pSurf->PolyColor.s.alpha = 0x19;return PF_Translucent;
case 0 : return 0xff;
case tr_trans10 : return 0xe6;
case tr_trans20 : return 0xcc;
case tr_trans30 : return 0xb3;
case tr_trans40 : return 0x99;
case tr_trans50 : return 0x80;
case tr_trans60 : return 0x66;
case tr_trans70 : return 0x4c;
case tr_trans80 : return 0x33;
case tr_trans90 : return 0x19;
}
return 0xff;
}
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf)
{
if (!transtablenum)
{
pSurf->PolyColor.s.alpha = 0xff;
return PF_Masked;
}
pSurf->PolyColor.s.alpha = HWR_GetTranstableAlpha(transtablenum);
return HWR_GetBlendModeFlag(style);
}
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
{
if (!transtablenum)
{
pSurf->PolyColor.s.alpha = 0x00;
return PF_Masked;
}
pSurf->PolyColor.s.alpha = HWR_GetTranstableAlpha(transtablenum);
return PF_Translucent;
}
......@@ -2770,10 +2813,10 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
if (blendmode & PF_Translucent)
{
Surf.PolyColor.s.alpha = (UINT8)alpha;
blendmode |= PF_Modulated|PF_Occlude|PF_Clip;
blendmode |= PF_Modulated|PF_Occlude;
}
else
blendmode |= PF_Masked|PF_Modulated|PF_Clip;
blendmode |= PF_Masked|PF_Modulated;
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, 1, false); // floor shader
}
......@@ -3443,7 +3486,7 @@ static void HWR_LinkDrawHackFinish(void)
{
// draw sprite shape, only to z-buffer
HWR_GetPatch(linkdrawlist[i].spr->gpatch);
HWR_ProcessPolygon(&surf, linkdrawlist[i].verts, 4, PF_Translucent|PF_Occlude|PF_Invisible|PF_Clip, 0, false);
HWR_ProcessPolygon(&surf, linkdrawlist[i].verts, 4, PF_Translucent|PF_Occlude|PF_Invisible, 0, false);
}
// reset list
linkdrawcount = 0;
......@@ -3587,7 +3630,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
HWR_Lighting(&sSurf, 0, colormap);
sSurf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated, 3, false); // sprite shader
}
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
......@@ -3741,10 +3784,10 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
else if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.PolyColor.s.alpha = 0x40;
blend = PF_Translucent;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
else if (spr->mobj->frame & FF_TRANSMASK)
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
{
// BP: i agree that is little better in environement but it don't
......@@ -3752,7 +3795,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
Surf.PolyColor.s.alpha = 0xFF;
blend = PF_Translucent|occlusion;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion;
if (!occlusion) use_linkdraw_hack = true;
}
......@@ -3860,7 +3903,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
Surf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
......@@ -3889,7 +3932,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
Surf.PolyColor.s.alpha = alpha;
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
......@@ -4156,10 +4199,10 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
else if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.PolyColor.s.alpha = 0x40;
blend = PF_Translucent;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
else if (spr->mobj->frame & FF_TRANSMASK)
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
{
// BP: i agree that is little better in environement but it don't
......@@ -4167,7 +4210,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
Surf.PolyColor.s.alpha = 0xFF;
blend = PF_Translucent|occlusion;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion;
if (!occlusion) use_linkdraw_hack = true;
}
......@@ -4183,7 +4226,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
if (use_linkdraw_hack)
HWR_LinkDrawHackAdd(wallVerts, spr);
......@@ -4271,10 +4314,10 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.PolyColor.s.alpha = 0x40;
blend = PF_Translucent;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
else if (spr->mobj->frame & FF_TRANSMASK)
blend = HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
blend = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
{
// BP: i agree that is little better in environement but it don't
......@@ -4282,10 +4325,10 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr)
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
Surf.PolyColor.s.alpha = 0xFF;
blend = PF_Translucent|PF_Occlude;
blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|PF_Occlude;
}
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, 3, false); // sprite shader
HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, 3, false); // sprite shader
}
#endif
......@@ -4749,7 +4792,7 @@ static void HWR_DrawSprites(void)
// (Other states probably don't matter. Here I left them same as in LinkDrawHackFinish)
// Without this workaround the rest of the draw calls in this frame (including UI, screen texture)
// can get drawn using an incorrect glBlendFunc, resulting in a occasional black screen.
HWD.pfnSetBlend(PF_Translucent|PF_Occlude|PF_Clip|PF_Masked);
HWD.pfnSetBlend(PF_Translucent|PF_Occlude|PF_Masked);
}
// --------------------------------------------------------------------------
......@@ -6422,7 +6465,7 @@ void HWR_DoPostProcessor(player_t *player)
Surf.PolyColor.s.alpha = 0xc0; // match software mode
HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip);
HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_AdditiveSource|PF_NoTexture|PF_NoDepthTest);
}
// Capture the screen for intermission and screen waving
......
......@@ -54,7 +54,6 @@ boolean HWR_Screenshot(const char *pathname);
void HWR_AddCommands(void);
void HWR_AddSessionCommands(void);
void transform(float *cx, float *cy, float *cz);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
INT32 HWR_GetTextureUsed(void);
void HWR_DoPostProcessor(player_t *player);
void HWR_StartScreenWipe(void);
......@@ -65,10 +64,15 @@ void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum);
void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so MD2's can use them
// This stuff is put here so models can use them
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work
UINT8 HWR_GetTranstableAlpha(INT32 transtablenum);
FBITFIELD HWR_GetBlendModeFlag(INT32 ast);
FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf);
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf);
void HWR_ReadShaders(UINT16 wadnum, boolean PK3);
boolean HWR_LoadShaders(void);
......
......@@ -1317,11 +1317,17 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
//durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.PolyColor.s.alpha = 0x40;
Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode);
}
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
{
Surf.PolyColor.s.alpha = 0xFF;
Surf.PolyFlags = 0;
}
// dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted
......
......@@ -425,6 +425,10 @@ static PFNglBufferData pglBufferData;
typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers);
static PFNglDeleteBuffers pglDeleteBuffers;
/* 2.0 functions */
typedef void (APIENTRY * PFNglBlendEquation) (GLenum mode);
static PFNglBlendEquation pglBlendEquation;
/* 1.2 Parms */
/* GL_CLAMP_TO_EDGE_EXT */
......@@ -892,6 +896,9 @@ void SetupGLFunc4(void)
pglBufferData = GetGLFunc("glBufferData");
pglDeleteBuffers = GetGLFunc("glDeleteBuffers");
/* 2.0 funcs */
pglBlendEquation = GetGLFunc("glBlendEquation");
#ifdef GL_SHADERS
pglCreateShader = GetGLFunc("glCreateShader");
pglShaderSource = GetGLFunc("glShaderSource");
......@@ -1286,6 +1293,7 @@ void SetStates(void)
pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
pglEnable(GL_ALPHA_TEST);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
//pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque)
......@@ -1554,64 +1562,110 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1,
pglEnable(GL_TEXTURE_2D);
}
// -----------------+
// SetBlend : Set render mode
// -----------------+
// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
// is it faster when pixels are discarded ?
static void Clamp2D(GLenum pname)
{
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp
pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE);
}
static void SetBlendEquation(GLenum mode)
{
if (pglBlendEquation)
pglBlendEquation(mode);
}
static void SetBlendMode(FBITFIELD flags)
{
// Set blending function
switch (flags)
{
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
break;
case PF_Additive & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
break;
case PF_AdditiveSource & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
break;
case PF_Multiplicative & PF_Blending:
pglBlendFunc(GL_DST_COLOR, GL_ZERO);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
break;
default: // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
break;
}
// Set blending equation
switch (flags)
{
case PF_Subtractive & PF_Blending:
SetBlendEquation(GL_FUNC_SUBTRACT);
break;
case PF_ReverseSubtract & PF_Blending:
// good for shadow
// not really but what else ?
SetBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
break;
default:
SetBlendEquation(GL_FUNC_ADD);
break;
}
// Alpha test
switch (flags)
{
case PF_Masked & PF_Blending:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Translucent & PF_Blending:
case PF_Additive & PF_Blending:
case PF_AdditiveSource & PF_Blending:
case PF_Subtractive & PF_Blending:
case PF_ReverseSubtract & PF_Blending:
case PF_Environment & PF_Blending:
case PF_Multiplicative & PF_Blending:
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default:
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
// -----------------+
// SetBlend : Set render mode
// -----------------+
// PF_Masked - we could use an ALPHA_TEST of GL_EQUAL, and alpha ref of 0,
// is it faster when pixels are discarded ?
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
{
FBITFIELD Xor;
Xor = CurrentPolyFlags^PolyFlags;
if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible|PF_NoAlphaTest))
if (Xor & (PF_Blending|PF_RemoveYWrap|PF_ForceWrapX|PF_ForceWrapY|PF_Occlude|PF_NoTexture|PF_Modulated|PF_NoDepthTest|PF_Decal|PF_Invisible))
{
if (Xor&(PF_Blending)) // if blending mode must be changed
{
switch (PolyFlags & PF_Blending) {
case PF_Translucent & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Masked & PF_Blending:
// Hurdler: does that mean lighting is only made by alpha src?
// it sounds ok, but not for polygonsmooth
pglBlendFunc(GL_SRC_ALPHA, GL_ZERO); // 0 alpha = holes in texture
pglAlphaFunc(GL_GREATER, 0.5f);
break;
case PF_Additive & PF_Blending:
pglBlendFunc(GL_SRC_ALPHA, GL_ONE); // src * alpha + dest
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Environment & PF_Blending:
pglBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Substractive & PF_Blending:
// good for shadow
// not really but what else ?
pglBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
pglAlphaFunc(GL_NOTEQUAL, 0.0f);
break;
case PF_Fog & PF_Fog:
// Sryder: Fog
// multiplies input colour by input alpha, and destination colour by input colour, then adds them
pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments
break;
default : // must be 0, otherwise it's an error
// No blending
pglBlendFunc(GL_ONE, GL_ZERO); // the same as no blending
pglAlphaFunc(GL_GREATER, 0.5f);
break;
}
}
if (Xor & PF_Blending) // if blending mode must be changed
SetBlendMode(PolyFlags & PF_Blending);
if (Xor & PF_NoAlphaTest)
{
if (PolyFlags & PF_NoAlphaTest)
......@@ -1628,7 +1682,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDisable(GL_POLYGON_OFFSET_FILL);
}
if (Xor&PF_NoDepthTest)
if (Xor & PF_NoDepthTest)
{
if (PolyFlags & PF_NoDepthTest)
pglDepthFunc(GL_ALWAYS); //pglDisable(GL_DEPTH_TEST);
......@@ -1636,25 +1690,25 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags)
pglDepthFunc(GL_LEQUAL); //pglEnable(GL_DEPTH_TEST);
}
if (Xor&PF_RemoveYWrap)
if (Xor & PF_RemoveYWrap)
{
if (PolyFlags & PF_RemoveYWrap)
Clamp2D(GL_TEXTURE_WRAP_T);
}
if (Xor&PF_ForceWrapX)
if (Xor & PF_ForceWrapX)
{
if (PolyFlags & PF_ForceWrapX)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
}
if (Xor&PF_ForceWrapY)
if (Xor & PF_ForceWrapY)
{
if (PolyFlags & PF_ForceWrapY)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
if (Xor&PF_Modulated)
if (Xor & PF_Modulated)
{
#if defined (__unix__) || defined (UNIXCOMMON)
if (oglflags & GLF_NOTEXENV)
......@@ -2613,7 +2667,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
else
pglColor4ubv((GLubyte*)&Surface->PolyColor.s);
SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated);
SetBlend((poly.alpha < 1 ? Surface->PolyFlags : (PF_Masked|PF_Occlude))|PF_Modulated);
tint.red = byte2float[Surface->TintColor.s.red];
tint.green = byte2float[Surface->TintColor.s.green];
......@@ -3194,7 +3248,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip);
SetBlend(PF_Modulated|PF_NoDepthTest);
pglEnable(GL_TEXTURE_2D);
// Draw the original screen
......@@ -3204,7 +3258,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void)
pglVertexPointer(3, GL_FLOAT, 0, screenVerts);
pglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip);
SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest);
// Draw the end screen that fades in
pglActiveTexture(GL_TEXTURE0);
......
......@@ -64,6 +64,7 @@ enum mobj_e {
mobj_renderflags,
mobj_skin,
mobj_color,
mobj_blendmode,
mobj_bnext,
mobj_bprev,
mobj_hnext,
......@@ -139,6 +140,7 @@ static const char *const mobj_opt[] = {
"renderflags",
"skin",
"color",
"blendmode",
"bnext",
"bprev",
"hnext",
......@@ -315,6 +317,9 @@ static int mobj_get(lua_State *L)
case mobj_color:
lua_pushinteger(L, mo->color);
break;
case mobj_blendmode:
lua_pushinteger(L, mo->blendmode);
break;
case mobj_bnext:
LUA_PushUserdata(L, mo->bnext, META_MOBJ);
break;
......@@ -650,6 +655,9 @@ static int mobj_set(lua_State *L)
mo->color = newcolor;
break;
}
case mobj_blendmode: