diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4973eb1c3..a4a1e0faa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1067,6 +1067,7 @@ set (PCH_SOURCES hwrenderer/textures/hw_precache.cpp hwrenderer/utility/hw_clock.cpp hwrenderer/utility/hw_cvars.cpp + hwrenderer/utility/hw_draw2d.cpp hwrenderer/utility/hw_lighting.cpp hwrenderer/utility/hw_shaderpatcher.cpp hwrenderer/utility/hw_vrmodes.cpp diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 493aa6c8b..da876c1d0 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -379,195 +379,3 @@ void FGLRenderer::BeginFrame() mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); } -//=========================================================================== -// -// Vertex buffer for 2D drawer -// -//=========================================================================== - -class F2DVertexBuffer -{ - IVertexBuffer *mVertexBuffer; - IIndexBuffer *mIndexBuffer; - - -public: - - F2DVertexBuffer() - { - mVertexBuffer = screen->CreateVertexBuffer(); - mIndexBuffer = screen->CreateIndexBuffer(); - - static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, myoffsetof(F2DDrawer::TwoDVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, myoffsetof(F2DDrawer::TwoDVertex, u) }, - { 0, VATTR_COLOR, VFmt_Byte4, myoffsetof(F2DDrawer::TwoDVertex, color0) } - }; - mVertexBuffer->SetFormat(1, 3, sizeof(FSkyVertex), format); - } - ~F2DVertexBuffer() - { - delete mIndexBuffer; - delete mVertexBuffer; - } - - void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount) - { - mVertexBuffer->SetData(vertcount * sizeof(*vertices), vertices, false); - mIndexBuffer->SetData(indexcount * sizeof(unsigned int), indices, false); - } - - void Bind(FRenderState &state) - { - state.SetVertexBuffer(mVertexBuffer, 0, 0); - state.SetIndexBuffer(mIndexBuffer); - } -}; - -//=========================================================================== -// -// Draws the 2D stuff. This is the version for OpenGL 3 and later. -// -//=========================================================================== - -CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE) - -void FGLRenderer::Draw2D(F2DDrawer *drawer) -{ - twoD.Clock(); - FGLDebug::PushGroup("Draw2D"); - if (VRMode::GetVRMode(true)->mEyeCount == 1) - mBuffers->BindCurrentFB(); - - const auto &mScreenViewport = screen->mScreenViewport; - glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); - screen->mViewpoints->Set2D(gl_RenderState, screen->GetWidth(), screen->GetHeight()); - - glDisable(GL_DEPTH_TEST); - - // Korshun: ENABLE AUTOMAP ANTIALIASING!!! - if (gl_aalines) - glEnable(GL_LINE_SMOOTH); - else - { - glDisable(GL_MULTISAMPLE); - glDisable(GL_LINE_SMOOTH); - glLineWidth(1.0); - } - - - auto &vertices = drawer->mVertices; - auto &indices = drawer->mIndices; - auto &commands = drawer->mData; - - if (commands.Size() == 0) - { - twoD.Unclock(); - return; - } - - for (auto &v : vertices) - { - // Change from BGRA to RGBA - std::swap(v.color0.r, v.color0.b); - } - F2DVertexBuffer vb; - vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size()); - vb.Bind(gl_RenderState); - gl_RenderState.EnableFog(false); - - for(auto &cmd : commands) - { - - int gltrans = -1; - gl_RenderState.SetRenderStyle(cmd.mRenderStyle); - gl_RenderState.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed)); - gl_RenderState.EnableFog(2); // Special 2D mode 'fog'. - - // Rather than adding remapping code, let's enforce that the constants here are equal. - 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 - // Note that the origin here is the lower left corner! - auto sciX = screen->ScreenToWindowX(cmd.mScissor[0]); - auto sciY = screen->ScreenToWindowY(cmd.mScissor[3]); - auto sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX; - auto sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY; - glScissor(sciX, sciY, sciW, sciH); - } - else glDisable(GL_SCISSOR_TEST); - - if (cmd.mSpecialColormap[0].a != 0) - { - gl_RenderState.SetTextureMode(TM_FIXEDCOLORMAP); - gl_RenderState.SetObjectColor(cmd.mSpecialColormap[0]); - gl_RenderState.SetObjectColor2(cmd.mSpecialColormap[1]); - } - gl_RenderState.SetFog(cmd.mColor1, 0); - gl_RenderState.SetColor(1, 1, 1, 1, cmd.mDesaturate); - - gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); - - if (cmd.mTexture != nullptr) - { - auto mat = FMaterial::ValidateTexture(cmd.mTexture, false); - if (mat == nullptr) continue; - - if (gltrans == -1 && cmd.mTranslation != nullptr) gltrans = cmd.mTranslation->GetUniqueIndex(); - gl_RenderState.ApplyMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, -gltrans, -1); - gl_RenderState.EnableTexture(true); - - // Canvas textures are stored upside down - if (cmd.mTexture->bHasCanvas) - { - gl_RenderState.mTextureMatrix.loadIdentity(); - gl_RenderState.mTextureMatrix.scale(1.f, -1.f, 1.f); - gl_RenderState.mTextureMatrix.translate(0.f, 1.f, 0.0f); - gl_RenderState.EnableTextureMatrix(true); - } - if (cmd.mFlags & F2DDrawer::DTF_Burn) - { - gl_RenderState.SetEffect(EFF_BURN); - } - } - else - { - gl_RenderState.EnableTexture(false); - } - gl_RenderState.Apply(); - - switch (cmd.mType) - { - case F2DDrawer::DrawTypeTriangles: - glDrawElements(GL_TRIANGLES, cmd.mIndexCount, GL_UNSIGNED_INT, (const void *)(cmd.mIndexIndex * sizeof(unsigned int))); - break; - - case F2DDrawer::DrawTypeLines: - glDrawArrays(GL_LINES, cmd.mVertIndex, cmd.mVertCount); - break; - - case F2DDrawer::DrawTypePoints: - glDrawArrays(GL_POINTS, cmd.mVertIndex, cmd.mVertCount); - break; - - } - gl_RenderState.SetObjectColor(0xffffffff); - gl_RenderState.SetObjectColor2(0); - gl_RenderState.EnableTextureMatrix(false); - gl_RenderState.SetEffect(EFF_NONE); - - } - glDisable(GL_SCISSOR_TEST); - - gl_RenderState.SetRenderStyle(STYLE_Translucent); - screen->mVertexData->Bind(gl_RenderState); - gl_RenderState.EnableTexture(true); - gl_RenderState.EnableBrightmap(true); - gl_RenderState.SetTextureMode(TM_NORMAL); - gl_RenderState.EnableFog(false); - gl_RenderState.ResetColor(); - FGLDebug::PopGroup(); - twoD.Unclock(); -} diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 5a6ab35ca..0ab59de0e 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -388,10 +388,9 @@ static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TR void FGLRenderState::Draw(int dt, int index, int count, bool apply) { - assert(this == &gl_RenderState); if (apply) { - gl_RenderState.Apply(); + Apply(); } drawcalls.Clock(); glDrawArrays(dt2gl[dt], index, count); @@ -400,10 +399,9 @@ void FGLRenderState::Draw(int dt, int index, int count, bool apply) void FGLRenderState::DrawIndexed(int dt, int index, int count, bool apply) { - assert(this == &gl_RenderState); if (apply) { - gl_RenderState.Apply(); + Apply(); } drawcalls.Clock(); glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t))); @@ -428,7 +426,7 @@ void FGLRenderState::SetDepthRange(float min, float max) void FGLRenderState::EnableDrawBufferAttachments(bool on) { - EnableDrawBuffers(on ? gl_RenderState.GetPassDrawBufferCount() : 1); + EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1); } void FGLRenderState::SetStencil(int offs, int op, int flags) @@ -443,6 +441,18 @@ void FGLRenderState::SetStencil(int offs, int op, int flags) glDepthMask(!(flags & SF_DepthMaskOff)); } +void FGLRenderState::ToggleState(int state, bool on) +{ + if (on) + { + glEnable(state); + } + else + { + glDisable(state); + } +} + void FGLRenderState::SetCulling(int mode) { if (mode != Cull_None) @@ -461,14 +471,7 @@ void FGLRenderState::EnableClipDistance(int num, bool state) // Update the viewpoint-related clip plane setting. if (!(gl.flags & RFL_NO_CLIP_PLANES)) { - if (state) - { - glEnable(GL_CLIP_DISTANCE0 + num); - } - else - { - glDisable(GL_CLIP_DISTANCE0 + num); - } + ToggleState(GL_CLIP_DISTANCE0 + num, state); } } @@ -496,14 +499,7 @@ void FGLRenderState::Clear(int targets) void FGLRenderState::EnableStencil(bool on) { - if (on) - { - glEnable(GL_STENCIL_TEST); - } - else - { - glDisable(GL_STENCIL_TEST); - } + ToggleState(GL_STENCIL_TEST, on); } void FGLRenderState::SetScissor(int x, int y, int w, int h) @@ -526,26 +522,17 @@ void FGLRenderState::SetViewport(int x, int y, int w, int h) void FGLRenderState::EnableDepthTest(bool on) { - if (on) - { - glEnable(GL_DEPTH_TEST); - } - else - { - glDisable(GL_DEPTH_TEST); - } + ToggleState(GL_DEPTH_TEST, on); } void FGLRenderState::EnableMultisampling(bool on) { - if (on) - { - glEnable(GL_MULTISAMPLE); - } - else - { - glDisable(GL_MULTISAMPLE); - } + ToggleState(GL_MULTISAMPLE, on); +} + +void FGLRenderState::EnableLineSmooth(bool on) +{ + ToggleState(GL_LINE_SMOOTH, on); } //========================================================================== diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 8c61451ec..6a3ec724c 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -140,6 +140,8 @@ public: return mPassType == GBUFFER_PASS ? 3 : 1; } + void ToggleState(int state, bool on); + void ClearScreen() override; void Draw(int dt, int index, int count, bool apply = true) override; void DrawIndexed(int dt, int index, int count, bool apply = true) override; @@ -158,6 +160,7 @@ public: void SetViewport(int x, int y, int w, int h) override; void EnableDepthTest(bool on) override; void EnableMultisampling(bool on) override; + void EnableLineSmooth(bool on) override; }; diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index c20d727ef..d31f11c78 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -56,6 +56,8 @@ FGLRenderer *GLRenderer; void gl_LoadExtensions(); void gl_PrintStartupLog(); +void Draw2D(F2DDrawer *drawer, FRenderState &state); + CUSTOM_CVAR(Int, vid_hwgamma, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) { @@ -480,7 +482,15 @@ void OpenGLFrameBuffer::GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, void OpenGLFrameBuffer::Draw2D() { - if (GLRenderer != nullptr) GLRenderer->Draw2D(&m2DDrawer); + if (GLRenderer != nullptr) + { + FGLDebug::PushGroup("Draw2D"); + if (VRMode::GetVRMode(true)->mEyeCount == 1) + GLRenderer->mBuffers->BindCurrentFB(); + + ::Draw2D(&m2DDrawer, gl_RenderState); + FGLDebug::PopGroup(); + } } void OpenGLFrameBuffer::PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) diff --git a/src/hwrenderer/scene/hw_drawinfo.h b/src/hwrenderer/scene/hw_drawinfo.h index fa248a938..2fa6ee3b5 100644 --- a/src/hwrenderer/scene/hw_drawinfo.h +++ b/src/hwrenderer/scene/hw_drawinfo.h @@ -17,44 +17,6 @@ enum EDrawMode DM_SKYPORTAL }; - -enum EDrawType -{ - DT_Points = 0, - DT_Lines = 1, - DT_Triangles = 2, - DT_TriangleFan = 3, - DT_TriangleStrip = 4 -}; - -enum EDepthFunc -{ - DF_Less, - DF_LEqual, - DF_Always -}; - -enum EStencilFlags -{ - SF_AllOn = 0, - SF_ColorMaskOff = 1, - SF_DepthMaskOff = 2, -}; - -enum EStencilOp -{ - SOP_Keep = 0, - SOP_Increment = 1, - SOP_Decrement = 2 -}; - -enum ECull -{ - Cull_None, - Cull_CCW, - Cull_CW -}; - struct FSectorPortalGroup; struct FLinePortalSpan; struct FFlatVertex; diff --git a/src/hwrenderer/scene/hw_renderstate.h b/src/hwrenderer/scene/hw_renderstate.h index 45349497a..52a053d46 100644 --- a/src/hwrenderer/scene/hw_renderstate.h +++ b/src/hwrenderer/scene/hw_renderstate.h @@ -36,6 +36,45 @@ enum EAlphaFunc Alpha_Greater = 1 }; +enum EDrawType +{ + DT_Points = 0, + DT_Lines = 1, + DT_Triangles = 2, + DT_TriangleFan = 3, + DT_TriangleStrip = 4 +}; + +enum EDepthFunc +{ + DF_Less, + DF_LEqual, + DF_Always +}; + +enum EStencilFlags +{ + SF_AllOn = 0, + SF_ColorMaskOff = 1, + SF_DepthMaskOff = 2, +}; + +enum EStencilOp +{ + SOP_Keep = 0, + SOP_Increment = 1, + SOP_Decrement = 2 +}; + +enum ECull +{ + Cull_None, + Cull_CCW, + Cull_CW +}; + + + struct FStateVec4 { float vec[4]; @@ -453,6 +492,7 @@ public: virtual void SetViewport(int x, int y, int w, int h) = 0; virtual void EnableDepthTest(bool on) = 0; virtual void EnableMultisampling(bool on) = 0; + virtual void EnableLineSmooth(bool on) = 0; }; diff --git a/src/hwrenderer/utility/hw_draw2d.cpp b/src/hwrenderer/utility/hw_draw2d.cpp new file mode 100644 index 000000000..6abadb682 --- /dev/null +++ b/src/hwrenderer/utility/hw_draw2d.cpp @@ -0,0 +1,222 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2018 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** 2d drawer +** Renderer interface +** +*/ + +#include "doomstat.h" +#include "v_video.h" +#include "cmdlib.h" +#include "r_defs.h" +#include "hwrenderer/data/buffers.h" +#include "hwrenderer/data/flatvertices.h" +#include "hwrenderer/data/hw_viewpointbuffer.h" +#include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/utility/hw_cvars.h" +#include "hwrenderer/scene/hw_renderstate.h" +#include "r_videoscale.h" + + +//=========================================================================== +// +// Vertex buffer for 2D drawer +// +//=========================================================================== + +class F2DVertexBuffer +{ + IVertexBuffer *mVertexBuffer; + IIndexBuffer *mIndexBuffer; + + +public: + + F2DVertexBuffer() + { + mVertexBuffer = screen->CreateVertexBuffer(); + mIndexBuffer = screen->CreateIndexBuffer(); + + static const FVertexBufferAttribute format[] = { + { 0, VATTR_VERTEX, VFmt_Float3, myoffsetof(F2DDrawer::TwoDVertex, x) }, + { 0, VATTR_TEXCOORD, VFmt_Float2, myoffsetof(F2DDrawer::TwoDVertex, u) }, + { 0, VATTR_COLOR, VFmt_Byte4, myoffsetof(F2DDrawer::TwoDVertex, color0) } + }; + mVertexBuffer->SetFormat(1, 3, sizeof(F2DDrawer::TwoDVertex), format); + } + ~F2DVertexBuffer() + { + delete mIndexBuffer; + delete mVertexBuffer; + } + + void UploadData(F2DDrawer::TwoDVertex *vertices, int vertcount, int *indices, int indexcount) + { + mVertexBuffer->SetData(vertcount * sizeof(*vertices), vertices, false); + mIndexBuffer->SetData(indexcount * sizeof(unsigned int), indices, false); + } + + void Bind(FRenderState &state) + { + state.SetVertexBuffer(mVertexBuffer, 0, 0); + state.SetIndexBuffer(mIndexBuffer); + } +}; + +//=========================================================================== +// +// Draws the 2D stuff. This is the version for OpenGL 3 and later. +// +//=========================================================================== + +CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE) + +void Draw2D(F2DDrawer *drawer, FRenderState &state) +{ + twoD.Clock(); + + const auto &mScreenViewport = screen->mScreenViewport; + state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); + screen->mViewpoints->Set2D(state, screen->GetWidth(), screen->GetHeight()); + + state.EnableDepthTest(false); + state.EnableMultisampling(false); + state.EnableLineSmooth(gl_aalines); + + auto &vertices = drawer->mVertices; + auto &indices = drawer->mIndices; + auto &commands = drawer->mData; + + if (commands.Size() == 0) + { + twoD.Unclock(); + return; + } + + for (auto &v : vertices) + { + // Change from BGRA to RGBA + std::swap(v.color0.r, v.color0.b); + } + F2DVertexBuffer vb; + vb.UploadData(&vertices[0], vertices.Size(), &indices[0], indices.Size()); + vb.Bind(state); + state.EnableFog(false); + + for(auto &cmd : commands) + { + + int gltrans = -1; + state.SetRenderStyle(cmd.mRenderStyle); + state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed)); + state.EnableFog(2); // Special 2D mode 'fog'. + + // Rather than adding remapping code, let's enforce that the constants here are equal. + state.SetTextureMode(cmd.mDrawMode); + + int sciX, sciY, sciW, sciH; + if (cmd.mFlags & F2DDrawer::DTF_Scissor) + { + // scissor test doesn't use the current viewport for the coordinates, so use real screen coordinates + // Note that the origin here is the lower left corner! + sciX = screen->ScreenToWindowX(cmd.mScissor[0]); + sciY = screen->ScreenToWindowY(cmd.mScissor[3]); + sciW = screen->ScreenToWindowX(cmd.mScissor[2]) - sciX; + sciH = screen->ScreenToWindowY(cmd.mScissor[1]) - sciY; + } + else + { + sciX = sciY = sciW = sciH = -1; + } + state.SetScissor(sciX, sciY, sciW, sciH); + + if (cmd.mSpecialColormap[0].a != 0) + { + state.SetTextureMode(TM_FIXEDCOLORMAP); + state.SetObjectColor(cmd.mSpecialColormap[0]); + state.SetObjectColor2(cmd.mSpecialColormap[1]); + } + state.SetFog(cmd.mColor1, 0); + state.SetColor(1, 1, 1, 1, cmd.mDesaturate); + + state.AlphaFunc(Alpha_GEqual, 0.f); + + if (cmd.mTexture != nullptr) + { + auto mat = FMaterial::ValidateTexture(cmd.mTexture, false); + if (mat == nullptr) continue; + + if (gltrans == -1 && cmd.mTranslation != nullptr) gltrans = cmd.mTranslation->GetUniqueIndex(); + state.SetMaterial(mat, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, -gltrans, -1); + state.EnableTexture(true); + + // Canvas textures are stored upside down + if (cmd.mTexture->bHasCanvas) + { + state.mTextureMatrix.loadIdentity(); + state.mTextureMatrix.scale(1.f, -1.f, 1.f); + state.mTextureMatrix.translate(0.f, 1.f, 0.0f); + state.EnableTextureMatrix(true); + } + if (cmd.mFlags & F2DDrawer::DTF_Burn) + { + state.SetEffect(EFF_BURN); + } + } + else + { + state.EnableTexture(false); + } + + switch (cmd.mType) + { + case F2DDrawer::DrawTypeTriangles: + state.DrawIndexed(DT_Triangles, cmd.mIndexIndex, cmd.mIndexCount); + break; + + case F2DDrawer::DrawTypeLines: + state.Draw(DT_Lines, cmd.mVertIndex, cmd.mVertCount); + break; + + case F2DDrawer::DrawTypePoints: + state.Draw(DT_Points, cmd.mVertIndex, cmd.mVertCount); + break; + + } + state.SetObjectColor(0xffffffff); + state.SetObjectColor2(0); + state.EnableTextureMatrix(false); + state.SetEffect(EFF_NONE); + + } + state.SetScissor(-1, -1, -1, -1); + + state.SetRenderStyle(STYLE_Translucent); + screen->mVertexData->Bind(state); + state.EnableTexture(true); + state.EnableBrightmap(true); + state.SetTextureMode(TM_NORMAL); + state.EnableFog(false); + state.ResetColor(); + twoD.Unclock(); +}