// //--------------------------------------------------------------------------- // // 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 2 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, int remap); FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum); //========================================================================== // // Set up the skyinfo struct // //========================================================================== void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane) { int picnum = plane == plane_ceiling ? sector->ceilingpicnum : sector->floorpicnum; tileUpdatePicnum(&picnum, 0, 0); int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal; int32_t dapyscale = 0, dapskybits = 0, dapyoffs = 0, daptileyscale = 0; FGameTexture* skytex = SkyboxReplacement(tileGetTexture(picnum)->GetID(), palette); int realskybits = 0; // todo: check for skybox replacement. if (!skytex) { int remap = TRANSLATION(Translation_Remap + curbasepal, palette); int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale, true); int tw = tileWidth(picnum); if ((1 << sizeToBits(tw)) < tw) dapskybits--; // Build math is weird. skytex = GetSkyTexture(picnum, dapskybits, dapskyoff, remap); realskybits = dapskybits; if (skytex) dapskybits = 0; else skytex = tileGetTexture(picnum); } float xpanning = plane == plane_ceiling ? sector->ceilingxpan_ : sector->floorxpan_; float ypanning = plane == plane_ceiling ? sector->ceilingypan_ : sector->floorypan_; // dapyscale is not relvant for a sky dome. sky->y_scale = FixedToFloat(daptileyscale); sky->cloudy = !!(sector->exflags & SECTOREX_CLOUDSCROLL); if (!sky->cloudy) { sky->y_offset = dapyoffs * 1.5; sky->x_offset = xpanning / (1 << (realskybits - dapskybits)); } else { sky->y_offset = ypanning; sky->x_offset = 2 * xpanning / (1 << (realskybits - dapskybits)); } PalEntry pe = GlobalMapFog ? GlobalMapFog : lookups.getFade(palette); pe.a = 230; sky->fadecolor = pe; 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); 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) { 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) { if (bs->floorstat & CSTAT_SECTOR_SKY) { 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); }