From 70b6754299b0836717b1a3d69f4f5c4d8e39dd53 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 28 Mar 2018 21:38:00 +0200 Subject: [PATCH] - implemented the 2D drawer for the hardware renderer. Not tested yet. --- src/gl/renderer/gl_colormap.h | 4 +- src/gl/renderer/gl_lightdata.cpp | 1 - src/gl/renderer/gl_renderer.cpp | 167 +++++++++++++++++++++++++++ src/gl/renderer/gl_renderer.h | 1 + src/gl/renderer/gl_renderstate.cpp | 21 ++++ src/gl/renderer/gl_renderstate.h | 2 +- src/gl/system/gl_framebuffer.cpp | 12 ++ src/gl/system/gl_framebuffer.h | 1 + src/gl/system/gl_interface.h | 3 +- src/gl/textures/gl_translate.cpp | 17 +-- src/gl/textures/gl_translate.h | 1 + src/v_2ddrawer.h | 6 +- src/v_video.h | 4 +- wadsrc/static/shaders/d3d/shaders.ps | 18 +-- 14 files changed, 232 insertions(+), 26 deletions(-) diff --git a/src/gl/renderer/gl_colormap.h b/src/gl/renderer/gl_colormap.h index 85988e0b8..0bdd7dd8c 100644 --- a/src/gl/renderer/gl_colormap.h +++ b/src/gl/renderer/gl_colormap.h @@ -9,7 +9,9 @@ struct lightlist_t; enum EColorManipulation { - + CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here. + CM_INGAME2D = -3, // ingame lighting mode for automap + CM_PLAIN2D = -2, // regular 2D drawing. CM_INVALID=-1, CM_DEFAULT=0, // untranslated CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index b1960c91f..542b6a588 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -138,7 +138,6 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend } else if (style.Flags & STYLEF_InvertSource) { - // The only place where InvertSource is used is for inverted sprites with the infrared powerup. texturemode = TM_INVERSE; } diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index db7e8bb00..5d2ef73bd 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -432,3 +432,170 @@ unsigned char *FGLRenderer::GetTextureBuffer(FTexture *tex, int &w, int &h) } return NULL; } + +//=========================================================================== +// +// Vertex buffer for 2D drawer +// +//=========================================================================== +#define TDiO ((F2DDrawer::TwoDVertex*)NULL) + +class F2DVertexBuffer : public FVertexBuffer +{ + uint32_t ibo_id; + +public: + + F2DVertexBuffer() + { + glGenBuffers(1, &ibo_id); + } + ~F2DVertexBuffer() + { + if (ibo_id != 0) + { + glDeleteBuffers(1, &ibo_id); + } + } + void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount) + { + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBufferData(GL_ARRAY_BUFFER, vertcount * sizeof(vertices[0]), vertices, GL_STREAM_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_id); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexcount * sizeof(indices[0]), indices, GL_STREAM_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + void BindVBO() override + { + // set up the vertex buffer for drawing the 2D elements. + glGenBuffers(1, &vbo_id); + glGenBuffers(1, &ibo_id); + + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSimpleVertex), &TDiO->x); + glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSimpleVertex), &TDiO->u); + glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSimpleVertex), &TDiO->color0); + glEnableVertexAttribArray(VATTR_VERTEX); + glEnableVertexAttribArray(VATTR_TEXCOORD); + glEnableVertexAttribArray(VATTR_COLOR); + glDisableVertexAttribArray(VATTR_VERTEX2); + glDisableVertexAttribArray(VATTR_NORMAL); + } +}; + +//=========================================================================== +// +// Draws the 2D stuff. This is the version for OpenGL 3 and later. +// +//=========================================================================== + +void FGLRenderer::Draw2D(F2DDrawer *drawer) +{ + F2DDrawer::EDrawType lasttype = F2DDrawer::DrawTypeTriangles; + auto &vertices = drawer->mVertices; + auto &indices = drawer->mIndices; + auto &commands = drawer->mData; + + if (commands.Size() == 0) return; + + for (auto &v : vertices) + { + // Change from BGRA to RGBA + std::swap(v.color0.r, v.color0.b); + } + auto vb = new F2DVertexBuffer; + vb->UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size()); + gl_RenderState.SetVertexBuffer(vb); + + + for(auto &cmd : commands) + { + gl_RenderState.ResetColor(); // this is needed to reset the desaturation. + int tm, sb, db, be; + // The texture mode being returned here cannot be used, because the higher level code + // already manipulated the data so that some cases will not be handled correctly. + // Since we already get a proper mode from the calling code this doesn't really matter. + gl_GetRenderStyle(cmd.mRenderStyle, false, false, &tm, &sb, &db, &be); + gl_RenderState.BlendEquation(be); + gl_RenderState.BlendFunc(sb, db); + + // Rather than adding remapping code, let's enforce that the constants here are equal. + static_assert(F2DDrawer::DTM_Normal == TM_MODULATE, "DTM_Normal != TM_MODULATE"); + static_assert(F2DDrawer::DTM_Opaque == TM_OPAQUE, "DTM_Opaque != TM_OPAQUE"); + static_assert(F2DDrawer::DTM_Invert == TM_INVERSE, "DTM_Invert != TM_INVERSE"); + static_assert(F2DDrawer::DTM_InvertOpaque == TM_INVERTOPAQUE, "DTM_InvertOpaque != TM_INVERTOPAQUE"); + static_assert(F2DDrawer::DTM_Stencil == TM_MASK, "DTM_Stencil != TM_MASK"); + static_assert(F2DDrawer::DTM_AlphaTexture == TM_REDTOALPHA, "DTM_AlphaTexture != TM_REDTOALPHA"); + gl_RenderState.SetTextureMode(cmd.mDrawMode); + if (cmd.mFlags & F2DDrawer::DTF_Scissor) + { + glEnable(GL_SCISSOR_TEST); + // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates + glScissor( + GLRenderer->ScreenToWindowX(cmd.mScissor[0]), + GLRenderer->ScreenToWindowX(cmd.mScissor[1]), + GLRenderer->ScreenToWindowX(cmd.mScissor[2] - cmd.mScissor[0]), + GLRenderer->ScreenToWindowX(cmd.mScissor[3] - cmd.mScissor[1])); + } + else glDisable(GL_SCISSOR_TEST); + gl_RenderState.SetObjectColor(cmd.mColor1); + gl_RenderState.SetObjectColor2(cmd.mColor2); + + if (cmd.mFlags & F2DDrawer::DTF_IngameLighting) + { + gl_RenderState.SetFixedColormap(CM_INGAME2D); + } + else if (cmd.mFlags & F2DDrawer::DTF_SpecialColormap) + { + gl_RenderState.SetFixedColormap(CM_SPECIAL2D); + } + else + { + gl_RenderState.SetFixedColormap(CM_PLAIN2D); + } + + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + + switch (cmd.mType) + { + case F2DDrawer::DrawTypeTriangles: + if (cmd.mTexture != nullptr) + { + auto mat = FMaterial::ValidateTexture(cmd.mTexture, false); + if (mat == nullptr) continue; + int gltrans = GLTranslationPalette::GetInternalTranslation(cmd.mTranslation); + gl_RenderState.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, gltrans, -1, false); + gl_RenderState.EnableTexture(true); + } + else + { + gl_RenderState.EnableTexture(false); + } + gl_RenderState.Apply(); + glDrawElements(GL_TRIANGLES, cmd.mIndexCount, GL_UNSIGNED_INT, (const void *)(cmd.mIndexIndex * sizeof(unsigned int))); + break; + + case F2DDrawer::DrawTypeLines: + gl_RenderState.EnableTexture(false); + gl_RenderState.Apply(); + glDrawArrays(GL_LINES, cmd.mVertIndex, cmd.mVertCount); + gl_RenderState.EnableTexture(true); + break; + + case F2DDrawer::DrawTypePoints: + gl_RenderState.EnableTexture(false); + gl_RenderState.Apply(); + glDrawArrays(GL_POINTS, cmd.mVertIndex, cmd.mVertCount); + gl_RenderState.EnableTexture(true); + break; + + } + } + glDisable(GL_SCISSOR_TEST); + gl_RenderState.SetVertexBuffer(nullptr); + delete vb; +} \ No newline at end of file diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index fc913b45d..e5f420da4 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -190,6 +190,7 @@ public: void DrawPresentTexture(const GL_IRECT &box, bool applyGamma); void Flush(); void GetSpecialTextures(); + void Draw2D(F2DDrawer *data); bool StartOffscreen(); diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index b27a5de59..ed4d79658 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -233,6 +233,27 @@ bool FRenderState::ApplyShader() { activeShader->muFixedColormap.Set(0); } + else if (mColormapState == CM_PLAIN2D) + { + activeShader->muFixedColormap.Set(4); + } + else if (mColormapState == CM_INGAME2D) + { + activeShader->muFixedColormap.Set(5); + } + else if (mColormapState == CM_SPECIAL2D) + { + activeShader->muFixedColormap.Set(2); + activeShader->muFixedColormap.Set(1); + float startr = mObjectColor.r / 255; + float startg = mObjectColor.g / 255; + float startb = mObjectColor.b / 255; + float ranger = mObjectColor2.r / 255 - startr; + float rangeg = mObjectColor2.g / 255 - startg; + float rangeb = mObjectColor2.b / 255 - startb; + activeShader->muColormapStart.Set(startr, startg, startb, 0.f); + activeShader->muColormapRange.Set(ranger, rangeg, rangeb, 0.f); + } else if (mColormapState > CM_DEFAULT && mColormapState < CM_MAXCOLORMAP) { if (FGLRenderBuffers::IsEnabled()) diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 34a030f8a..8c4425c5c 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -144,7 +144,7 @@ public: void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture) { - // alpha textures need special treatment in the legacy renderer because withouz shaders they need a different texture. + // alpha textures need special treatment in the legacy renderer because without shaders they need a different texture. if (alphatexture && gl.legacyMode) translation = INT_MAX; if (mat->tex->bHasCanvas) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index f3687b1e7..66c3a7df2 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -473,3 +473,15 @@ void OpenGLFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y) x = int16_t((x - letterboxX) * Width / letterboxWidth); y = int16_t((y - letterboxY) * Height / letterboxHeight); } + +//=========================================================================== +// +// 2D drawing +// +//=========================================================================== + +void OpenGLFrameBuffer::Draw2D() +{ + //if (gl.legacyMode) Draw2DLegacy(); + if (GLRenderer != nullptr) GLRenderer->Draw2D(&m2DDrawer); +} diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 3b34b4104..8a270bb64 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -68,6 +68,7 @@ public: void SetVSync(bool vsync); void ScaleCoordsFromWindow(int16_t &x, int16_t &y) override; + void Draw2D() override; bool HWGammaActive = false; // Are we using hardware or software gamma? std::shared_ptr mDebug; // Debug API diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index a839e13b4..c68e5f6c2 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -35,8 +35,7 @@ enum TexMode TM_INVERSE, // (1-r, 1-g, 1-b, a) TM_REDTOALPHA, // (1, 1, 1, r) TM_CLAMPY, // (r, g, b, (t >= 0.0 && t <= 1.0)? a:0) - - TM_INVERTOPAQUE, // used by GL 2.x fallback code. + TM_INVERTOPAQUE, // (1-r, 1-g, 1-b, 1) }; enum ELightMethod diff --git a/src/gl/textures/gl_translate.cpp b/src/gl/textures/gl_translate.cpp index 20a58e22c..c775c50a6 100644 --- a/src/gl/textures/gl_translate.cpp +++ b/src/gl/textures/gl_translate.cpp @@ -62,14 +62,17 @@ bool GLTranslationPalette::Update() return true; } +int GLTranslationPalette::GetInternalTranslation(FRemapTable *remap) +{ + if (remap == nullptr || remap->Inactive) return 0; + + GLTranslationPalette *tpal = static_cast(remap->GetNative()); + if (tpal == nullptr) return 0; + return tpal->GetIndex(); +} + int GLTranslationPalette::GetInternalTranslation(int trans) { if (trans <= 0) return 0; - - FRemapTable *remap = TranslationToTable(trans); - if (remap == NULL || remap->Inactive) return 0; - - GLTranslationPalette *tpal = static_cast(remap->GetNative()); - if (tpal == NULL) return 0; - return tpal->GetIndex(); + return GetInternalTranslation(TranslationToTable(trans)); } diff --git a/src/gl/textures/gl_translate.h b/src/gl/textures/gl_translate.h index 07ede1a22..092f4d73e 100644 --- a/src/gl/textures/gl_translate.h +++ b/src/gl/textures/gl_translate.h @@ -30,6 +30,7 @@ public: static GLTranslationPalette *CreatePalette(FRemapTable *remap); static int GetInternalTranslation(int trans); + static int GetInternalTranslation(FRemapTable *trans); static PalEntry *GetPalette(unsigned int index) { return index > 0 && index <= AllPalettes.Size()? AllPalettes[index-1].pe : NULL; diff --git a/src/v_2ddrawer.h b/src/v_2ddrawer.h index 7c325c877..578f4498b 100644 --- a/src/v_2ddrawer.h +++ b/src/v_2ddrawer.h @@ -25,9 +25,9 @@ public: DTM_Normal = 0, DTM_Stencil = 1, DTM_Opaque = 2, - DTM_AlphaTexture = 3, - DTM_Invert = 4, - DTM_InvertOpaque = 5, + DTM_Invert = 3, + DTM_AlphaTexture = 4, + DTM_InvertOpaque = 6, }; enum ETextureFlags : uint8_t diff --git a/src/v_video.h b/src/v_video.h index 56d62f799..8c69dbdc1 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -287,9 +287,8 @@ public: class DFrameBuffer { typedef DSimpleCanvas Super; - F2DDrawer m2DDrawer; - protected: + void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete; void DrawTextureParms(FTexture *img, DrawParms &parms); @@ -297,6 +296,7 @@ protected: bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const; void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms); + F2DDrawer m2DDrawer; int Width = 0; int Height = 0; bool Bgra = 0; diff --git a/wadsrc/static/shaders/d3d/shaders.ps b/wadsrc/static/shaders/d3d/shaders.ps index 4f1e0e221..5d53f9bf8 100644 --- a/wadsrc/static/shaders/d3d/shaders.ps +++ b/wadsrc/static/shaders/d3d/shaders.ps @@ -37,18 +37,18 @@ float4 SampleTexture(float2 tex_coord) // Normal color calculation for most drawing modes. -float4 NormalColor(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR +float4 NormalColor(float2 tex_coord : TEXCOORD0, float4 VertexColor : COLOR0, float4 Overlay : COLOR1) : COLOR { - return Flash + SampleTexture(tex_coord) * InvFlash; + return Overlay + SampleTexture(tex_coord) * VertexColor; } -// Copy the red channel to the alpha channel. Pays no attention to palettes. +// Copy the red channel to the alpha channel. Pays no attention to palettes and only works with grayscale textures -float4 RedToAlpha(float2 tex_coord : TEXCOORD0, float4 Flash : COLOR0, float4 InvFlash : COLOR1) : COLOR +float4 RedToAlpha(float2 tex_coord : TEXCOORD0, float4 VertexColor : COLOR0, float4 Overlay : COLOR1) : COLOR { float4 color = Invert(tex2D(Image, tex_coord)); - color.a = color.r; - return Flash + color * InvFlash; + color.a *= color.r; + return Overlay + color * VertexColor; } // Just return the value of c0. @@ -87,12 +87,12 @@ float4 InGameColormap(float2 tex_coord : TEXCOORD0, float4 color : COLOR0, float rgb.rgb = intensity.rgb + rgb.rgb * Desaturation.y; #endif - // Fade - rgb.rgb = rgb.rgb * fade.aaa + fade.rgb; - // Shade and Alpha rgb = rgb * color; + // Fade + rgb.rgb = rgb.rgb * fade.aaa + fade.rgb; + return rgb; }