From 211a7f2569215559c4f1b896664b300c51b1009c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 7 Apr 2018 10:53:20 +0200 Subject: [PATCH] - made the screen blend work for the software renderer. It may use the same calculations as the hardware renderer but must use the 2D drawer for display. It should be investigated if the hardware renderer can do this as well. --- src/gl/renderer/gl_lightdata.cpp | 6 ++--- src/gl/renderer/gl_renderer.cpp | 38 ++++++++++++++++++++++---------- src/gl/renderer/gl_renderer.h | 2 +- src/gl/scene/gl_swscene.cpp | 2 +- src/r_data/renderstyle.cpp | 3 ++- src/r_data/renderstyle.h | 6 +++++ src/v_2ddrawer.cpp | 4 ++-- src/v_2ddrawer.h | 2 +- src/v_draw.cpp | 10 ++++----- src/v_video.h | 4 ++-- 10 files changed, 49 insertions(+), 28 deletions(-) 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);