diff --git a/src/deh_tables.c b/src/deh_tables.c index dd6d7d69f..9a27a2b30 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -22,6 +22,7 @@ #include "v_video.h" // video flags (for lua) #include "i_sound.h" // musictype_t (for lua) #include "g_state.h" // gamestate_t (for lua) +#include "r_data.h" // patchalphastyle_t #include "deh_tables.h" @@ -4841,6 +4842,13 @@ struct int_const_s const INT_CONST[] = { {"FF_VERTICALFLIP",FF_VERTICALFLIP}, {"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP}, {"FF_PAPERSPRITE",FF_PAPERSPRITE}, + {"FF_FLOORSPRITE",FF_FLOORSPRITE}, + {"FF_BLENDMASK",FF_BLENDMASK}, + {"FF_BLENDSHIFT",FF_BLENDSHIFT}, + {"FF_ADD",FF_ADD}, + {"FF_SUBTRACT",FF_SUBTRACT}, + {"FF_REVERSESUBTRACT",FF_REVERSESUBTRACT}, + {"FF_MODULATE",FF_MODULATE}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, // new preshifted translucency (used in source) @@ -4895,9 +4903,10 @@ struct int_const_s const INT_CONST[] = { {"RF_OBJECTSLOPESPLAT",RF_OBJECTSLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, - {"RF_BLENDMASK",RF_BLENDMASK}, + {"RF_BRIGHTMASK",RF_BRIGHTMASK}, {"RF_FULLBRIGHT",RF_FULLBRIGHT}, {"RF_FULLDARK",RF_FULLDARK}, + {"RF_SEMIBRIGHT",RF_SEMIBRIGHT}, {"RF_NOCOLORMAPS",RF_NOCOLORMAPS}, {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, {"RF_PAPERSPRITE",RF_PAPERSPRITE}, @@ -4905,6 +4914,27 @@ struct int_const_s const INT_CONST[] = { {"RF_SHADOWDRAW",RF_SHADOWDRAW}, {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_DROPSHADOW",RF_DROPSHADOW}, + {"RF_DONTDRAW",RF_DONTDRAW}, + {"RF_BLENDMASK",RF_BLENDMASK}, + {"RF_BLENDSHIFT",RF_BLENDSHIFT}, + {"RF_ADD",RF_ADD}, + {"RF_SUBTRACT",RF_SUBTRACT}, + {"RF_REVERSESUBTRACT",RF_REVERSESUBTRACT}, + {"RF_MODULATE",RF_MODULATE}, + {"RF_OVERLAY",RF_OVERLAY}, + {"RF_TRANSMASK",RF_TRANSMASK}, + {"RF_TRANSSHIFT",RF_TRANSSHIFT}, + {"RF_TRANS10",RF_TRANS10}, + {"RF_TRANS20",RF_TRANS20}, + {"RF_TRANS30",RF_TRANS30}, + {"RF_TRANS40",RF_TRANS40}, + {"RF_TRANS50",RF_TRANS50}, + {"RF_TRANS60",RF_TRANS60}, + {"RF_TRANS70",RF_TRANS70}, + {"RF_TRANS80",RF_TRANS80}, + {"RF_TRANS90",RF_TRANS90}, + {"RF_GHOSTLY",RF_GHOSTLY}, + {"RF_GHOSTLYMASK",RF_GHOSTLYMASK}, // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, @@ -5380,9 +5410,12 @@ struct int_const_s const INT_CONST[] = { {"V_HUDTRANSHALF",V_HUDTRANSHALF}, {"V_HUDTRANS",V_HUDTRANS}, {"V_HUDTRANSDOUBLE",V_HUDTRANSDOUBLE}, - {"V_AUTOFADEOUT",V_AUTOFADEOUT}, - {"V_RETURN8",V_RETURN8}, - {"V_OFFSET",V_OFFSET}, + {"V_BLENDSHIFT",V_BLENDSHIFT}, + {"V_BLENDMASK",V_BLENDMASK}, + {"V_ADD",V_ADD}, + {"V_SUBTRACT",V_SUBTRACT}, + {"V_REVERSESUBTRACT",V_REVERSESUBTRACT}, + {"V_MODULATE",V_MODULATE}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, {"V_FLIP",V_FLIP}, {"V_CENTERNAMETAG",V_CENTERNAMETAG}, @@ -5390,8 +5423,8 @@ struct int_const_s const INT_CONST[] = { {"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM}, {"V_SNAPTOLEFT",V_SNAPTOLEFT}, {"V_SNAPTORIGHT",V_SNAPTORIGHT}, - {"V_WRAPX",V_WRAPX}, - {"V_WRAPY",V_WRAPY}, + {"V_AUTOFADEOUT",V_AUTOFADEOUT}, + {"V_RETURN8",V_RETURN8}, {"V_NOSCALESTART",V_NOSCALESTART}, {"V_PERPLAYER",V_PERPLAYER}, diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ba4923d10..7a6ba22bc 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -119,11 +119,6 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) flags = PF_Translucent|PF_NoDepthTest; - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; - // clip it since it is used for bunny scroll in doom I HWD.pfnDrawPolygon(NULL, v, 4, flags); } @@ -134,7 +129,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); - UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); + UINT32 alphalevel, blendmode; GLPatch_t *hwrPatch; // 3--2 @@ -145,9 +140,6 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p UINT8 perplayershuffle = 0; - if (alphalevel >= 10 && alphalevel < 13) - return; - // make patch ready in hardware cache if (!colormap) HWR_GetPatch(gpatch); @@ -191,15 +183,9 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p offsetx = (float)(gpatch->leftoffset) * fscalew; // top offset - // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? + // TODO: make some kind of vertical version of V_FLIP offsety = (float)(gpatch->topoffset) * fscaleh; - if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs - { - offsetx *= dupx; - offsety *= dupy; - } - cx -= offsetx; cy -= offsety; } @@ -359,27 +345,32 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p v[0].t = v[1].t = 0.0f; v[2].t = v[3].t = hwrPatch->max_t; - flags = PF_Translucent|PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; + flags = PF_NoDepthTest; // clip it since it is used for bunny scroll in doom I - if (alphalevel) + if ((blendmode = ((option & V_BLENDMASK) >> V_BLENDSHIFT))) + blendmode++; // realign to constants + if ((alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT)) || blendmode) { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + + flags |= HWR_GetBlendModeFlag(blendmode); + + if (alphalevel == 10) + Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 11) + Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 12) + Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else + Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); + HWD.pfnDrawPolygon(&Surf, v, 4, flags|PF_Modulated); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags); + HWD.pfnDrawPolygon(NULL, v, 4, flags|PF_Translucent); } void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) @@ -388,7 +379,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, FBITFIELD flags; float cx = FIXED_TO_FLOAT(x); float cy = FIXED_TO_FLOAT(y); - UINT8 alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT); + UINT32 alphalevel, blendmode; GLPatch_t *hwrPatch; // 3--2 @@ -397,9 +388,6 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // 0--1 float dupx, dupy, fscale, fwidth, fheight; - if (alphalevel >= 10 && alphalevel < 13) - return; - // make patch ready in hardware cache HWR_GetPatch(gpatch); hwrPatch = ((GLPatch_t *)gpatch->hardware); @@ -507,27 +495,32 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, else v[2].t = v[3].t = ((sy+h)/(float)(gpatch->height))*hwrPatch->max_t; - flags = PF_Translucent|PF_NoDepthTest; - - if (option & V_WRAPX) - flags |= PF_ForceWrapX; - if (option & V_WRAPY) - flags |= PF_ForceWrapY; + flags = PF_NoDepthTest; // clip it since it is used for bunny scroll in doom I - if (alphalevel) + if ((blendmode = ((option & V_BLENDMASK) >> V_BLENDSHIFT))) + blendmode++; // realign to constants + if ((alphalevel = ((option & V_ALPHAMASK) >> V_ALPHASHIFT)) || blendmode) { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; - else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; - else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; - else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + + flags |= HWR_GetBlendModeFlag(blendmode); + + if (alphalevel == 10) + Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 11) + Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 12) + Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; + else + Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; + flags |= PF_Modulated; - HWD.pfnDrawPolygon(&Surf, v, 4, flags); + HWD.pfnDrawPolygon(&Surf, v, 4, flags|PF_Modulated); } else - HWD.pfnDrawPolygon(NULL, v, 4, flags); + HWD.pfnDrawPolygon(NULL, v, 4, flags|PF_Translucent); } void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index e94c637e4..f2d340893 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -716,15 +716,15 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 ast) { switch (ast) { - case AST_COPY: + //case AST_COPY: -- intentionally defaults to translucent case AST_OVERLAY: return PF_Masked; case AST_ADD: return PF_Additive; case AST_SUBTRACT: - return PF_Subtractive; - case AST_REVERSESUBTRACT: return PF_ReverseSubtract; + case AST_REVERSESUBTRACT: + return PF_Subtractive; case AST_MODULATE: return PF_Multiplicative; default: @@ -757,11 +757,13 @@ UINT8 HWR_GetTranstableAlpha(INT32 transtablenum) FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf) { - if (!transtablenum || style == AST_COPY || style == AST_OVERLAY) - { - pSurf->PolyColor.s.alpha = 0xff; - return PF_Masked; - } + pSurf->PolyColor.s.alpha = 0xff; + + if (style == AST_MODULATE) + return PF_Multiplicative; + + if (!transtablenum && !style) + pSurf->PolyColor.s.alpha = HWR_GetTranstableAlpha(transtablenum); return HWR_GetBlendModeFlag(style); @@ -853,7 +855,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) // // HWR_SplitWall // -static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags) +static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD blendmode) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -990,12 +992,12 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, wallVerts[0].y = bot; wallVerts[1].y = endbot; - if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture|polyflags, true, lightnum, colormap); - else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent|polyflags, false, lightnum, colormap); + if (blendmode & PF_Fog) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, true, lightnum, colormap); + else if (blendmode & (PF_Translucent|PF_Additive|PF_Subtractive|PF_Environment)) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked|polyflags, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, blendmode, lightnum, colormap); top = bot; endtop = endbot; @@ -1019,12 +1021,12 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, wallVerts[0].y = bot; wallVerts[1].y = endbot; - if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture|polyflags, true, lightnum, colormap); - else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent|polyflags, false, lightnum, colormap); + if (blendmode & PF_Fog) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, true, lightnum, colormap); + else if (blendmode & (PF_Translucent|PF_Additive|PF_Subtractive|PF_Environment)) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked|polyflags, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, blendmode, lightnum, colormap); } // HWR_DrawSkyWall @@ -1204,12 +1206,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); - if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FF_CUTLEVEL, NULL, 0); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, PF_Environment, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + FBITFIELD blendmode = PF_Masked; + + if (grTex->mipmap.flags & TF_TRANSPARENT) + blendmode = PF_Environment; + + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FF_CUTLEVEL, NULL, blendmode); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } // check BOTTOM TEXTURE @@ -1270,12 +1279,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); - if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FF_CUTLEVEL, NULL, 0); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, PF_Environment, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + FBITFIELD blendmode = PF_Masked; + + if (grTex->mipmap.flags & TF_TRANSPARENT) + blendmode = PF_Environment; + + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); if (gl_midtexture) @@ -1468,12 +1484,26 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom case 256: blendmode = PF_Translucent; break; - default: - if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) - blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), &Surf); - else - blendmode = PF_Masked; + case 913: + blendmode = PF_Multiplicative; + Surf.PolyColor.s.alpha = 0xff; break; + default: + { + UINT32 blend = 0; + transnum_t transtable = R_GetLinedefTransTable(gl_linedef); + if (transtable == NUMTRANSMAPS) + transtable = 0; + if (gl_linedef->special == 910) + blend = AST_ADD; + else if (gl_linedef->special == 911) + blend = AST_SUBTRACT; + else if (gl_linedef->special == 912) + blend = AST_REVERSESUBTRACT; + + blendmode = HWR_SurfaceBlend(blend, transtable, &Surf); + break; + } } if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0) @@ -1494,10 +1524,10 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_frontsector->numlights) { if (!(blendmode & PF_Masked)) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_TRANSLUCENT, NULL, PF_Decal); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_TRANSLUCENT, NULL, blendmode); else { - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, PF_Decal); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); } } else if (!(blendmode & PF_Masked)) @@ -1578,15 +1608,21 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); - // I don't think that solid walls can use translucent linedef types... - if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, 0); - else { + FBITFIELD blendmode = PF_Masked; if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, PF_Environment, false, lightnum, colormap); + blendmode = PF_Environment; + + // I don't think that solid walls can use translucent linedef types... + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } } @@ -1743,7 +1779,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->flags, rover, 0); + HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->flags, rover, blendmode); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1751,14 +1787,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + if ((rover->flags & FF_TRANSLUCENT) && (rover->alpha < 256 || rover->blend)) { - blendmode = PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + blendmode = HWR_GetBlendModeFlag(rover->blend); + Surf.PolyColor.s.alpha = (UINT8)(rover->alpha-1); } if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, rover->flags, rover, 0); + HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, rover->flags, rover, blendmode); else { if (blendmode != PF_Masked) @@ -1855,7 +1891,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); if (gl_backsector->numlights) - HWR_SplitWall(gl_backsector, wallVerts, 0, &Surf, rover->flags, rover, 0); + HWR_SplitWall(gl_backsector, wallVerts, 0, &Surf, rover->flags, rover, blendmode); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1863,14 +1899,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + if ((rover->flags & FF_TRANSLUCENT) && (rover->alpha < 256 || rover->blend)) { - blendmode = PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + blendmode = HWR_GetBlendModeFlag(rover->blend); + Surf.PolyColor.s.alpha = (UINT8)(rover->alpha-1); } if (gl_backsector->numlights) - HWR_SplitWall(gl_backsector, wallVerts, texnum, &Surf, rover->flags, rover, 0); + HWR_SplitWall(gl_backsector, wallVerts, texnum, &Surf, rover->flags, rover, blendmode); else { if (blendmode != PF_Masked) @@ -2946,6 +2982,13 @@ static void HWR_AddPolyObjectPlanes(void) } } +static FBITFIELD HWR_RippleBlend(sector_t *sector, ffloor_t *rover, boolean ceiling) +{ + (void)sector; + (void)ceiling; + return /*R_IsRipplePlane(sector, rover, ceiling)*/ (rover->flags & FF_RIPPLE) ? PF_Ripple : 0; +} + // -----------------+ // HWR_Subsector : Determine floor/ceiling planes. // : Add sprites of things in sector. @@ -3136,8 +3179,10 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient + else if (rover->flags & FF_TRANSLUCENT && (rover->alpha < 256 || rover->blend)) // SoM: Flags are more efficient { + FBITFIELD blendmode = HWR_GetBlendModeFlag(rover->blend) | HWR_RippleBlend(gl_frontsector, rover, false); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_AddTransparentFloor(&levelflats[*rover->bottompic], @@ -3145,14 +3190,14 @@ static void HWR_Subsector(size_t num) false, *rover->bottomheight, *gl_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, + rover->alpha-1, rover->master->frontsector, blendmode, false, *gl_frontsector->lightlist[light].extra_colormap); } else { HWR_GetLevelFlat(&levelflats[*rover->bottompic]); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } @@ -3181,8 +3226,10 @@ static void HWR_Subsector(size_t num) alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + else if (rover->flags & FF_TRANSLUCENT && (rover->alpha < 256 || rover->blend)) { + FBITFIELD blendmode = HWR_GetBlendModeFlag(rover->blend) | HWR_RippleBlend(gl_frontsector, rover, false); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_AddTransparentFloor(&levelflats[*rover->toppic], @@ -3190,14 +3237,14 @@ static void HWR_Subsector(size_t num) true, *rover->topheight, *gl_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, + rover->alpha-1, rover->master->frontsector, blendmode, false, *gl_frontsector->lightlist[light].extra_colormap); } else { HWR_GetLevelFlat(&levelflats[*rover->toppic]); light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } @@ -3839,31 +3886,33 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) else occlusion = PF_Occlude; - if (!cv_translucency.value) // translucency disabled + // Determine the blendmode and translucency value { - Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|occlusion; - if (!occlusion) use_linkdraw_hack = true; - } - else if (spr->mobj->flags2 & MF2_SHADOW) - { - Surf.PolyColor.s.alpha = 0x40; - blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); - } - else if (spr->mobj->frame & FF_TRANSMASK) - { - INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); - } - else - { - // BP: i agree that is little better in environement but it don't - // work properly under glide nor with fogcolor to ffffff :( - // Hurdler: PF_Environement would be cool, but we need to fix - // the issue with the fog before - Surf.PolyColor.s.alpha = 0xFF; - blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion; - if (!occlusion) use_linkdraw_hack = true; + UINT32 blendmode, trans; + if (spr->mobj->renderflags & RF_BLENDMASK) + blendmode = (spr->mobj->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + else + blendmode = (spr->mobj->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + if (spr->mobj->renderflags & RF_TRANSMASK) + trans = (spr->mobj->renderflags & RF_TRANSMASK) >> RF_TRANSSHIFT; + else + trans = (spr->mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + return; // cap + + blend = HWR_SurfaceBlend(blendmode, trans, &Surf); + if (!trans && !blendmode) + { + // BP: i agree that is little better in environement but it don't + // work properly under glide nor with fogcolor to ffffff :( + // Hurdler: PF_Environement would be cool, but we need to fix + // the issue with the fog before + blend |= occlusion; + if (!occlusion) use_linkdraw_hack = true; + } } if (HWR_UseShader()) @@ -3902,6 +3951,9 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) } } + if (R_ThingIsSemiBright(spr->mobj)) + lightlevel = 128 + (lightlevel>>1); + for (i = 0; i < sector->numlights; i++) { if (endtop < endrealbot && top < realbot) @@ -4255,6 +4307,9 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else if (!lightset) lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel; + if (R_ThingIsSemiBright(spr->mobj)) + lightlevel = 128 + (lightlevel>>1); + HWR_Lighting(&Surf, lightlevel, colormap); } @@ -4271,31 +4326,33 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) else occlusion = PF_Occlude; - if (!cv_translucency.value) // translucency disabled + // Determine the blendmode and translucency value { - Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|occlusion; - if (!occlusion) use_linkdraw_hack = true; - } - else if (spr->mobj->flags2 & MF2_SHADOW) - { - Surf.PolyColor.s.alpha = 0x40; - blend = HWR_GetBlendModeFlag(spr->mobj->blendmode); - } - else if (spr->mobj->frame & FF_TRANSMASK) - { - INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - blend = HWR_SurfaceBlend(spr->mobj->blendmode, trans, &Surf); - } - else - { - // BP: i agree that is little better in environement but it don't - // work properly under glide nor with fogcolor to ffffff :( - // Hurdler: PF_Environement would be cool, but we need to fix - // the issue with the fog before - Surf.PolyColor.s.alpha = 0xFF; - blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|occlusion; - if (!occlusion) use_linkdraw_hack = true; + UINT32 blendmode, trans; + if (spr->mobj->renderflags & RF_BLENDMASK) + blendmode = (spr->mobj->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + else + blendmode = (spr->mobj->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + if (spr->mobj->renderflags & RF_TRANSMASK) + trans = (spr->mobj->renderflags & RF_TRANSMASK) >> RF_TRANSSHIFT; + else + trans = (spr->mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + return; // cap + + blend = HWR_SurfaceBlend(blendmode, trans, &Surf); + if (!trans && !blendmode) + { + // BP: i agree that is little better in environement but it don't + // work properly under glide nor with fogcolor to ffffff :( + // Hurdler: PF_Environement would be cool, but we need to fix + // the issue with the fog before + blend |= occlusion; + if (!occlusion) use_linkdraw_hack = true; + } } if (spr->renderflags & RF_SHADOWEFFECTS) @@ -4401,19 +4458,32 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) HWR_Lighting(&Surf, lightlevel, colormap); } - if (spr->mobj->frame & FF_TRANSMASK) + // Determine the blendmode and translucency value { - INT32 trans = (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT; - blend = HWR_SurfaceBlend(AST_TRANSLUCENT, trans, &Surf); - } - else - { - // BP: i agree that is little better in environement but it don't - // work properly under glide nor with fogcolor to ffffff :( - // Hurdler: PF_Environement would be cool, but we need to fix - // the issue with the fog before - Surf.PolyColor.s.alpha = 0xFF; - blend = HWR_GetBlendModeFlag(spr->mobj->blendmode)|PF_Occlude; + UINT32 blendmode, trans; + if (spr->mobj->renderflags & RF_BLENDMASK) + blendmode = (spr->mobj->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + else + blendmode = (spr->mobj->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + if (spr->mobj->renderflags & RF_TRANSMASK) + trans = (spr->mobj->renderflags & RF_TRANSMASK) >> RF_TRANSSHIFT; + else + trans = (spr->mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + return; // cap + + blend = HWR_SurfaceBlend(blendmode, trans, &Surf); + if (!trans && !blendmode) + { + // BP: i agree that is little better in environement but it don't + // work properly under glide nor with fogcolor to ffffff :( + // Hurdler: PF_Environement would be cool, but we need to fix + // the issue with the fog before + blend |= PF_Occlude; + } } if (HWR_UseShader()) @@ -4989,13 +5059,6 @@ static void HWR_ProjectSprite(mobj_t *thing) if (thing->spritexscale < 1 || thing->spriteyscale < 1) return; - // Visibility check by the blend mode. - if (thing->frame & FF_TRANSMASK) - { - if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) - return; - } - dispoffset = thing->info->dispoffset; this_scale = FIXED_TO_FLOAT(thing->scale); @@ -5382,13 +5445,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) unsigned rot = 0; UINT8 flip; - // Visibility check by the blend mode. - if (thing->frame & FF_TRANSMASK) - { - if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) - return; - } - // transform the origin point tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 5caf344f7..8802349fe 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -414,7 +414,7 @@ static void md2_loadTexture(md2_t *model) size = w*h; while (size--) { - V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); + image->rgba = V_CubeApply(image); image++; } } @@ -1354,12 +1354,24 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) //if (tics > durs) //durs = tics; - if (spr->mobj->frame & FF_TRANSMASK) - Surf.PolyFlags = HWR_SurfaceBlend(spr->mobj->blendmode, (spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf); - else + // Determine the blendmode and translucency value { - Surf.PolyColor.s.alpha = (spr->mobj->flags2 & MF2_SHADOW) ? 0x40 : 0xff; - Surf.PolyFlags = HWR_GetBlendModeFlag(spr->mobj->blendmode); + UINT32 blendmode, trans; + if (spr->mobj->renderflags & RF_BLENDMASK) + blendmode = (spr->mobj->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + else + blendmode = (spr->mobj->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + if (spr->mobj->renderflags & RF_TRANSMASK) + trans = (spr->mobj->renderflags & RF_TRANSMASK) >> RF_TRANSSHIFT; + else + trans = (spr->mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + return false; // cap + + Surf.PolyFlags = HWR_SurfaceBlend(blendmode, trans, &Surf); } // don't forget to enable the depth test because we can't do this diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7c4f1acf1..828c455c4 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1869,7 +1869,7 @@ static void HU_DrawChat_Old(void) static inline void HU_DrawCrosshair(void) { - INT32 i, y; + INT32 i, y, dupz; i = cv_crosshair.value & 3; if (!i) @@ -1885,12 +1885,14 @@ static inline void HU_DrawCrosshair(void) #endif y = viewwindowy + (viewheight>>1); - V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); + dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + + V_DrawFixedPatch(vid.width<<(FRACBITS-1), y<>1); - if (splitscreen) - { -#ifdef HWRENDER - if (rendermode != render_soft) - y += (INT32)gl_viewheight; - else -#endif - y += viewheight; + if (!splitscreen) + return; - V_DrawScaledPatch(vid.width>>1, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); - } +#ifdef HWRENDER + if (rendermode != render_soft) + y += (INT32)gl_viewheight; + else +#endif + y += viewheight; + + dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + + V_DrawFixedPatch(vid.width<<(FRACBITS-1), y<alpha); return 1; + case ffloor_blend: + lua_pushinteger(L, ffloor->blend); + return 1; } return 0; } @@ -1885,6 +1890,9 @@ static int ffloor_set(lua_State *L) case ffloor_alpha: ffloor->alpha = (INT32)luaL_checkinteger(L, 3); break; + case ffloor_blend: + ffloor->blend = (INT32)luaL_checkinteger(L, 3); + break; } return 0; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 65adceb15..1cbb2da9f 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -316,7 +316,12 @@ static int mobj_get(lua_State *L) lua_pushinteger(L, mo->color); break; case mobj_blendmode: - lua_pushinteger(L, mo->blendmode); + { + INT32 backcompat = (mo->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + if (backcompat) + backcompat++; + lua_pushinteger(L, backcompat); + } break; case mobj_bnext: LUA_PushUserdata(L, mo->bnext, META_MOBJ); @@ -654,8 +659,15 @@ static int mobj_set(lua_State *L) break; } case mobj_blendmode: - mo->blendmode = (INT32)luaL_checkinteger(L, 3); + { + INT32 backcompat = (INT32)luaL_checkinteger(L, 3); + if (backcompat < 0 || backcompat > AST_OVERLAY) + return luaL_error(L, "mobj.blendmode %d out of range (0 - %d).", backcompat, AST_OVERLAY); + if (backcompat) + backcompat--; + mo->renderflags = (mo->renderflags & ~RF_BLENDMASK)|(backcompat << RF_BLENDSHIFT); break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: diff --git a/src/m_menu.c b/src/m_menu.c index 0fca39801..f278d594f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -4034,7 +4034,7 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) xx += p->width - p->leftoffset; for (i = 0; i < 16; i++) { - V_DrawScaledPatch(xx, y, V_WRAPX, W_CachePatchNum(centerlump[i & 1], PU_PATCH)); + V_DrawScaledPatch(xx, y, 0, W_CachePatchNum(centerlump[i & 1], PU_PATCH)); xx += 8; } V_DrawScaledPatch(xx, y, 0, W_CachePatchNum(rightlump, PU_PATCH)); @@ -4130,7 +4130,7 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) p = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); for (n = 0; n < boxlines; n++) { - V_DrawScaledPatch(cx, cy, V_WRAPY, p); + V_DrawScaledPatch(cx, cy, 0, p); cy += step; } V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BL], PU_PATCH)); @@ -4142,8 +4142,8 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) cy = y; while (width > 0) { - V_DrawScaledPatch(cx, cy, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH)); - V_DrawScaledPatch(cx, y + boff + boxlines*step, V_WRAPX, W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH)); + V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH)); + V_DrawScaledPatch(cx, y + boff + boxlines*step, 0, W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH)); width--; cx += step; } @@ -4155,7 +4155,7 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) p = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); for (n = 0; n < boxlines; n++) { - V_DrawScaledPatch(cx, cy, V_WRAPY, p); + V_DrawScaledPatch(cx, cy, 0, p); cy += step; } V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BR], PU_PATCH)); diff --git a/src/p_mobj.c b/src/p_mobj.c index 49db6daee..c1d89bcd9 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10477,7 +10477,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->destscale = FRACUNIT/2; // Sprite rendering - mobj->blendmode = AST_TRANSLUCENT; mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->floorspriteslope = NULL; diff --git a/src/p_mobj.h b/src/p_mobj.h index 5bb7c908e..be2a8400f 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -288,7 +288,6 @@ typedef struct mobj_s UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags - INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by @@ -415,7 +414,6 @@ typedef struct precipmobj_s UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags - INT32 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by diff --git a/src/p_pspr.h b/src/p_pspr.h index 231262beb..0bbb81c58 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -41,9 +41,20 @@ /// \brief Frame flags - SPR2: Super sprite2 #define FF_SPR2SUPER 0x80 /// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation -#define FF_SPR2ENDSTATE 0x1000 +#define FF_SPR2ENDSTATE 0x100 /// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation -#define FF_SPR2MIDSTART 0x2000 +#define FF_SPR2MIDSTART 0x200 + +/// \brief Frame flags: blend types +#define FF_BLENDMASK 0x7000 +/// \brief shift for FF_BLENDMASK +#define FF_BLENDSHIFT 12 +/// \brief preshifted blend flags minus 1 as effects don't distinguish between AST_COPY and AST_TRANSLUCENT +#define FF_ADD ((AST_ADD-1)<renderflags) diff2 |= MD2_RENDERFLAGS; - if (mobj->blendmode != AST_TRANSLUCENT) - diff2 |= MD2_BLENDMODE; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) @@ -1803,8 +1801,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) WRITEUINT32(save_p, mobj->renderflags); - if (diff2 & MD2_BLENDMODE) - WRITEINT32(save_p, mobj->blendmode); if (diff2 & MD2_SPRITEXSCALE) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) @@ -2843,10 +2839,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->shadowscale = READFIXED(save_p); if (diff2 & MD2_RENDERFLAGS) mobj->renderflags = READUINT32(save_p); - if (diff2 & MD2_BLENDMODE) - mobj->blendmode = READINT32(save_p); - else - mobj->blendmode = AST_TRANSLUCENT; if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save_p); else diff --git a/src/p_setup.c b/src/p_setup.c index 40dd1a284..28a103d6f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1350,8 +1350,11 @@ static void P_LoadSidedefs(UINT8 *data) if (msd->toptexture[0] == '#') { char *col = msd->toptexture; - sd->toptexture = sd->bottomtexture = - ((col[1]-'0')*100 + (col[2]-'0')*10 + col[3]-'0') + 1; + sd->toptexture = + ((col[1]-'0')*100 + (col[2]-'0')*10 + col[3]-'0')+1; + if (col[4]) // extra num for blendmode + sd->toptexture += (col[4]-'0')*1000; + sd->bottomtexture = sd->toptexture; sd->midtexture = R_TextureNumForName(msd->midtexture); } else diff --git a/src/p_spec.c b/src/p_spec.c index 226e58d15..6190ab189 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5629,8 +5629,31 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (flags & FF_TRANSLUCENT) { if (sides[master->sidenum[0]].toptexture > 0) - fflr->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned + { + // for future reference, "#0" is 1, and "#255" is 256. Be warned + fflr->alpha = sides[master->sidenum[0]].toptexture; + +#if 0 // kart indev compat + if (fflr->alpha == 901) // additive special + { + fflr->blend = AST_ADD; + fflr->alpha = 0xff; + } + else if (fflr->alpha == 902) // subtractive special + { + fflr->blend = AST_SUBTRACT; + fflr->alpha = 0xff; + } + else +#endif + if (fflr->alpha >= 1001) // fourth digit + { + fflr->blend = (fflr->alpha/1000)+1; // becomes an AST + fflr->alpha %= 1000; + } + } else + fflr->alpha = 0x80; } else diff --git a/src/r_data.c b/src/r_data.c index 2cfe9cb7a..841950cca 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -94,7 +94,7 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph #define clamp(c) max(min(c, 0xFF), 0x00); else { - float falpha = ((float)alpha / 256.0f); + float falpha = ((float)alpha / 255.0f); float fr = ((float)foreground.s.red * falpha); float fg = ((float)foreground.s.green * falpha); float fb = ((float)foreground.s.blue * falpha); diff --git a/src/r_data.h b/src/r_data.h index aec52b54b..770aefd43 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -30,9 +30,6 @@ typedef struct size_t numlumps; } lumplist_t; -// Possible alpha types for a patch. -enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; - UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT8 alpha); diff --git a/src/r_defs.h b/src/r_defs.h index 9c649fbc4..74f0ff9d8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -184,6 +184,7 @@ typedef struct ffloor_s INT32 lastlight; INT32 alpha; + UINT8 blend; tic_t norender; // for culling // these are saved for netgames, so do not let Lua touch these! @@ -713,6 +714,9 @@ typedef struct #pragma pack() #endif +// Possible alpha types for a patch. +typedef enum {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY} patchalphastyle_t; + typedef enum { RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally @@ -726,18 +730,51 @@ typedef enum RF_NOSPLATBILLBOARD = 0x0040, // Don't billboard floor sprites (faces forward from the view angle) RF_NOSPLATROLLANGLE = 0x0080, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) - RF_BLENDMASK = 0x0F00, // --Blending modes - RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness - RF_FULLDARK = 0x0200, // Sprite is drawn completely dark - RF_NOCOLORMAPS = 0x0400, // Sprite is not drawn with colormaps +RF_BRIGHTMASK = 0x00000300, // --Bright modes + RF_FULLBRIGHT = 0x00000100, // Sprite is drawn at full brightness + RF_FULLDARK = 0x00000200, // Sprite is drawn completely dark + RF_SEMIBRIGHT = (RF_FULLBRIGHT | RF_FULLDARK), // between sector bright and full bright - RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types - RF_PAPERSPRITE = 0x1000, // Paper sprite - RF_FLOORSPRITE = 0x2000, // Floor sprite + RF_NOCOLORMAPS = 0x00000400, // Sprite is not drawn with colormaps - RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow. - RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow. + RF_SPRITETYPEMASK = 0x00003000, // --Different sprite types + RF_PAPERSPRITE = 0x00001000, // Paper sprite + RF_FLOORSPRITE = 0x00002000, // Floor sprite + + RF_SHADOWDRAW = 0x00004000, // Stretches and skews the sprite like a shadow. + RF_SHADOWEFFECTS = 0x00008000, // Scales and becomes transparent like a shadow. RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK), + + RF_DONTDRAW = 0x00F00000, // --Don't generate a vissprite +#if 0 // kart compat, ask sal if you're gonna implement - this is why RF_DONTDRAW *must* take four bits + RF_DONTDRAWP1 = 0x00100000, // No P1 + RF_DONTDRAWP2 = 0x00200000, // No P2 + RF_DONTDRAWP3 = 0x00400000, // No P3 + RF_DONTDRAWP4 = 0x00800000, // No P4 +#endif + + RF_BLENDMASK = 0x07000000, // --Blending override - see patchalphastyle_t + RF_BLENDSHIFT = (6*4), + // minus 1 as effects don't distinguish between AST_COPY and AST_TRANSLUCENT + RF_ADD = ((AST_ADD-1)<= 0) - return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); - else + if (--alphalevel < 0) return NULL; -} - -boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel) -{ - if (blendmode == AST_COPY || blendmode == AST_SUBTRACT || blendmode == AST_MODULATE || blendmode == AST_OVERLAY) - return true; - - return (alphalevel < BlendTab_Count[BlendTab_FromStyle[blendmode]]); + return transtables + (ClipTransLevel(alphalevel) << FF_TRANSSHIFT); } // Define for getting accurate color brightness readings according to how the human eye sees them. diff --git a/src/r_draw.h b/src/r_draw.h index caf43fd89..0c0b6e0e0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -140,11 +140,11 @@ extern UINT8 *blendtables[NUMBLENDMAPS]; void R_InitTranslucencyTables(void); void R_GenerateBlendTables(void); +void R_GenerateTranslucencyTable(UINT8 *table, int style, UINT8 blendamt); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); -boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); // Color ramp modification should force a recache extern UINT8 skincolor_modified[]; diff --git a/src/r_plane.c b/src/r_plane.c index ea4dfa4e8..84fb35803 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -842,28 +842,14 @@ void R_DrawSinglePlane(visplane_t *pl) spanfunctype = (pl->ffloor->master->flags & ML_EFFECT6) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; // Hacked up support for alpha value in software mode Tails 09-24-2002 - if (pl->ffloor->alpha < 12) - return; // Don't even draw it - else if (pl->ffloor->alpha < 38) - ds_transmap = R_GetTranslucencyTable(tr_trans90); - else if (pl->ffloor->alpha < 64) - ds_transmap = R_GetTranslucencyTable(tr_trans80); - else if (pl->ffloor->alpha < 89) - ds_transmap = R_GetTranslucencyTable(tr_trans70); - else if (pl->ffloor->alpha < 115) - ds_transmap = R_GetTranslucencyTable(tr_trans60); - else if (pl->ffloor->alpha < 140) - ds_transmap = R_GetTranslucencyTable(tr_trans50); - else if (pl->ffloor->alpha < 166) - ds_transmap = R_GetTranslucencyTable(tr_trans40); - else if (pl->ffloor->alpha < 192) - ds_transmap = R_GetTranslucencyTable(tr_trans30); - else if (pl->ffloor->alpha < 217) - ds_transmap = R_GetTranslucencyTable(tr_trans20); - else if (pl->ffloor->alpha < 243) - ds_transmap = R_GetTranslucencyTable(tr_trans10); - else // Opaque, but allow transparent flat pixels - spanfunctype = SPANDRAWFUNC_SPLAT; + // ...unhacked by toaster 04-01-2021 + { + INT32 trans = (10*((256+12) - pl->ffloor->alpha))/255; + if (trans >= 10) + return; // Don't even draw it + if (!(ds_transmap = R_GetBlendTable(pl->ffloor->blend, trans))) + spanfunctype = SPANDRAWFUNC_SPLAT; // Opaque, but allow transparent flat pixels + } if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); diff --git a/src/r_segs.c b/src/r_segs.c index a6772f964..a2dc0335c 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -120,9 +120,13 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) } } -transnum_t R_GetLinedefTransTable(fixed_t alpha) +transnum_t R_GetLinedefTransTable(line_t *ldef) { - return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); + transnum_t transnum = NUMTRANSMAPS; // Send back NUMTRANSMAPS for none + fixed_t alpha = ldef->alpha; + if (alpha > 0 && alpha < FRACUNIT) + transnum = (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); + return transnum; } void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) @@ -139,6 +143,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) INT32 times, repeats; INT64 overflow_test; INT32 range; + transnum_t transtable = NUMTRANSMAPS; + patchalphastyle_t blendmode = 0; // Calculate light table. // Use different light tables @@ -155,11 +161,33 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (!ldef->alpha) return; - if (ldef->alpha > 0 && ldef->alpha < FRACUNIT) + transtable = R_GetLinedefTransTable(ldef); + if (ldef->special == 910) + { + if (transtable == NUMTRANSMAPS) + transtable = 0; + blendmode = AST_ADD; + } + else if (ldef->special == 911) + { + if (transtable == NUMTRANSMAPS) + transtable = 0; + blendmode = AST_SUBTRACT; + } + else if (ldef->special == 912) + { + if (transtable == NUMTRANSMAPS) + transtable = 0; + blendmode = AST_REVERSESUBTRACT; + } + else if (ldef->special == 913) + { + transtable = 0; + blendmode = AST_MODULATE; + } + if ((dc_transmap = R_GetBlendTable(blendmode, transtable))) { - dc_transmap = R_GetTranslucencyTable(R_GetLinedefTransTable(ldef->alpha)); colfunc = colfuncs[COLDRAWFUNC_FUZZY]; - } else if (ldef->special == 909) { @@ -600,28 +628,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) boolean fuzzy = true; // Hacked up support for alpha value in software mode Tails 09-24-2002 - if (pfloor->alpha < 12) - return; // Don't even draw it - else if (pfloor->alpha < 38) - dc_transmap = R_GetTranslucencyTable(tr_trans90); - else if (pfloor->alpha < 64) - dc_transmap = R_GetTranslucencyTable(tr_trans80); - else if (pfloor->alpha < 89) - dc_transmap = R_GetTranslucencyTable(tr_trans70); - else if (pfloor->alpha < 115) - dc_transmap = R_GetTranslucencyTable(tr_trans60); - else if (pfloor->alpha < 140) - dc_transmap = R_GetTranslucencyTable(tr_trans50); - else if (pfloor->alpha < 166) - dc_transmap = R_GetTranslucencyTable(tr_trans40); - else if (pfloor->alpha < 192) - dc_transmap = R_GetTranslucencyTable(tr_trans30); - else if (pfloor->alpha < 217) - dc_transmap = R_GetTranslucencyTable(tr_trans20); - else if (pfloor->alpha < 243) - dc_transmap = R_GetTranslucencyTable(tr_trans10); - else - fuzzy = false; // Opaque + // ...unhacked by toaster 04-01-2021 + { + INT32 trans = (10*((256+12) - pfloor->alpha))/255; + if (trans >= 10) + return; // Don't even draw it + if (!(dc_transmap = R_GetBlendTable(pfloor->blend, trans))) + fuzzy = false; // Opaque + } if (fuzzy) colfunc = colfuncs[COLDRAWFUNC_FUZZY]; diff --git a/src/r_segs.h b/src/r_segs.h index ace5711d4..0c43b0895 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -18,7 +18,7 @@ #pragma interface #endif -transnum_t R_GetLinedefTransTable(fixed_t alpha); +transnum_t R_GetLinedefTransTable(line_t *ldef); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); diff --git a/src/r_textures.c b/src/r_textures.c index d5da69018..e8d79981a 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -1072,7 +1072,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) INT16 patchYPos; UINT8 flip = 0; UINT8 alpha = 255; - enum patchalphastyle style = AST_COPY; + patchalphastyle_t style = AST_COPY; texpatch_t *resultPatch = NULL; lumpnum_t patchLumpNum; diff --git a/src/r_textures.h b/src/r_textures.h index 74a94a9ed..6e0cc168a 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -33,7 +33,7 @@ typedef struct UINT16 wad, lump; UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both UINT8 alpha; // Translucency value - enum patchalphastyle style; + patchalphastyle_t style; } texpatch_t; // texture type diff --git a/src/r_things.c b/src/r_things.c index 5c0e5fda9..a83a62009 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1109,6 +1109,10 @@ static void R_SplitSprite(vissprite_t *sprite) if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; + + if (newsprite->cut & SC_SEMIBRIGHT) + lindex = (MAXLIGHTSCALE/2) + (lindex >> 1); + newsprite->colormap = spritelights[lindex]; } } @@ -1410,7 +1414,8 @@ static void R_ProjectSprite(mobj_t *thing) boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored); INT32 lindex; - INT32 trans; + UINT32 blendmode; + UINT32 trans; vissprite_t *vis; patch_t *patch; @@ -1799,15 +1804,26 @@ static void R_ProjectSprite(mobj_t *thing) // Determine the translucency value. if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) - trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK - else if (oldthing->frame & FF_TRANSMASK) { - trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; - if (!R_BlendLevelVisible(oldthing->blendmode, trans)) - return; + trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK + blendmode = 0; } else - trans = 0; + { + if (oldthing->renderflags & RF_BLENDMASK) + blendmode = (oldthing->renderflags & RF_BLENDMASK) >> RF_BLENDSHIFT; + else + blendmode = (oldthing->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + if (oldthing->renderflags & RF_TRANSMASK) + trans = (oldthing->renderflags & RF_TRANSMASK) >> RF_TRANSSHIFT; + else + trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + return; // cap + } // Check if this sprite needs to be rendered like a shadow shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); @@ -2012,13 +2028,12 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += FixedMul(scalestep, spriteyscale) * (vis->x1 - x1); } - if ((oldthing->blendmode != AST_COPY) && cv_translucency.value) - vis->transmap = R_GetBlendTable(oldthing->blendmode, trans); - else - vis->transmap = NULL; + vis->transmap = R_GetBlendTable(blendmode, trans); if (R_ThingIsFullBright(oldthing) || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) vis->cut |= SC_FULLBRIGHT; + else if (R_ThingIsSemiBright(oldthing)) + vis->cut |= SC_SEMIBRIGHT; else if (R_ThingIsFullDark(oldthing)) vis->cut |= SC_FULLDARK; @@ -2041,6 +2056,9 @@ static void R_ProjectSprite(mobj_t *thing) if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; + if (vis->cut & SC_SEMIBRIGHT) + lindex = (MAXLIGHTSCALE/2) + (lindex >> 1); + vis->colormap = spritelights[lindex]; } @@ -3008,7 +3026,7 @@ boolean R_ThingVisible (mobj_t *thing) { return (!( thing->sprite == SPR_NULL || - ( thing->flags2 & (MF2_DONTDRAW) ) || + ( thing->flags2 & (MF2_DONTDRAW) ) || ( thing->renderflags & (RF_DONTDRAW) ) || (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) )); } @@ -3069,19 +3087,31 @@ boolean R_ThingIsPaperSprite(mobj_t *thing) boolean R_ThingIsFloorSprite(mobj_t *thing) { - return (thing->flags2 & MF2_SPLAT || thing->renderflags & RF_FLOORSPRITE); + return (thing->flags2 & MF2_SPLAT || thing->frame & FF_FLOORSPRITE || thing->renderflags & RF_FLOORSPRITE); } boolean R_ThingIsFullBright(mobj_t *thing) { - return (thing->frame & FF_FULLBRIGHT || thing->renderflags & RF_FULLBRIGHT); + if (thing->renderflags & RF_BRIGHTMASK) + return ((thing->renderflags & RF_BRIGHTMASK) == RF_FULLBRIGHT); + return ((thing->frame & FF_BRIGHTMASK) == FF_FULLBRIGHT); +} + +boolean R_ThingIsSemiBright(mobj_t *thing) +{ + if (thing->renderflags & RF_BRIGHTMASK) + return ((thing->renderflags & RF_BRIGHTMASK) == RF_SEMIBRIGHT); + return ((thing->frame & FF_BRIGHTMASK) == FF_SEMIBRIGHT); } boolean R_ThingIsFullDark(mobj_t *thing) { - return (thing->renderflags & RF_FULLDARK); + if (thing->renderflags & RF_BRIGHTMASK) + return ((thing->renderflags & RF_BRIGHTMASK) == RF_FULLDARK); + return ((thing->frame & FF_BRIGHTMASK) == FF_FULLDARK); } + // // R_DrawMasked // diff --git a/src/r_things.h b/src/r_things.h index 95b4215af..1d14fbcbd 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -82,6 +82,7 @@ boolean R_ThingIsPaperSprite (mobj_t *thing); boolean R_ThingIsFloorSprite (mobj_t *thing); boolean R_ThingIsFullBright (mobj_t *thing); +boolean R_ThingIsSemiBright (mobj_t *thing); boolean R_ThingIsFullDark (mobj_t *thing); // -------------- @@ -123,13 +124,14 @@ typedef enum SC_PRECIP = 1<<2, SC_LINKDRAW = 1<<3, SC_FULLBRIGHT = 1<<4, - SC_FULLDARK = 1<<5, - SC_VFLIP = 1<<6, - SC_ISSCALED = 1<<7, - SC_ISROTATED = 1<<8, - SC_SHADOW = 1<<9, - SC_SHEAR = 1<<10, - SC_SPLAT = 1<<11, + SC_SEMIBRIGHT = 1<<5, + SC_FULLDARK = 1<<6, + SC_VFLIP = 1<<7, + SC_ISSCALED = 1<<8, + SC_ISROTATED = 1<<9, + SC_SHADOW = 1<<10, + SC_SHEAR = 1<<11, + SC_SPLAT = 1<<12, // masks SC_CUTMASK = SC_TOP|SC_BOTTOM, SC_FLAGMASK = ~SC_CUTMASK diff --git a/src/v_video.c b/src/v_video.c index 4713db0d8..8304f43d3 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -86,6 +86,7 @@ consvar_t cv_constextsize = CVAR_INIT ("con_textsize", "Medium", CV_SAVE|CV_CALL // local copy of the palette for V_GetColor() RGBA_t *pLocalPalette = NULL; RGBA_t *pMasterPalette = NULL; +RGBA_t *pGammaCorrectedPalette = NULL; /* The following was an extremely helpful resource when developing my Colour Cube LUT. @@ -279,33 +280,25 @@ static boolean InitCube(void) return true; } -#ifdef BACKWARDSCOMPATCORRECTION -/* -So it turns out that the way gamma was implemented previously, the default -colour profile of the game was messed up. Since this bad decision has been -around for a long time, and the intent is to keep the base game looking the -same, I'm not gonna be the one to remove this base modification. -toast 20/04/17 -... welp yes i am (27/07/19, see the ifdef around it) -*/ -const UINT8 correctiontable[256] = - {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, - 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32, - 33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48, - 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, - 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, - 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96, - 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, - 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, - 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, - 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, - 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, - 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; -#endif +UINT32 V_GammaCorrect(UINT32 input, double power) +{ + RGBA_t result; + double linear; + + result.rgba = input; + + linear = ((double)result.s.red)/255.0f; + linear = pow(linear, power)*255.0f; + result.s.red = (UINT8)(linear); + linear = ((double)result.s.green)/255.0f; + linear = pow(linear, power)*255.0f; + result.s.green = (UINT8)(linear); + linear = ((double)result.s.blue)/255.0f; + linear = pow(linear, power)*255.0f; + result.s.blue = (UINT8)(linear); + + return result.rgba; +} // keep a copy of the palette so that we can get the RGB value for a color index at any time. static void LoadPalette(const char *lumpname) @@ -316,42 +309,45 @@ static void LoadPalette(const char *lumpname) Cubeapply = InitCube(); - Z_Free(pLocalPalette); + if (pLocalPalette != pMasterPalette) + Z_Free(pLocalPalette); Z_Free(pMasterPalette); - pLocalPalette = Z_Malloc(sizeof (*pLocalPalette)*palsize, PU_STATIC, NULL); pMasterPalette = Z_Malloc(sizeof (*pMasterPalette)*palsize, PU_STATIC, NULL); + if (Cubeapply) + pLocalPalette = Z_Malloc(sizeof (*pLocalPalette)*palsize, PU_STATIC, NULL); + else + pLocalPalette = pMasterPalette; + pGammaCorrectedPalette = Z_Malloc(sizeof (*pGammaCorrectedPalette)*palsize, PU_STATIC, NULL); pal = W_CacheLumpNum(lumpnum, PU_CACHE); for (i = 0; i < palsize; i++) { -#ifdef BACKWARDSCOMPATCORRECTION - pMasterPalette[i].s.red = pLocalPalette[i].s.red = correctiontable[*pal++]; - pMasterPalette[i].s.green = pLocalPalette[i].s.green = correctiontable[*pal++]; - pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = correctiontable[*pal++]; -#else - pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++; - pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++; - pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++; -#endif - pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF; + pMasterPalette[i].s.red = *pal++; + pMasterPalette[i].s.green = *pal++; + pMasterPalette[i].s.blue = *pal++; + pMasterPalette[i].s.alpha = 0xFF; - // lerp of colour cubing! if you want, make it smoother yourself - if (Cubeapply) - V_CubeApply(&pLocalPalette[i].s.red, &pLocalPalette[i].s.green, &pLocalPalette[i].s.blue); + pGammaCorrectedPalette[i].rgba = V_GammaDecode(pMasterPalette[i].rgba); + + if (!Cubeapply) + continue; + + pLocalPalette[i].rgba = V_GammaEncode(V_CubeApply(&pGammaCorrectedPalette[i])); } } -void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) +UINT32 V_CubeApply(RGBA_t *input) { float working[4][3]; float linear; UINT8 q; + RGBA_t result; if (!Cubeapply) - return; + return (*input).rgba; - linear = (*red/255.0); + linear = ((*input).s.red/255.0); #define dolerp(e1, e2) ((1 - linear)*e1 + linear*e2) for (q = 0; q < 3; q++) { @@ -360,13 +356,13 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) working[2][q] = dolerp(Cubepal[0][0][1][q], Cubepal[1][0][1][q]); working[3][q] = dolerp(Cubepal[0][1][1][q], Cubepal[1][1][1][q]); } - linear = (*green/255.0); + linear = ((*input).s.green/255.0); for (q = 0; q < 3; q++) { working[0][q] = dolerp(working[0][q], working[1][q]); working[1][q] = dolerp(working[2][q], working[3][q]); } - linear = (*blue/255.0); + linear = ((*input).s.blue/255.0); for (q = 0; q < 3; q++) { working[0][q] = 255*dolerp(working[0][q], working[1][q]); @@ -377,9 +373,12 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) } #undef dolerp - *red = (UINT8)(working[0][0]); - *green = (UINT8)(working[0][1]); - *blue = (UINT8)(working[0][2]); + result.s.red = (UINT8)(working[0][0]); + result.s.green = (UINT8)(working[0][1]); + result.s.blue = (UINT8)(working[0][2]); + result.s.alpha = (*input).s.alpha; + + return result.rgba; } const char *R_GetPalname(UINT16 num) @@ -510,7 +509,7 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); - UINT32 alphalevel = 0; + UINT32 alphalevel, blendmode; fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; @@ -536,25 +535,22 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca patchdrawfunc = standardpdraw; - v_translevel = NULL; + if ((blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT))) + blendmode++; // realign to constants if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) { - if (alphalevel == 13) + if (alphalevel == 10) // V_HUDTRANSHALF alphalevel = hudminusalpha[st_translucency]; - else if (alphalevel == 14) + else if (alphalevel == 11) // V_HUDTRANS alphalevel = 10 - st_translucency; - else if (alphalevel == 15) + else if (alphalevel == 12) // V_HUDTRANSDOUBLE alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) - return; // invis - - if (alphalevel) - { - v_translevel = R_GetTranslucencyTable(alphalevel); - patchdrawfunc = translucentpdraw; - } + if (alphalevel >= 10) // Still inelegible to render? + return; } + if ((v_translevel = R_GetBlendTable(blendmode, alphalevel))) + patchdrawfunc = translucentpdraw; v_colormap = NULL; if (colormap) @@ -590,10 +586,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca colfrac = FixedDiv(FRACUNIT, fdup); rowfrac = FixedDiv(FRACUNIT, vdup); - // So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible - // For now let's just at least give V_OFFSET the ability to support V_FLIP - // I'll probably make a better fix for 2.2 where I don't have to worry about breaking existing support for stuff - // -- Monster Iestyn 29/10/18 { fixed_t offsetx = 0, offsety = 0; @@ -604,15 +596,9 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca offsetx = FixedMul(patch->leftoffset<topoffset<> V_BLENDSHIFT))) + blendmode++; // realign to constants if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) { - if (alphalevel == 13) + if (alphalevel == 10) // V_HUDTRANSHALF alphalevel = hudminusalpha[st_translucency]; - else if (alphalevel == 14) + else if (alphalevel == 11) // V_HUDTRANS alphalevel = 10 - st_translucency; - else if (alphalevel == 15) + else if (alphalevel == 12) // V_HUDTRANSDOUBLE alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) - return; // invis - - if (alphalevel) - { - v_translevel = R_GetTranslucencyTable(alphalevel); - patchdrawfunc = translucentpdraw; - } + if (alphalevel >= 10) // Still inelegible to render? + return; } + if ((v_translevel = R_GetBlendTable(blendmode, alphalevel))) + patchdrawfunc = translucentpdraw; // only use one dup, to avoid stretching (har har) dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); @@ -1358,15 +1341,15 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) { - if (alphalevel == 13) + if (alphalevel == 10) // V_HUDTRANSHALF alphalevel = hudminusalpha[st_translucency]; - else if (alphalevel == 14) + else if (alphalevel == 11) // V_HUDTRANS alphalevel = 10 - st_translucency; - else if (alphalevel == 15) + else if (alphalevel == 12) // V_HUDTRANSDOUBLE alphalevel = hudplusalpha[st_translucency]; - if (alphalevel >= 10) - return; // invis + if (alphalevel >= 10) // Still inelegible to render? + return; } if (splitscreen && (c & V_PERPLAYER)) diff --git a/src/v_video.h b/src/v_video.h index 8a18f82ad..d4ac36f8a 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -63,8 +63,13 @@ const char *GetPalette(void); extern RGBA_t *pLocalPalette; extern RGBA_t *pMasterPalette; +extern RGBA_t *pGammaCorrectedPalette; -void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); +UINT32 V_GammaCorrect(UINT32 input, double power); +#define V_GammaDecode(input) V_GammaCorrect(input, 2.2f) +#define V_GammaEncode(input) V_GammaCorrect(input, (1/2.2f)) + +UINT32 V_CubeApply(RGBA_t *input); // Retrieve the ARGB value from a palette color index #define V_GetColor(color) (pLocalPalette[color&0xFF]) @@ -122,17 +127,23 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_70TRANS 0x00070000 #define V_80TRANS 0x00080000 // used to be V_8020TRANS #define V_90TRANS 0x00090000 -#define V_HUDTRANSHALF 0x000D0000 -#define V_HUDTRANS 0x000E0000 // draw the hud translucent -#define V_HUDTRANSDOUBLE 0x000F0000 +#define V_HUDTRANSHALF 0x000A0000 +#define V_HUDTRANS 0x000B0000 // draw the hud translucent +#define V_HUDTRANSDOUBLE 0x000C0000 // Macros follow #define V_USERHUDTRANSHALF ((10-(cv_translucenthud.value/2))<