// //--------------------------------------------------------------------------- // // Copyright(C) 2002-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 "texturemanager.h" #include "hw_drawinfo.h" #include "hw_drawstructs.h" #include "hw_portal.h" //#include "hw_lighting.h" #include "hw_material.h" #include "gamefuncs.h" #include "build.h" #include "cmdlib.h" CVAR(Bool,gl_noskyboxes, false, 0) FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap); //========================================================================== // // Set up the skyinfo struct // //========================================================================== void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane, PalEntry FadeColor) { int picnum = plane == plane_ceiling ? sector->ceilingpicnum : sector->floorpicnum; float xpanning = plane == plane_ceiling ? sector->ceilingxpan_ : sector->floorxpan_; float ypanning = plane == plane_ceiling ? sector->ceilingypan_ : sector->floorypan_; int32_t dapyscale = 0, dapskybits = 0, dapyoffs = 0, daptileyscale = 0; FGameTexture* skytex = nullptr; int realskybits = 0; // todo: check for skybox replacement. if (!skytex) { int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale); skytex = GetSkyTexture(picnum, dapskybits, dapskyoff); realskybits = dapskybits; if (skytex) dapskybits = 0; else skytex = tileGetTexture(picnum); } float t = (float)((1 << (sizeToBits(tileWidth(picnum)))) << dapskybits); int ti = (1 << (sizeToBits(tileHeight(picnum)))); if (ti != tileHeight(picnum)) ti += ti; // dapyscale is not relvant for a sky dome. sky->y_scale = FixedToFloat(daptileyscale); sky->y_offset = dapyoffs*2 + (ypanning * ti / 64.f); sky->x_offset = xpanning / (1 << (realskybits - dapskybits)); sky->fadecolor = FadeColor; sky->shade = 0;// clamp(plane == plane_ceiling ? sector->ceilingshade : sector->floorshade, 0, numshades - 1); sky->texture = skytex; } //========================================================================== // // Calculate sky texture for ceiling or floor // //========================================================================== void HWWall::SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowreflect) { int ptype; if ((sector->portalflags == PORTAL_SECTOR_CEILING && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR && plane == plane_floor)) { if (screen->instack[1 - plane] || sector->portalnum >= (int)allPortals.Size()) return; portal = &allPortals[sector->portalnum]; PutPortal(di, PORTALTYPE_SECTORSTACK, plane); } else if ((sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT && plane == plane_floor)) { ptype = PORTALTYPE_PLANEMIRROR; if (plane == plane_ceiling && (sector->ceilingstat & CSTAT_SECTOR_SLOPE)) return; if (plane == plane_floor && (sector->floorstat & CSTAT_SECTOR_SLOPE)) return; planemirror = plane == plane_floor ? §or->floorz : §or->ceilingz; PutPortal(di, PORTALTYPE_PLANEMIRROR, plane); } else { ptype = PORTALTYPE_SKY; HWSkyInfo skyinfo; initSkyInfo(di, &skyinfo, sector, plane, fade); ptype = PORTALTYPE_SKY; sky = &skyinfo; PutPortal(di, ptype, plane); } } //========================================================================== // // Skies on one sided walls // //========================================================================== void HWWall::SkyNormal(HWDrawInfo* di, sectortype* fs, FVector2& v1, FVector2& v2, float fch1, float fch2, float ffh1, float ffh2) { if ((fs->ceilingstat & CSTAT_SECTOR_SKY) || fs->portalflags == PORTAL_SECTOR_CEILING || fs->portalflags == PORTAL_SECTOR_CEILING_REFLECT) { ztop[0] = ztop[1] = 32768.0f; zbottom[0] = fch1; zbottom[1] = fch2; SkyPlane(di, fs, plane_ceiling, true); } if ((fs->floorstat & CSTAT_SECTOR_SKY) || fs->portalflags == PORTAL_SECTOR_FLOOR || fs->portalflags == PORTAL_SECTOR_FLOOR_REFLECT) { ztop[0] = ffh1; ztop[1] = ffh2; zbottom[0] = zbottom[1] = -32768.0f; SkyPlane(di, fs, plane_floor, true); } } //========================================================================== // // Upper Skies on two sided walls // //========================================================================== void HWWall::SkyTop(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype * bs, FVector2& v1, FVector2& v2, float fch1, float fch2) { if (fs->portalflags == PORTAL_SECTOR_CEILING || fs->portalflags == PORTAL_SECTOR_CEILING_REFLECT) { if (fs->portalflags == PORTAL_SECTOR_CEILING_REFLECT) { /* float backreflect = bs->GetReflect(sectortype::ceiling); if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. return; } */ } else { if (bs->portalflags == PORTAL_SECTOR_CEILING && bs->portalnum == fs->portalnum) { return; } } } else if (fs->ceilingstat & CSTAT_SECTOR_SKY) { if (bs->ceilingstat & CSTAT_SECTOR_SKY) { float c1, c2, f1, f2; PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); // if the back sector is closed the sky must be drawn! if (c1 > f1 || c2 > f2) return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! } else return; ztop[0] = ztop[1] = 32768.0f; zbottom[0] = fch1; zbottom[1] = fch2; SkyPlane(di, fs, plane_ceiling, true); } //========================================================================== // // Lower Skies on two sided walls // //========================================================================== void HWWall::SkyBottom(HWDrawInfo *di, walltype * seg,sectortype * fs,sectortype * bs, FVector2& v1, FVector2& v2, float ffh1, float ffh2) { if (fs->portalflags == PORTAL_SECTOR_FLOOR || fs->portalflags == PORTAL_SECTOR_FLOOR_REFLECT) { if (fs->portalflags == PORTAL_SECTOR_FLOOR_REFLECT) { /* float backreflect = bs->GetReflect(sectortype::floor); if (backreflect > 0 && bs->ceilingplane.fD() == fs->ceilingplane.fD() && !bs->isClosed()) { // Don't add intra-portal line to the portal. return; } */ } else { if (bs->portalflags == PORTAL_SECTOR_FLOOR && bs->portalnum == fs->portalnum) { return; } } // stacked sectors } else if (fs->floorstat & CSTAT_SECTOR_SKY) { float c1, c2, f1, f2; PlanesAtPoint(bs, v1.X * 16.f, v1.Y * -16.f, &c1, &f1); PlanesAtPoint(bs, v2.X * 16.f, v2.Y * -16.f, &c2, &f2); if (bs->floorstat & CSTAT_SECTOR_SKY) { // if the back sector is closed the sky must be drawn! if (c1 > f1 || c2 > f2) return; } flags |= HWF_SKYHACK; // mid textures on such lines need special treatment! } else return; zbottom[0] = zbottom[1] = -32768.0f; ztop[0] = ffh1; ztop[1] = ffh2; SkyPlane(di, fs, plane_floor, true); }