From 3940f179804bb8dd83d921f18093292c4de3d2dd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 25 Oct 2018 00:25:55 +0200 Subject: [PATCH] - portals are now completely on the hwrenderer side. The only thing that still needs to be on the backend side is the one function that manages the rendering. --- src/CMakeLists.txt | 3 +- src/gl/data/gl_vertexbuffer.cpp | 25 +++ src/gl/data/gl_vertexbuffer.h | 2 - src/gl/models/gl_models.cpp | 1 - src/gl/renderer/gl_renderer.cpp | 1 - src/gl/renderer/gl_renderstate.cpp | 6 + src/gl/renderer/gl_renderstate.h | 3 + src/gl/scene/gl_drawinfo.cpp | 4 +- src/gl/scene/gl_portal.cpp | 252 ----------------------- src/gl/scene/gl_portal.h | 111 ----------- src/gl/scene/gl_scene.cpp | 2 +- src/gl/scene/gl_skydome.cpp | 274 -------------------------- src/gl/scene/gl_walls_draw.cpp | 7 +- src/hwrenderer/scene/hw_portal.cpp | 199 ++++++++++++++++++- src/hwrenderer/scene/hw_portal.h | 74 ++++++- src/hwrenderer/scene/hw_renderstate.h | 8 + src/hwrenderer/scene/hw_skydome.h | 2 + src/hwrenderer/scene/hw_skyportal.cpp | 223 +++++++++++++++++++++ 18 files changed, 544 insertions(+), 653 deletions(-) delete mode 100644 src/gl/scene/gl_portal.cpp delete mode 100644 src/gl/scene/gl_portal.h delete mode 100644 src/gl/scene/gl_skydome.cpp create mode 100644 src/hwrenderer/scene/hw_skyportal.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3cf31ef78..a798ad5380 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -821,9 +821,7 @@ set( FASTMATH_SOURCES textures/hires/xbr/xbrz.cpp textures/hires/xbr/xbrz_old.cpp gl/scene/gl_drawinfo.cpp - gl/scene/gl_skydome.cpp gl/scene/gl_scene.cpp - gl/scene/gl_portal.cpp gl/scene/gl_walls_draw.cpp gl_load/gl_load.c hwrenderer/postprocessing/hw_postprocess_cvars.cpp @@ -840,6 +838,7 @@ set( FASTMATH_SOURCES hwrenderer/scene/hw_renderhacks.cpp hwrenderer/scene/hw_renderstate.cpp hwrenderer/scene/hw_sky.cpp + hwrenderer/scene/hw_skyportal.cpp hwrenderer/scene/hw_sprites.cpp hwrenderer/scene/hw_spritelight.cpp hwrenderer/scene/hw_walls.cpp diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index 27ab111987..dfe55cf505 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -90,6 +90,31 @@ void FSimpleVertexBuffer::set(FSimpleVertex *verts, int count) glBufferData(GL_ARRAY_BUFFER, count * sizeof(*verts), verts, GL_STREAM_DRAW); } +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +FSkyVertexBuffer::FSkyVertexBuffer() +{ + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glBufferData(GL_ARRAY_BUFFER, mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], GL_STATIC_DRAW); +} + +void FSkyVertexBuffer::BindVBO() +{ + glBindBuffer(GL_ARRAY_BUFFER, vbo_id); + glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->x); + glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->u); + glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSkyVertex), &VSO->color); + glEnableVertexAttribArray(VATTR_VERTEX); + glEnableVertexAttribArray(VATTR_TEXCOORD); + glEnableVertexAttribArray(VATTR_COLOR); + glDisableVertexAttribArray(VATTR_VERTEX2); + glDisableVertexAttribArray(VATTR_NORMAL); +} + //========================================================================== // // diff --git a/src/gl/data/gl_vertexbuffer.h b/src/gl/data/gl_vertexbuffer.h index b97e69db9f..5393e20685 100644 --- a/src/gl/data/gl_vertexbuffer.h +++ b/src/gl/data/gl_vertexbuffer.h @@ -186,12 +186,10 @@ public: class FSkyVertexBuffer : public FVertexBuffer, public FSkyDomeCreator { - void RenderRow(int prim, int row); public: FSkyVertexBuffer(); - void RenderDome(FMaterial *tex, int mode); void BindVBO(); }; diff --git a/src/gl/models/gl_models.cpp b/src/gl/models/gl_models.cpp index 2eabff2a3b..1e793c7064 100644 --- a/src/gl/models/gl_models.cpp +++ b/src/gl/models/gl_models.cpp @@ -40,7 +40,6 @@ #include "gl_load/gl_interface.h" #include "gl/renderer/gl_renderer.h" #include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" #include "gl/models/gl_models.h" #include "gl/renderer/gl_renderstate.h" #include "gl/shaders/gl_shader.h" diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index b9d47bbb45..b8b09c7724 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -42,7 +42,6 @@ #include "gl_load/gl_interface.h" #include "gl/system/gl_framebuffer.h" #include "hwrenderer/utility/hw_cvars.h" -#include "gl/scene/gl_portal.h" #include "gl/system/gl_debug.h" #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderstate.h" diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 4cc432f3a3..56321e6bc2 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -362,3 +362,9 @@ void FGLRenderState::ApplyBlendMode() } } + +// Needs to be redone +void FGLRenderState::SetVertexBuffer(int which) +{ + SetVertexBuffer(which == VB_Sky ? (FVertexBuffer*)GLRenderer->mSkyVBO : GLRenderer->mVBO); +} diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 9ff961871a..f535dbe955 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -186,6 +186,9 @@ public: { return mPassType == GBUFFER_PASS ? 3 : 1; } + + + void SetVertexBuffer(int which) override; }; extern FGLRenderState gl_RenderState; diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index f85bfb8106..88f57ef4bb 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -38,8 +38,8 @@ #include "gl/data/gl_vertexbuffer.h" #include "gl/scene/gl_drawinfo.h" #include "hwrenderer/scene/hw_clipper.h" -#include "gl/scene/gl_portal.h" #include "gl/renderer/gl_renderstate.h" +#include "gl/renderer/gl_renderer.h" #include "gl/data/gl_viewpointbuffer.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/models/gl_models.h" @@ -318,7 +318,7 @@ void FDrawInfo::RenderPortal(HWPortal *p, bool usestencil) gp->SetupStencil(this, gl_RenderState, usestencil); auto new_di = StartDrawInfo(Viewpoint, &VPUniforms); new_di->mCurrentPortal = gp; - gp->DrawContents(new_di); + gp->DrawContents(new_di, gl_RenderState); new_di->EndDrawInfo(); GLRenderer->mViewpoints->Bind(vpIndex); gp->RemoveStencil(this, gl_RenderState, usestencil); diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp deleted file mode 100644 index 91849c45be..0000000000 --- a/src/gl/scene/gl_portal.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2004-2016 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/ -// -//-------------------------------------------------------------------------- -// -/* -** gl_portal.cpp -** Generalized portal maintenance classes for skyboxes, horizons etc. -** -*/ - -#include "gl_load/gl_system.h" -#include "p_local.h" -#include "c_dispatch.h" -#include "doomstat.h" -#include "a_sharedglobal.h" -#include "r_sky.h" -#include "p_maputl.h" -#include "d_player.h" -#include "g_levellocals.h" - -#include "gl_load/gl_interface.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_renderstate.h" -#include "gl/data/gl_vertexbuffer.h" -#include "hwrenderer/scene/hw_clipper.h" -#include "gl/scene/gl_portal.h" -#include "gl/data/gl_viewpointbuffer.h" -#include "hwrenderer/utility/hw_lighting.h" - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// -// -// General portal handling code -// -// -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -EXTERN_CVAR(Int, r_mirror_recursions) - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// -// -// Horizon Portal -// -// -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -GLHorizonPortal::GLHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local) - : HWPortal(s, local) -{ - origin = pt; - - // create the vertex data for this horizon portal. - GLSectorPlane * sp = &origin->plane; - const float vx = vp.Pos.X; - const float vy = vp.Pos.Y; - const float vz = vp.Pos.Z; - const float z = sp->Texheight; - const float tz = (z - vz); - - // Draw to some far away boundary - // This is not drawn as larger strips because it causes visual glitches. - FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer(); - for (int xx = -32768; xx < 32768; xx += 4096) - { - float x = xx + vx; - for (int yy = -32768; yy < 32768; yy += 4096) - { - float y = yy + vy; - ptr->Set(x, z, y, x / 64, -y / 64); - ptr++; - ptr->Set(x + 4096, z, y, x / 64 + 64, -y / 64); - ptr++; - ptr->Set(x, z, y + 4096, x / 64, -y / 64 - 64); - ptr++; - ptr->Set(x + 4096, z, y + 4096, x / 64 + 64, -y / 64 - 64); - ptr++; - } - } - - // fill the gap between the polygon and the true horizon - // Since I can't draw into infinity there can always be a - // small gap - ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); - ptr++; - ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); - ptr++; - ptr->Set(-32768 + vx, z, 32768 + vy, -512.f, 0); - ptr++; - ptr->Set(-32768 + vx, vz, 32768 + vy, -512.f, tz); - ptr++; - ptr->Set(32768 + vx, z, 32768 + vy, 512.f, 0); - ptr++; - ptr->Set(32768 + vx, vz, 32768 + vy, 512.f, tz); - ptr++; - ptr->Set(32768 + vx, z, -32768 + vy, -512.f, 0); - ptr++; - ptr->Set(32768 + vx, vz, -32768 + vy, -512.f, tz); - ptr++; - ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); - ptr++; - ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); - ptr++; - - vcount = GLRenderer->mVBO->GetCount(ptr, &voffset) - 10; - -} - -//----------------------------------------------------------------------------- -// -// GLHorizonPortal::DrawContents -// -//----------------------------------------------------------------------------- -void GLHorizonPortal::DrawContents(HWDrawInfo *hwdi) -{ - auto di = static_cast(hwdi); - Clocker c(PortalAll); - - FMaterial * gltexture; - player_t * player=&players[consoleplayer]; - GLSectorPlane * sp = &origin->plane; - auto &vp = di->Viewpoint; - - gltexture=FMaterial::ValidateTexture(sp->texture, false, true); - if (!gltexture) - { - di->ClearScreen(); - return; - } - di->SetCameraPos(vp.Pos); - - - if (gltexture && gltexture->tex->isFullbright()) - { - // glowing textures are always drawn full bright without color - di->SetColor(255, 0, origin->colormap, 1.f); - di->SetFog(255, 0, &origin->colormap, false); - } - else - { - int rel = getExtraLight(); - di->SetColor(origin->lightlevel, rel, origin->colormap, 1.0f); - di->SetFog(origin->lightlevel, rel, &origin->colormap, false); - } - - - gl_RenderState.ApplyMaterial(gltexture, CLAMP_NONE, 0, -1); - gl_RenderState.SetObjectColor(origin->specialcolor); - - gl_RenderState.SetPlaneTextureRotation(sp, gltexture); - gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); - gl_RenderState.SetRenderStyle(STYLE_Source); - gl_RenderState.Apply(); - - - for (unsigned i = 0; i < vcount; i += 4) - { - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, voffset + i, 4); - } - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, voffset + vcount, 10); - - gl_RenderState.EnableTextureMatrix(false); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// -// -// Eternity-style horizon portal -// -// To the rest of the engine these masquerade as a skybox portal -// Internally they need to draw two horizon or sky portals -// and will use the respective classes to achieve that. -// -// -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void GLEEHorizonPortal::DrawContents(HWDrawInfo *di) -{ - auto &vp = di->Viewpoint; - sector_t *sector = portal->mOrigin; - if (sector->GetTexture(sector_t::floor) == skyflatnum || - sector->GetTexture(sector_t::ceiling) == skyflatnum) - { - GLSkyInfo skyinfo; - skyinfo.init(sector->sky, 0); - GLSkyPortal sky(mState, &skyinfo, true); - sky.DrawContents(di); - } - if (sector->GetTexture(sector_t::ceiling) != skyflatnum) - { - GLHorizonInfo horz; - horz.plane.GetFromSector(sector, sector_t::ceiling); - horz.lightlevel = hw_ClampLight(sector->GetCeilingLight()); - horz.colormap = sector->Colormap; - horz.specialcolor = 0xffffffff; - if (portal->mType == PORTS_PLANE) - { - horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight); - } - GLHorizonPortal ceil(mState, &horz, di->Viewpoint, true); - ceil.DrawContents(di); - } - if (sector->GetTexture(sector_t::floor) != skyflatnum) - { - GLHorizonInfo horz; - horz.plane.GetFromSector(sector, sector_t::floor); - horz.lightlevel = hw_ClampLight(sector->GetFloorLight()); - horz.colormap = sector->Colormap; - horz.specialcolor = 0xffffffff; - if (portal->mType == PORTS_PLANE) - { - horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight); - } - GLHorizonPortal floor(mState, &horz, di->Viewpoint, true); - floor.DrawContents(di); - } -} - -const char *GLSkyPortal::GetName() { return "Sky"; } -const char *GLHorizonPortal::GetName() { return "Horizon"; } -const char *GLEEHorizonPortal::GetName() { return "EEHorizon"; } - diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h deleted file mode 100644 index 6da1aececa..0000000000 --- a/src/gl/scene/gl_portal.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -** gl_renderstruct.h -** Generalized portal maintenance classes to make rendering special effects easier -** and help add future extensions -** -**--------------------------------------------------------------------------- -** Copyright 2002-2005 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __GL_PORTAL_H -#define __GL_PORTAL_H - -#include "tarray.h" -#include "r_utility.h" -#include "actor.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/scene/gl_drawinfo.h" -#include "hwrenderer/scene/hw_drawstructs.h" -#include "hwrenderer/scene/hw_portal.h" - -struct GLEEHorizonPortal; - -struct GLSkyPortal : public HWPortal -{ - GLSkyInfo * origin; - friend struct GLEEHorizonPortal; - -protected: - virtual void DrawContents(HWDrawInfo *di); - virtual void * GetSource() const { return origin; } - virtual bool IsSky() { return true; } - virtual bool NeedDepthBuffer() { return false; } - virtual const char *GetName(); - -public: - - - GLSkyPortal(FPortalSceneState *state, GLSkyInfo * pt, bool local = false) - : HWPortal(state, local) - { - origin=pt; - } - -}; - -struct GLHorizonPortal : public HWPortal -{ - GLHorizonInfo * origin; - unsigned int voffset; - unsigned int vcount; - friend struct GLEEHorizonPortal; - -protected: - virtual void DrawContents(HWDrawInfo *di); - virtual void * GetSource() const { return origin; } - virtual bool NeedDepthBuffer() { return false; } - virtual bool NeedCap() { return false; } - virtual const char *GetName(); - -public: - - GLHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false); -}; - -struct GLEEHorizonPortal : public HWPortal -{ - FSectorPortal * portal; - -protected: - virtual void DrawContents(HWDrawInfo *di); - virtual void * GetSource() const { return portal; } - virtual bool NeedDepthBuffer() { return false; } - virtual bool NeedCap() { return false; } - virtual const char *GetName(); - -public: - - GLEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : HWPortal(state, false) - { - portal=pt; - } - -}; - -#endif diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 292b94b58f..942f8a4a17 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -53,8 +53,8 @@ #include "hwrenderer/scene/hw_clipper.h" #include "hwrenderer/scene/hw_portal.h" #include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" #include "hwrenderer/utility/hw_vrmodes.h" +#include "gl/renderer/gl_renderer.h" //========================================================================== // diff --git a/src/gl/scene/gl_skydome.cpp b/src/gl/scene/gl_skydome.cpp deleted file mode 100644 index 468a82574b..0000000000 --- a/src/gl/scene/gl_skydome.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2003-2016 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/ -// -//-------------------------------------------------------------------------- -// - -#include "gl_load/gl_system.h" -#include "doomtype.h" -#include "g_level.h" -#include "w_wad.h" -#include "r_state.h" -#include "r_utility.h" -#include "g_levellocals.h" -#include "textures/skyboxtexture.h" - -#include "gl_load/gl_interface.h" -#include "gl/data/gl_vertexbuffer.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/renderer/gl_renderstate.h" -#include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" -#include "gl/shaders/gl_shader.h" - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -FSkyVertexBuffer::FSkyVertexBuffer() -{ - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glBufferData(GL_ARRAY_BUFFER, mVertices.Size() * sizeof(FSkyVertex), &mVertices[0], GL_STATIC_DRAW); -} - -void FSkyVertexBuffer::BindVBO() -{ - glBindBuffer(GL_ARRAY_BUFFER, vbo_id); - glVertexAttribPointer(VATTR_VERTEX, 3, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->x); - glVertexAttribPointer(VATTR_TEXCOORD, 2, GL_FLOAT, false, sizeof(FSkyVertex), &VSO->u); - glVertexAttribPointer(VATTR_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(FSkyVertex), &VSO->color); - glEnableVertexAttribArray(VATTR_VERTEX); - glEnableVertexAttribArray(VATTR_TEXCOORD); - glEnableVertexAttribArray(VATTR_COLOR); - glDisableVertexAttribArray(VATTR_VERTEX2); - glDisableVertexAttribArray(VATTR_NORMAL); -} - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -inline void FSkyVertexBuffer::RenderRow(int prim, int row) -{ - glDrawArrays(prim, mPrimStart[row], mPrimStart[row + 1] - mPrimStart[row]); -} - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void FSkyVertexBuffer::RenderDome(FMaterial *tex, int mode) -{ - int rc = mRows + 1; - - // The caps only get drawn for the main layer but not for the overlay. - if (mode == SKYMODE_MAINLAYER && tex != NULL) - { - PalEntry pe = tex->tex->GetSkyCapColor(false); - gl_RenderState.SetObjectColor(pe); - gl_RenderState.EnableTexture(false); - gl_RenderState.Apply(); - RenderRow(GL_TRIANGLE_FAN, 0); - - pe = tex->tex->GetSkyCapColor(true); - gl_RenderState.SetObjectColor(pe); - gl_RenderState.Apply(); - RenderRow(GL_TRIANGLE_FAN, rc); - gl_RenderState.EnableTexture(true); - } - gl_RenderState.SetObjectColor(0xffffffff); - gl_RenderState.Apply(); - for (int i = 1; i <= mRows; i++) - { - RenderRow(GL_TRIANGLE_STRIP, i); - RenderRow(GL_TRIANGLE_STRIP, rc + i); - } -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -void RenderDome(FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode) -{ - if (tex) - { - gl_RenderState.ApplyMaterial(tex, CLAMP_NONE, 0, -1); - gl_RenderState.EnableModelMatrix(true); - gl_RenderState.EnableTextureMatrix(true); - - GLRenderer->mSkyVBO->SetupMatrices(tex, x_offset, y_offset, mirror, mode, gl_RenderState.mModelMatrix, gl_RenderState.mTextureMatrix); - } - - GLRenderer->mSkyVBO->RenderDome(tex, mode); - gl_RenderState.EnableTextureMatrix(false); - gl_RenderState.EnableModelMatrix(false); -} - - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void RenderBox(FTextureID texno, FMaterial * gltex, float x_offset, bool sky2) -{ - FSkyBox * sb = static_cast(gltex->tex); - int faces; - FMaterial * tex; - - gl_RenderState.EnableModelMatrix(true); - gl_RenderState.mModelMatrix.loadIdentity(); - - if (!sky2) - gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector.X, level.info->skyrotatevector.Z, level.info->skyrotatevector.Y); - else - gl_RenderState.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector2.X, level.info->skyrotatevector2.Z, level.info->skyrotatevector2.Y); - - if (sb->faces[5]) - { - faces=4; - - // north - tex = FMaterial::ValidateTexture(sb->faces[0], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(0), 4); - - // east - tex = FMaterial::ValidateTexture(sb->faces[1], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(1), 4); - - // south - tex = FMaterial::ValidateTexture(sb->faces[2], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(2), 4); - - // west - tex = FMaterial::ValidateTexture(sb->faces[3], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(3), 4); - } - else - { - faces=1; - tex = FMaterial::ValidateTexture(sb->faces[0], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(-1), 10); - } - - // top - tex = FMaterial::ValidateTexture(sb->faces[faces], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(sb->fliptop? 6:5), 4); - - // bottom - tex = FMaterial::ValidateTexture(sb->faces[faces+1], false); - gl_RenderState.ApplyMaterial(tex, CLAMP_XY, 0, -1); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLE_STRIP, GLRenderer->mSkyVBO->FaceStart(4), 4); - - gl_RenderState.EnableModelMatrix(false); -} - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- -void GLSkyPortal::DrawContents(HWDrawInfo *di) -{ - bool drawBoth = false; - auto &vp = di->Viewpoint; - - // We have no use for Doom lighting special handling here, so disable it for this function. - int oldlightmode = ::level.lightmode; - if (::level.lightmode == 8) - { - ::level.lightmode = 2; - gl_RenderState.SetSoftLightLevel(-1); - } - - - gl_RenderState.ResetColor(); - gl_RenderState.EnableFog(false); - gl_RenderState.AlphaFunc(Alpha_GEqual, 0.f); - gl_RenderState.SetRenderStyle(STYLE_Translucent); - bool oldClamp = gl_RenderState.SetDepthClamp(true); - - di->SetupView(0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); - - gl_RenderState.SetVertexBuffer(GLRenderer->mSkyVBO); - if (origin->texture[0] && origin->texture[0]->tex->bSkybox) - { - RenderBox(origin->skytexno1, origin->texture[0], origin->x_offset[0], origin->sky2); - } - else - { - if (origin->texture[0]==origin->texture[1] && origin->doublesky) origin->doublesky=false; - - if (origin->texture[0]) - { - gl_RenderState.SetTextureMode(TM_OPAQUE); - RenderDome(origin->texture[0], origin->x_offset[0], origin->y_offset, origin->mirrored, FSkyVertexBuffer::SKYMODE_MAINLAYER); - gl_RenderState.SetTextureMode(TM_NORMAL); - } - - gl_RenderState.AlphaFunc(Alpha_Greater, 0.f); - - if (origin->doublesky && origin->texture[1]) - { - RenderDome(origin->texture[1], origin->x_offset[1], origin->y_offset, false, FSkyVertexBuffer::SKYMODE_SECONDLAYER); - } - - if (::level.skyfog>0 && !di->isFullbrightScene() && (origin->fadecolor & 0xffffff) != 0) - { - PalEntry FadeColor = origin->fadecolor; - FadeColor.a = clamp(::level.skyfog, 0, 255); - - gl_RenderState.EnableTexture(false); - gl_RenderState.SetObjectColor(FadeColor); - gl_RenderState.Apply(); - glDrawArrays(GL_TRIANGLES, 0, 12); - gl_RenderState.EnableTexture(true); - gl_RenderState.SetObjectColor(0xffffffff); - } - } - gl_RenderState.SetVertexBuffer(GLRenderer->mVBO); - ::level.lightmode = oldlightmode; - gl_RenderState.SetDepthClamp(oldClamp); -} - diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 1c9eb7101d..757a8fd951 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -34,7 +34,6 @@ #include "gl/data/gl_vertexbuffer.h" #include "gl/dynlights/gl_lightbuffer.h" #include "gl/scene/gl_drawinfo.h" -#include "gl/scene/gl_portal.h" EXTERN_CVAR(Bool, gl_seamless) @@ -113,7 +112,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) portal = FindPortal(wall->horizon); if (!portal) { - portal = new GLHorizonPortal(&pstate, wall->horizon, Viewpoint); + portal = new HWHorizonPortal(&pstate, wall->horizon, Viewpoint, this); Portals.Push(portal); } portal->AddLine(wall); @@ -124,7 +123,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) if (!portal) { // either a regular skybox or an Eternity-style horizon - if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new GLEEHorizonPortal(&pstate, wall->secportal); + if (wall->secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(&pstate, wall->secportal, this); else { portal = new HWScenePortal(&pstate, new HWSkyboxPortal(wall->secportal)); @@ -194,7 +193,7 @@ void FDrawInfo::AddPortal(GLWall *wall, int ptype) portal = FindPortal(wall->sky); if (!portal) { - portal = new GLSkyPortal(&pstate, wall->sky); + portal = new HWSkyPortal(GLRenderer->mSkyVBO, &pstate, wall->sky); Portals.Push(portal); } portal->AddLine(wall); diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 6c4c38b58a..0fa873737e 100644 --- a/src/hwrenderer/scene/hw_portal.cpp +++ b/src/hwrenderer/scene/hw_portal.cpp @@ -30,11 +30,13 @@ #include "p_maputl.h" #include "hw_portal.h" #include "hw_clipper.h" -#include "actor.h" +#include "d_player.h" +#include "r_sky.h" #include "g_levellocals.h" #include "hw_renderstate.h" #include "hwrenderer/data/flatvertices.h" #include "hwrenderer/utility/hw_clock.h" +#include "hwrenderer/utility/hw_lighting.h" EXTERN_CVAR(Int, r_mirror_recursions) EXTERN_CVAR(Bool, gl_portals) @@ -782,3 +784,198 @@ void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di) } const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirror ceiling" : "Planemirror floor"; } + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// +// +// Horizon Portal +// +// +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +HWHorizonPortal::HWHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local) + : HWPortal(s, local) +{ + origin = pt; + + // create the vertex data for this horizon portal. + GLSectorPlane * sp = &origin->plane; + const float vx = vp.Pos.X; + const float vy = vp.Pos.Y; + const float vz = vp.Pos.Z; + const float z = sp->Texheight; + const float tz = (z - vz); + + // Draw to some far away boundary + // This is not drawn as larger strips because it causes visual glitches. + auto verts = di->AllocVertices(256 + 10); + auto ptr = verts.first; + for (int xx = -32768; xx < 32768; xx += 4096) + { + float x = xx + vx; + for (int yy = -32768; yy < 32768; yy += 4096) + { + float y = yy + vy; + ptr->Set(x, z, y, x / 64, -y / 64); + ptr++; + ptr->Set(x + 4096, z, y, x / 64 + 64, -y / 64); + ptr++; + ptr->Set(x, z, y + 4096, x / 64, -y / 64 - 64); + ptr++; + ptr->Set(x + 4096, z, y + 4096, x / 64 + 64, -y / 64 - 64); + ptr++; + } + } + + // fill the gap between the polygon and the true horizon + // Since I can't draw into infinity there can always be a + // small gap + ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); + ptr++; + ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); + ptr++; + ptr->Set(-32768 + vx, z, 32768 + vy, -512.f, 0); + ptr++; + ptr->Set(-32768 + vx, vz, 32768 + vy, -512.f, tz); + ptr++; + ptr->Set(32768 + vx, z, 32768 + vy, 512.f, 0); + ptr++; + ptr->Set(32768 + vx, vz, 32768 + vy, 512.f, tz); + ptr++; + ptr->Set(32768 + vx, z, -32768 + vy, -512.f, 0); + ptr++; + ptr->Set(32768 + vx, vz, -32768 + vy, -512.f, tz); + ptr++; + ptr->Set(-32768 + vx, z, -32768 + vy, 512.f, 0); + ptr++; + ptr->Set(-32768 + vx, vz, -32768 + vy, 512.f, tz); + ptr++; + + voffset = verts.second; + vcount = 256; + +} + +//----------------------------------------------------------------------------- +// +// HWHorizonPortal::DrawContents +// +//----------------------------------------------------------------------------- +void HWHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) +{ + Clocker c(PortalAll); + + FMaterial * gltexture; + player_t * player = &players[consoleplayer]; + GLSectorPlane * sp = &origin->plane; + auto &vp = di->Viewpoint; + + gltexture = FMaterial::ValidateTexture(sp->texture, false, true); + if (!gltexture) + { + di->ClearScreen(); + return; + } + di->SetCameraPos(vp.Pos); + + + if (gltexture && gltexture->tex->isFullbright()) + { + // glowing textures are always drawn full bright without color + state.SetColor(255, 0, false, origin->colormap, 1.f); + state.SetFog(255, 0, false, &origin->colormap, false); + } + else + { + int rel = getExtraLight(); + state.SetColor(origin->lightlevel, rel, di->isFullbrightScene(), origin->colormap, 1.0f); + state.SetFog(origin->lightlevel, rel, di->isFullbrightScene(), &origin->colormap, false); + } + + + state.SetMaterial(gltexture, CLAMP_NONE, 0, -1); + state.SetObjectColor(origin->specialcolor); + + state.SetPlaneTextureRotation(sp, gltexture); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetRenderStyle(STYLE_Source); + + for (unsigned i = 0; i < vcount; i += 4) + { + di->Draw(DT_TriangleStrip, state, voffset + i, 4, i==0); + } + di->Draw(DT_TriangleStrip, state, voffset + vcount, 10, false); + + state.EnableTextureMatrix(false); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// +// +// Eternity-style horizon portal +// +// To the rest of the engine these masquerade as a skybox portal +// Internally they need to draw two horizon or sky portals +// and will use the respective classes to achieve that. +// +// +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state) +{ + auto &vp = di->Viewpoint; + sector_t *sector = portal->mOrigin; + if (sector->GetTexture(sector_t::floor) == skyflatnum || + sector->GetTexture(sector_t::ceiling) == skyflatnum) + { + GLSkyInfo skyinfo; + skyinfo.init(sector->sky, 0); + //GLSkyPortal sky(mState, &skyinfo, true); + //sky.DrawContents(di, state); + } + if (sector->GetTexture(sector_t::ceiling) != skyflatnum) + { + GLHorizonInfo horz; + horz.plane.GetFromSector(sector, sector_t::ceiling); + horz.lightlevel = hw_ClampLight(sector->GetCeilingLight()); + horz.colormap = sector->Colormap; + horz.specialcolor = 0xffffffff; + if (portal->mType == PORTS_PLANE) + { + horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight); + } + HWHorizonPortal ceil(mState, &horz, di->Viewpoint, di, true); + ceil.DrawContents(di, state); + } + if (sector->GetTexture(sector_t::floor) != skyflatnum) + { + GLHorizonInfo horz; + horz.plane.GetFromSector(sector, sector_t::floor); + horz.lightlevel = hw_ClampLight(sector->GetFloorLight()); + horz.colormap = sector->Colormap; + horz.specialcolor = 0xffffffff; + if (portal->mType == PORTS_PLANE) + { + horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight); + } + HWHorizonPortal floor(mState, &horz, di->Viewpoint, di, true); + floor.DrawContents(di, state); + } +} + +const char *HWHorizonPortal::GetName() { return "Horizon"; } +const char *HWEEHorizonPortal::GetName() { return "EEHorizon"; } + + diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index eaee2ba1e5..99f69614c6 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -6,6 +6,8 @@ #include "hw_drawstructs.h" #include "hwrenderer/textures/hw_material.h" +class FSkyDomeCreator; + struct GLSkyInfo { float x_offset[2]; @@ -69,7 +71,7 @@ public: virtual bool IsSky() { return false; } virtual bool NeedCap() { return true; } virtual bool NeedDepthBuffer() { return true; } - virtual void DrawContents(HWDrawInfo *di) = 0; + virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0; virtual void RenderAttached(HWDrawInfo *di) {} void AddLine(GLWall * l) @@ -321,7 +323,7 @@ public: virtual bool IsSky() { return mScene->IsSky(); } virtual bool NeedCap() { return true; } virtual bool NeedDepthBuffer() { return true; } - virtual void DrawContents(HWDrawInfo *di) + virtual void DrawContents(HWDrawInfo *di, FRenderState &state) { if (mScene->Setup(di, di->mClipper)) { @@ -334,3 +336,71 @@ public: }; +struct HWHorizonPortal : public HWPortal +{ + GLHorizonInfo * origin; + unsigned int voffset; + unsigned int vcount; + friend struct HWEEHorizonPortal; + +protected: + virtual void DrawContents(HWDrawInfo *di, FRenderState &state); + virtual void * GetSource() const { return origin; } + virtual bool NeedDepthBuffer() { return false; } + virtual bool NeedCap() { return false; } + virtual const char *GetName(); + +public: + + HWHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local = false); +}; + +struct HWEEHorizonPortal : public HWPortal +{ + FSectorPortal * portal; + +protected: + virtual void DrawContents(HWDrawInfo *di, FRenderState &state); + virtual void * GetSource() const { return portal; } + virtual bool NeedDepthBuffer() { return false; } + virtual bool NeedCap() { return false; } + virtual const char *GetName(); + +public: + + HWEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt, HWDrawInfo *di) : HWPortal(state, false) + { + portal = pt; + } + +}; + + +struct HWSkyPortal : public HWPortal +{ + GLSkyInfo * origin; + FSkyDomeCreator *vertexBuffer; + friend struct HWEEHorizonPortal; + + void RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim, int row, bool apply = true); + void RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FMaterial * gltex, float x_offset, bool sky2); + void RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode); + +protected: + virtual void DrawContents(HWDrawInfo *di, FRenderState &state); + virtual void * GetSource() const { return origin; } + virtual bool IsSky() { return true; } + virtual bool NeedDepthBuffer() { return false; } + virtual const char *GetName(); + +public: + + + HWSkyPortal(FSkyDomeCreator *vertexbuffer, FPortalSceneState *state, GLSkyInfo * pt, bool local = false) + : HWPortal(state, local) + { + origin = pt; + vertexBuffer = vertexbuffer; + } + +}; diff --git a/src/hwrenderer/scene/hw_renderstate.h b/src/hwrenderer/scene/hw_renderstate.h index e3707ee83f..2dc2b14500 100644 --- a/src/hwrenderer/scene/hw_renderstate.h +++ b/src/hwrenderer/scene/hw_renderstate.h @@ -364,5 +364,13 @@ public: void SetColor(int sectorlightlevel, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon = false); void SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cmap, bool isadditive); + // Temporary helper to get around the lack of hardware independent vertex buffer interface. + // This needs to be done better so that abstract interfaces can be passed around between hwrenderer and the backends. + enum + { + VB_Default, + VB_Sky + }; + virtual void SetVertexBuffer(int which) = 0; }; diff --git a/src/hwrenderer/scene/hw_skydome.h b/src/hwrenderer/scene/hw_skydome.h index 9fcaf29eff..6d2bbff526 100644 --- a/src/hwrenderer/scene/hw_skydome.h +++ b/src/hwrenderer/scene/hw_skydome.h @@ -32,8 +32,10 @@ struct FSkyVertex }; +struct HWSkyPortal; class FSkyDomeCreator { + friend struct HWSkyPortal; public: static const int SKYHEMI_UPPER = 1; static const int SKYHEMI_LOWER = 2; diff --git a/src/hwrenderer/scene/hw_skyportal.cpp b/src/hwrenderer/scene/hw_skyportal.cpp new file mode 100644 index 0000000000..6ead548e1b --- /dev/null +++ b/src/hwrenderer/scene/hw_skyportal.cpp @@ -0,0 +1,223 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2003-2016 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/ +// +//-------------------------------------------------------------------------- +// + +#include "doomtype.h" +#include "g_level.h" +#include "w_wad.h" +#include "r_state.h" +#include "r_utility.h" +#include "g_levellocals.h" +#include "hwrenderer/scene/hw_skydome.h" +#include "hwrenderer/scene/hw_portal.h" +#include "hwrenderer/scene/hw_renderstate.h" +#include "textures/skyboxtexture.h" + + + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void HWSkyPortal::RenderRow(HWDrawInfo *di, FRenderState &state, EDrawType prim, int row, bool apply) +{ + di->Draw(prim, state, vertexBuffer->mPrimStart[row], vertexBuffer->mPrimStart[row + 1] - vertexBuffer->mPrimStart[row]); +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FMaterial * tex, float x_offset, float y_offset, bool mirror, int mode) +{ + if (tex) + { + state.SetMaterial(tex, CLAMP_NONE, 0, -1); + state.EnableModelMatrix(true); + state.EnableTextureMatrix(true); + + vertexBuffer->SetupMatrices(tex, x_offset, y_offset, mirror, mode, state.mModelMatrix, state.mTextureMatrix); + } + + int rc = vertexBuffer->mRows + 1; + + // The caps only get drawn for the main layer but not for the overlay. + if (mode == FSkyDomeCreator::SKYMODE_MAINLAYER && tex != NULL) + { + PalEntry pe = tex->tex->GetSkyCapColor(false); + state.SetObjectColor(pe); + state.EnableTexture(false); + RenderRow(di, state, DT_TriangleFan, 0); + + pe = tex->tex->GetSkyCapColor(true); + state.SetObjectColor(pe); + RenderRow(di, state, DT_TriangleFan, rc); + state.EnableTexture(true); + } + state.SetObjectColor(0xffffffff); + for (int i = 1; i <= vertexBuffer->mRows; i++) + { + RenderRow(di, state, DT_TriangleStrip, i, i == 1); + RenderRow(di, state, DT_TriangleStrip, rc + i, false); + } + + state.EnableTextureMatrix(false); + state.EnableModelMatrix(false); +} + + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texno, FMaterial * gltex, float x_offset, bool sky2) +{ + FSkyBox * sb = static_cast(gltex->tex); + int faces; + FMaterial * tex; + + state.EnableModelMatrix(true); + state.mModelMatrix.loadIdentity(); + + if (!sky2) + state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector.X, level.info->skyrotatevector.Z, level.info->skyrotatevector.Y); + else + state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector2.X, level.info->skyrotatevector2.Z, level.info->skyrotatevector2.Y); + + if (sb->faces[5]) + { + faces=4; + + // north + tex = FMaterial::ValidateTexture(sb->faces[0], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(0), 4); + + // east + tex = FMaterial::ValidateTexture(sb->faces[1], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(1), 4); + + // south + tex = FMaterial::ValidateTexture(sb->faces[2], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(2), 4); + + // west + tex = FMaterial::ValidateTexture(sb->faces[3], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(3), 4); + } + else + { + faces=1; + tex = FMaterial::ValidateTexture(sb->faces[0], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(-1), 10); + } + + // top + tex = FMaterial::ValidateTexture(sb->faces[faces], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(sb->fliptop ? 6 : 5), 4); + + // bottom + tex = FMaterial::ValidateTexture(sb->faces[faces+1], false); + state.SetMaterial(tex, CLAMP_XY, 0, -1); + di->Draw(DT_TriangleStrip, state, vertexBuffer->FaceStart(4), 4); + + state.EnableModelMatrix(false); +} + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- +void HWSkyPortal::DrawContents(HWDrawInfo *di, FRenderState &state) +{ + bool drawBoth = false; + auto &vp = di->Viewpoint; + + // We have no use for Doom lighting special handling here, so disable it for this function. + int oldlightmode = ::level.lightmode; + if (::level.lightmode == 8) + { + ::level.lightmode = 2; + state.SetSoftLightLevel(-1); + } + + + state.ResetColor(); + state.EnableFog(false); + state.AlphaFunc(Alpha_GEqual, 0.f); + state.SetRenderStyle(STYLE_Translucent); + bool oldClamp = di->SetDepthClamp(true); + + di->SetupView(0, 0, 0, !!(mState->MirrorFlag & 1), !!(mState->PlaneMirrorFlag & 1)); + + state.SetVertexBuffer(FRenderState::VB_Sky); + if (origin->texture[0] && origin->texture[0]->tex->bSkybox) + { + RenderBox(di, state, origin->skytexno1, origin->texture[0], origin->x_offset[0], origin->sky2); + } + else + { + if (origin->texture[0]==origin->texture[1] && origin->doublesky) origin->doublesky=false; + + if (origin->texture[0]) + { + state.SetTextureMode(TM_OPAQUE); + RenderDome(di, state, origin->texture[0], origin->x_offset[0], origin->y_offset, origin->mirrored, FSkyDomeCreator::SKYMODE_MAINLAYER); + state.SetTextureMode(TM_NORMAL); + } + + state.AlphaFunc(Alpha_Greater, 0.f); + + if (origin->doublesky && origin->texture[1]) + { + RenderDome(di, state, origin->texture[1], origin->x_offset[1], origin->y_offset, false, FSkyDomeCreator::SKYMODE_SECONDLAYER); + } + + if (::level.skyfog>0 && !di->isFullbrightScene() && (origin->fadecolor & 0xffffff) != 0) + { + PalEntry FadeColor = origin->fadecolor; + FadeColor.a = clamp(::level.skyfog, 0, 255); + + state.EnableTexture(false); + state.SetObjectColor(FadeColor); + di->Draw(DT_Triangles, state, 0, 12); + state.EnableTexture(true); + state.SetObjectColor(0xffffffff); + } + } + state.SetVertexBuffer(FRenderState::VB_Default); + ::level.lightmode = oldlightmode; + di->SetDepthClamp(oldClamp); +} + +const char *HWSkyPortal::GetName() { return "Sky"; }