diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 8b014641c..add2fdb12 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -42,9 +42,6 @@ static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; FGLRenderState gl_RenderState; -CVAR(Bool, gl_direct_state_change, true, 0) - - static VSMatrix identityMatrix(1); TArray gl_MatrixStack; @@ -213,19 +210,10 @@ bool FGLRenderState::ApplyShader() void FGLRenderState::Apply() { - if (!gl_direct_state_change) + if (mRenderStyle != stRenderStyle) { - if (mSrcBlend != stSrcBlend || mDstBlend != stDstBlend) - { - stSrcBlend = mSrcBlend; - stDstBlend = mDstBlend; - glBlendFunc(mSrcBlend, mDstBlend); - } - if (mBlendEquation != stBlendEquation) - { - stBlendEquation = mBlendEquation; - glBlendEquation(mBlendEquation); - } + ApplyBlendMode(); + stRenderStyle = mRenderStyle; } if (mMaterial.mChanged) @@ -343,4 +331,40 @@ void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translatio } } +//========================================================================== +// +// Apply blend mode from RenderStyle +// +//========================================================================== +void FGLRenderState::ApplyBlendMode() +{ + 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[mRenderStyle.SrcAlpha%STYLEALPHA_MAX]; + int dstblend = blendstyles[mRenderStyle.DestAlpha%STYLEALPHA_MAX]; + int blendequation = renderops[mRenderStyle.BlendOp & 15]; + + if (blendequation == -1) // This was a fuzz style. + { + srcblend = GL_DST_COLOR; + dstblend = GL_ONE_MINUS_SRC_ALPHA; + blendequation = GL_FUNC_ADD; + } + + // Checks must be disabled until all draw code has been converted. + //if (srcblend != stSrcBlend || dstblend != stDstBlend) + { + stSrcBlend = srcblend; + stDstBlend = dstblend; + glBlendFunc(srcblend, dstblend); + } + //if (blendequation != stBlendEquation) + { + stBlendEquation = blendequation; + glBlendEquation(blendequation); + } + +} diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index ec220d901..a79f2cd2d 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -39,8 +39,6 @@ class FShader; struct GLSectorPlane; extern TArray gl_MatrixStack; -EXTERN_CVAR(Bool, gl_direct_state_change) - enum EPassType { NORMAL_PASS, @@ -67,6 +65,7 @@ class FGLRenderState : public FRenderState int mEffectState; int mTempTM = TM_MODULATE; + FRenderStyle stRenderStyle; int stSrcBlend, stDstBlend; bool stAlphaTest; int stBlendEquation; @@ -103,6 +102,7 @@ public: void Apply(); void ApplyLightIndex(int index); + void ApplyBlendMode(); void SetVertexBuffer(FVertexBuffer *vb) { @@ -164,27 +164,14 @@ public: void BlendFunc(int src, int dst) { - if (!gl_direct_state_change) - { - mSrcBlend = src; - mDstBlend = dst; - } - else - { - glBlendFunc(src, dst); - } + glBlendFunc(src, dst); + stRenderStyle = LegacyRenderStyles[STYLE_OptFuzzy]; // temporary hack: Set to something that never can get here to invalidate the cache } void BlendEquation(int eq) { - if (!gl_direct_state_change) - { - mBlendEquation = eq; - } - else - { - glBlendEquation(eq); - } + glBlendEquation(eq); + stRenderStyle = LegacyRenderStyles[STYLE_OptFuzzy]; // temporary hack: Set to something that never can get here to invalidate the cache } // This wraps the depth clamp setting because we frequently need to read it which OpenGL is not particularly performant at... diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 34eb2918c..397c280f2 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -216,7 +216,7 @@ void FDrawInfo::DrawFlat(GLFlat *flat, int pass, bool trans) // trans only has m break; case GLPASS_TRANSLUCENT: - if (flat->renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE); + gl_RenderState.SetRenderStyle(flat->renderstyle); SetColor(flat->lightlevel, rel, flat->Colormap, flat->alpha); SetFog(flat->lightlevel, rel, &flat->Colormap, false); if (!flat->gltexture || !flat->gltexture->tex->isFullbright()) @@ -237,7 +237,7 @@ void FDrawInfo::DrawFlat(GLFlat *flat, int pass, bool trans) // trans only has m DrawSubsectors(flat, pass, true); gl_RenderState.EnableTextureMatrix(false); } - if (flat->renderstyle==STYLE_Add) gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gl_RenderState.SetRenderStyle(DefaultRenderStyle()); gl_RenderState.SetObjectColor(0xffffffff); break; } diff --git a/src/hwrenderer/scene/hw_renderstate.h b/src/hwrenderer/scene/hw_renderstate.h index c28052418..d37787988 100644 --- a/src/hwrenderer/scene/hw_renderstate.h +++ b/src/hwrenderer/scene/hw_renderstate.h @@ -129,6 +129,7 @@ protected: PalEntry mObjectColor; PalEntry mObjectColor2; FStateVec4 mDynColor; + FRenderStyle mRenderStyle; FMaterialState mMaterial; FStencilState mStencil; @@ -157,6 +158,7 @@ public: mLightParms[3] = -1.f; mSpecialEffect = EFF_NONE; mLightIndex = -1; + mRenderStyle = DefaultRenderStyle(); mMaterial.Reset(); mStencil.Reset(); mBias.Reset(); @@ -333,6 +335,15 @@ public: mLightIndex = index; } + void SetRenderStyle(FRenderStyle rs) + { + mRenderStyle = rs; + } + + void SetRenderStyle(ERenderStyle rs) + { + mRenderStyle = rs; + } void SetDepthBias(float a, float b) { diff --git a/src/r_data/renderstyle.cpp b/src/r_data/renderstyle.cpp index 7c27e822c..2ce22d19c 100644 --- a/src/r_data/renderstyle.cpp +++ b/src/r_data/renderstyle.cpp @@ -60,6 +60,8 @@ FRenderStyle LegacyRenderStyles[STYLE_Count] = { { STYLEOP_Add, STYLEALPHA_Src, STYLEALPHA_One, STYLEF_RedIsAlpha | STYLEF_ColorIsFixed } }, /* STYLE_AddShaded */ { { STYLEOP_Add, STYLEALPHA_DstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_Multiply */ { { STYLEOP_Add, STYLEALPHA_InvDstCol, STYLEALPHA_Zero, 0 } }, /* STYLE_InverseMultiply */ + { { STYLEOP_Add, STYLEALPHA_SrcCol, STYLEALPHA_InvSrcCol, 0 } }, /* STYLE_ColorBlend */ + { { STYLEOP_Add, STYLEALPHA_One, STYLEALPHA_Zero, 0 } }, /* STYLE_Source */ }; double GetAlpha(int type, double alpha) diff --git a/src/r_data/renderstyle.h b/src/r_data/renderstyle.h index 04970f962..4e84728ed 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -63,6 +63,8 @@ enum ERenderStyle STYLE_AddShaded, // Treat patch data as alpha values for alphacolor STYLE_Multiply, // Multiply source with destination (HW renderer only.) STYLE_InverseMultiply, // Multiply source with inverse of destination (HW renderer only.) + STYLE_ColorBlend, // Use color intensity as transparency factor + STYLE_Source, // No blending (only used internally) STYLE_Count }; @@ -141,6 +143,7 @@ union FRenderStyle inline FRenderStyle &operator= (ERenderStyle legacy); bool operator==(const FRenderStyle &o) const { return AsDWORD == o.AsDWORD; } + bool operator!=(const FRenderStyle &o) const { return AsDWORD != o.AsDWORD; } void CheckFuzz(); bool IsVisible(double alpha) const throw(); private: @@ -157,11 +160,6 @@ inline FRenderStyle DefaultRenderStyle() return LegacyRenderStyles[STYLE_Normal]; } -inline FRenderStyle BadRenderStyle() // This is just a marker to find places where work is still needed. -{ - return LegacyRenderStyles[STYLE_Normal]; -} - inline FRenderStyle &FRenderStyle::operator= (ERenderStyle legacy) { if (legacy < STYLE_None || legacy >= STYLE_Count)