diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 1e1feaf00..0e994abf9 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -108,12 +108,12 @@ CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL) void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending, int *tm, int *sb, int *db, int *be) { - static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }; + static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, }; static int renderops[] = { 0, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - int srcblend = blendstyles[style.SrcAlpha&3]; - int dstblend = blendstyles[style.DestAlpha&3]; + int srcblend = blendstyles[style.SrcAlpha%STYLEALPHA_MAX]; + int dstblend = blendstyles[style.DestAlpha%STYLEALPHA_MAX]; int blendequation = renderops[style.BlendOp&15]; int texturemode = drawopaque? TM_OPAQUE : TM_MODULATE; diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index c6496102c..50ef35c0b 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -560,7 +560,7 @@ void gl_FillScreen() // Draws a blend over the entire view // //========================================================================== -void FGLRenderer::DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap) +void FGLRenderer::DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap, bool in2d) { float blend[4] = { 0,0,0,0 }; PalEntry blendv = 0; @@ -623,15 +623,22 @@ void FGLRenderer::DrawBlend(sector_t * viewsector, bool FixedColormap, bool doco extra_blue = blendv.b / 255.0f; // If this is a multiplicative blend do it separately and add the additive ones on top of it. - blendv = 0; // black multiplicative blends are ignored if (extra_red || extra_green || extra_blue) { - gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO); - gl_RenderState.SetColor(extra_red, extra_green, extra_blue, 1.0f); - gl_FillScreen(); + if (!in2d) + { + gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO); + gl_RenderState.SetColor(extra_red, extra_green, extra_blue, 1.0f); + gl_FillScreen(); + } + else + { + screen->Dim(blendv, 1, 0, 0, screen->GetWidth(), screen->GetHeight(), &LegacyRenderStyles[STYLE_Multiply]); + } } + blendv = 0; } else if (blendv.a) { @@ -655,15 +662,22 @@ void FGLRenderer::DrawBlend(sector_t * viewsector, bool FixedColormap, bool doco V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); } - gl_RenderState.SetTextureMode(TM_MODULATE); - gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (blend[3]>0.0f) + if (!in2d) { - gl_RenderState.SetColor(blend[0], blend[1], blend[2], blend[3]); - gl_FillScreen(); + gl_RenderState.SetTextureMode(TM_MODULATE); + gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (blend[3] > 0.0f) + { + gl_RenderState.SetColor(blend[0], blend[1], blend[2], blend[3]); + gl_FillScreen(); + } + gl_RenderState.ResetColor(); + gl_RenderState.EnableTexture(true); + } + else + { + screen->Dim(PalEntry(255, blend[0] * 255, blend[1] * 255, blend[2] * 255), blend[3], 0, 0, screen->GetWidth(), screen->GetHeight()); } - gl_RenderState.ResetColor(); - gl_RenderState.EnableTexture(true); } diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 59b18d2f4..2b81ae547 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -193,7 +193,7 @@ public: void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); void RenderView(player_t *player); - void DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap); + void DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap, bool in2d = false); bool StartOffscreen(); diff --git a/src/gl/scene/gl_swscene.cpp b/src/gl/scene/gl_swscene.cpp index 7d5a21a8d..972a20cbf 100644 --- a/src/gl/scene/gl_swscene.cpp +++ b/src/gl/scene/gl_swscene.cpp @@ -123,5 +123,5 @@ void SWSceneDrawer::RenderView(player_t *player) screen->Begin2D(false); screen->DrawTexture(FBTexture, 0, 0, DTA_SpecialColormap, map, TAG_DONE); SWRenderer->DrawRemainingPlayerSprites(); - GLRenderer->DrawBlend(r_viewpoint.sector, !!map, swtruecolor); + GLRenderer->DrawBlend(r_viewpoint.sector, !!map, swtruecolor, true); } diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 987de82b9..9b0569ea4 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -58,6 +58,7 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] = { { STYLEOP_RevSub, STYLEALPHA_Src, STYLEALPHA_One, 0 } }, /* STYLE_Subtract*/ { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_ColorIsFixed } }, /* STYLE_AddStencil */ { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */ + { { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */ }; double GetAlpha(int type, double alpha) @@ -68,7 +69,7 @@ double GetAlpha(int type, double alpha) case STYLEALPHA_One: return 1.; case STYLEALPHA_Src: return alpha; case STYLEALPHA_InvSrc: return 1. - alpha; - default: return 0; + default: return 0.5; // undeterminable } } diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index afb82d380..d5393f487 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -61,6 +61,7 @@ enum ERenderStyle STYLE_Subtract, // Actually this is 'reverse subtract' but this is what normal people would expect by 'subtract'. STYLE_AddStencil, // Fill image interior with alphacolor STYLE_AddShaded, // Treat patch data as alpha values for alphacolor + STYLE_Multiply, // Multiply source with destination (HW renderer only.) STYLE_Count }; @@ -87,6 +88,11 @@ enum ERenderAlpha STYLEALPHA_One, // Blend factor is 1.0 STYLEALPHA_Src, // Blend factor is alpha STYLEALPHA_InvSrc, // Blend factor is 1.0 - alpha + STYLEALPHA_SrcCol, // Blend factor is color (HWR only) + STYLEALPHA_InvSrcCol, // Blend factor is 1.0 - color (HWR only) + STYLEALPHA_DstCol, // Blend factor is dest. color (HWR only) + STYLEALPHA_InvDstCol, // Blend factor is 1.0 - dest. color (HWR only) + STYLEALPHA_MAX }; enum ERenderFlags diff --git a/src/v_2ddrawer.cpp b/src/v_2ddrawer.cpp index fd0a9ce7a..e860d8034 100644 --- a/src/v_2ddrawer.cpp +++ b/src/v_2ddrawer.cpp @@ -435,14 +435,14 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FTexture * // //=========================================================================== -void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color) +void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, FRenderStyle *style) { RenderCommand dg; dg.mType = DrawTypeTriangles; dg.mVertCount = 4; dg.mVertIndex = (int)mVertices.Reserve(4); - dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; + dg.mRenderStyle = style? *style : LegacyRenderStyles[STYLE_Translucent]; auto ptr = &mVertices[dg.mVertIndex]; ptr->Set(x1, y1, 0, 0, 0, color); ptr++; ptr->Set(x1, y1 + h, 0, 0, 0, color); ptr++; diff --git a/src/v_2ddrawer.h b/src/v_2ddrawer.h index ad045a9b2..96fb51782 100644 --- a/src/v_2ddrawer.h +++ b/src/v_2ddrawer.h @@ -122,7 +122,7 @@ public: DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel); void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin); - void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color); + void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style); void AddDim(PalEntry color, float damount, int x1, int y1, int w, int h); void AddClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 081c20ab4..477a20b05 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1106,7 +1106,7 @@ void DFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, { color = GPalette.BaseColors[palcolor] | 0xff000000; } - m2DDrawer.AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000); + m2DDrawer.AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000, nullptr); } DEFINE_ACTION_FUNCTION(_Screen, Clear) @@ -1131,7 +1131,7 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) // //========================================================================== -void DFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) +void DFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style) { if (amount <= 0) { @@ -1141,10 +1141,10 @@ void DFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, in { amount = 1; } - m2DDrawer.AddColorOnlyQuad(x1, y1, w, h, color | (int(amount * 255) << 24)); + m2DDrawer.AddColorOnlyQuad(x1, y1, w, h, color.d & 0xffffff | (int(amount * 255) << 24), style); } -void DFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void DFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle *style) { if (clipwidth >= 0 && clipheight >= 0) { @@ -1164,7 +1164,7 @@ void DFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int if (h > clipheight) h = clipheight; if (h <= 0) return; } - DoDim(color, damount, x1, y1, w, h); + DoDim(color, damount, x1, y1, w, h, style); } DEFINE_ACTION_FUNCTION(_Screen, Dim) diff --git a/src/v_video.h b/src/v_video.h index 39d07eb07..7f745de20 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -371,8 +371,8 @@ public: void Clear2D() { m2DDrawer.Clear(); } // Dim part of the canvas - void Dim(PalEntry color, float amount, int x1, int y1, int w, int h); - void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h); + void Dim(PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style = nullptr); + void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style = nullptr); // Fill an area with a texture void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false);