diff --git a/src/common/textures/texture.cpp b/src/common/textures/texture.cpp index 793285029..1eb280552 100644 --- a/src/common/textures/texture.cpp +++ b/src/common/textures/texture.cpp @@ -158,69 +158,6 @@ void FTexture::SetDisplaySize(int fitwidth, int fitheight) if (int(Scale.Y * fitheight) != Height) Scale.Y += (1 / 65536.); } -//=========================================================================== -// -// Gets the average color of a texture for use as a sky cap color -// -//=========================================================================== - -PalEntry FTexture::averageColor(const uint32_t *data, int size, int maxout) -{ - int i; - unsigned int r, g, b; - - // First clear them. - r = g = b = 0; - if (size == 0) - { - return PalEntry(255, 255, 255); - } - for (i = 0; i < size; i++) - { - b += BPART(data[i]); - g += GPART(data[i]); - r += RPART(data[i]); - } - - r = r / size; - g = g / size; - b = b / size; - - int maxv = MAX(MAX(r, g), b); - - if (maxv && maxout) - { - r = ::Scale(r, maxout, maxv); - g = ::Scale(g, maxout, maxv); - b = ::Scale(b, maxout, maxv); - } - return PalEntry(255, r, g, b); -} - -PalEntry FTexture::GetSkyCapColor(bool bottom) -{ - if (!bSWSkyColorDone) - { - bSWSkyColorDone = true; - - FBitmap bitmap = GetBgraBitmap(nullptr); - int w = bitmap.GetWidth(); - int h = bitmap.GetHeight(); - - const uint32_t *buffer = (const uint32_t *)bitmap.GetPixels(); - if (buffer) - { - CeilingSkyColor = averageColor((uint32_t *)buffer, w * MIN(30, h), 0); - if (h>30) - { - FloorSkyColor = averageColor(((uint32_t *)buffer) + (h - 30)*w, w * 30, 0); - } - else FloorSkyColor = CeilingSkyColor; - } - } - return bottom ? FloorSkyColor : CeilingSkyColor; -} - //==================================================================== // // CheckRealHeight diff --git a/src/common/textures/textures.h b/src/common/textures/textures.h index ca07415ae..0df5aaa7b 100644 --- a/src/common/textures/textures.h +++ b/src/common/textures/textures.h @@ -288,7 +288,6 @@ public: bool isMasked() const { return bMasked; } void SetSkyOffset(int offs) { SkyOffset = offs; } int GetSkyOffset() const { return SkyOffset; } - PalEntry GetSkyCapColor(bool bottom); virtual int GetSourceLump() { return SourceLump; } // needed by the scripted GetName method. void GetGlowColor(float *data); bool isGlowing() const { return bGlowing; } @@ -329,7 +328,6 @@ public: virtual FBitmap GetBgraBitmap(const PalEntry *remap, int *trans = nullptr); static bool SmoothEdges(unsigned char * buffer,int w, int h); - static PalEntry averageColor(const uint32_t *data, int size, int maxout); protected: @@ -424,14 +422,6 @@ public: return bTranslucent != -1 ? bTranslucent : DetermineTranslucency(); } -private: - int CheckDDPK3(); - int CheckExternalFile(bool & hascolorkey); - - bool bSWSkyColorDone = false; - PalEntry FloorSkyColor; - PalEntry CeilingSkyColor; - public: void CheckTrans(unsigned char * buffer, int size, int trans); @@ -731,7 +721,6 @@ public: const SpritePositioningInfo& GetSpritePositioning(int which) { if (spi == nullptr) SetupSpriteData(); return spi[which]; } int GetAreas(FloatRect** pAreas) const { return Base->GetAreas(pAreas); } - PalEntry GetSkyCapColor(bool bottom) { return Base->GetSkyCapColor(bottom); } bool GetTranslucency() { diff --git a/src/common/utility/palette.cpp b/src/common/utility/palette.cpp index 5be3f6a45..f4876b4b9 100644 --- a/src/common/utility/palette.cpp +++ b/src/common/utility/palette.cpp @@ -471,6 +471,47 @@ void MakeGoodRemap(uint32_t* BaseColors, uint8_t* Remap) // 256 entries are different. :-) } +//=========================================================================== +// +// Gets the average color of a texture for use as a sky cap color +// +//=========================================================================== + +PalEntry averageColor(const uint32_t* data, int size, int maxout) +{ + int i; + unsigned int r, g, b; + + // First clear them. + r = g = b = 0; + if (size == 0) + { + return PalEntry(255, 255, 255); + } + for (i = 0; i < size; i++) + { + b += BPART(data[i]); + g += GPART(data[i]); + r += RPART(data[i]); + } + + r = r / size; + g = g / size; + b = b / size; + + int maxv = MAX(MAX(r, g), b); + + if (maxv && maxout) + { + r = ::Scale(r, maxout, maxv); + g = ::Scale(g, maxout, maxv); + b = ::Scale(b, maxout, maxv); + } + return PalEntry(255, r, g, b); +} + + + //========================================================================== // // V_GetColorFromString diff --git a/src/common/utility/palutil.h b/src/common/utility/palutil.h index 077c4c036..b1dcca40a 100644 --- a/src/common/utility/palutil.h +++ b/src/common/utility/palutil.h @@ -30,6 +30,7 @@ FString V_GetColorStringByName(const char* name, FScriptPosition* sc = nullptr); // Tries to get color by name, then by string int V_GetColor(const uint32_t* palette, const char* str, FScriptPosition* sc = nullptr); int V_GetColor(const uint32_t* palette, FScanner& sc); +PalEntry averageColor(const uint32_t* data, int size, int maxout); enum { diff --git a/src/rendering/hwrenderer/scene/hw_skyportal.cpp b/src/rendering/hwrenderer/scene/hw_skyportal.cpp index 79051f0ef..a41fff53e 100644 --- a/src/rendering/hwrenderer/scene/hw_skyportal.cpp +++ b/src/rendering/hwrenderer/scene/hw_skyportal.cpp @@ -66,13 +66,12 @@ void HWSkyPortal::RenderDome(HWDrawInfo *di, FRenderState &state, FGameTexture * // The caps only get drawn for the main layer but not for the overlay. if (mode == FSkyVertexBuffer::SKYMODE_MAINLAYER && tex != NULL) { - PalEntry pe = tex->GetSkyCapColor(false); - state.SetObjectColor(pe); + auto &col = R_GetSkyCapColor(tex); + state.SetObjectColor(col.first); state.EnableTexture(false); RenderRow(di, state, DT_TriangleFan, 0); - pe = tex->GetSkyCapColor(true); - state.SetObjectColor(pe); + state.SetObjectColor(col.second); RenderRow(di, state, DT_TriangleFan, rc); state.EnableTexture(true); } diff --git a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp index 55a47fca9..154ef8f86 100644 --- a/src/rendering/polyrenderer/backend/poly_hwtexture.cpp +++ b/src/rendering/polyrenderer/backend/poly_hwtexture.cpp @@ -64,8 +64,6 @@ void PolyHardwareTexture::Reset() DCanvas *PolyHardwareTexture::GetImage(FTexture *baselayer, const FMaterialState &state) { - FGameTexture *tex = state.mMaterial->Source(); - if (!mCanvas) { int flags = state.mMaterial->GetScaleFlags(); diff --git a/src/rendering/r_sky.cpp b/src/rendering/r_sky.cpp index 051068162..d8d340b0e 100644 --- a/src/rendering/r_sky.cpp +++ b/src/rendering/r_sky.cpp @@ -39,6 +39,8 @@ #include "v_text.h" #include "g_levellocals.h" #include "texturemanager.h" +#include "palentry.h" +#include "bitmap.h" // // sky mapping @@ -54,6 +56,46 @@ CUSTOM_CVAR (Int, r_skymode, 2, CVAR_ARCHIVE|CVAR_NOINITCALL) CVAR(Float, skyoffset, 0, 0) // for testing + +struct SkyColor +{ + FTextureID Texture; + std::pair Colors; +}; + +static TArray SkyColors; + +std::pair& R_GetSkyCapColor(FGameTexture* tex) +{ + for (auto& sky : SkyColors) + { + if (sky.Texture == tex->GetID()) return sky.Colors; + } + + auto itex = tex->GetTexture(); + SkyColor sky; + + FBitmap bitmap = itex->GetBgraBitmap(nullptr); + int w = bitmap.GetWidth(); + int h = bitmap.GetHeight(); + + const uint32_t* buffer = (const uint32_t*)bitmap.GetPixels(); + if (buffer) + { + sky.Colors.first = averageColor((uint32_t*)buffer, w * MIN(30, h), 0); + if (h > 30) + { + sky.Colors.second = averageColor(((uint32_t*)buffer) + (h - 30) * w, w * 30, 0); + } + else sky.Colors.second = sky.Colors.first; + } + sky.Texture = tex->GetID(); + SkyColors.Push(sky); + + return SkyColors.Last().Colors; +} + + //========================================================================== // // R_InitSkyMap diff --git a/src/rendering/r_sky.h b/src/rendering/r_sky.h index f2aa868fc..43cd7a0ce 100644 --- a/src/rendering/r_sky.h +++ b/src/rendering/r_sky.h @@ -28,6 +28,7 @@ #ifndef __R_SKY_H__ #define __R_SKY_H__ +#include #include "textures.h" struct FLevelLocals; @@ -41,6 +42,7 @@ extern int freelookviewheight; void InitSkyMap(FLevelLocals *Level); void R_InitSkyMap(); void R_UpdateSky (uint64_t mstime); +std::pair& R_GetSkyCapColor(FGameTexture* tex); // 57 world units roughly represent one sky texel for the glTranslate call. enum diff --git a/src/rendering/swrenderer/plane/r_skyplane.cpp b/src/rendering/swrenderer/plane/r_skyplane.cpp index 5b9b60c4c..7279c906b 100644 --- a/src/rendering/swrenderer/plane/r_skyplane.cpp +++ b/src/rendering/swrenderer/plane/r_skyplane.cpp @@ -258,8 +258,9 @@ namespace swrenderer drawerargs.SetDest(viewport, start_x, y1); drawerargs.SetCount(y2 - y1); drawerargs.SetFadeSky(r_skymode == 2 && !(Level->flags & LEVEL_FORCETILEDSKY)); - drawerargs.SetSolidTop(frontskytex->GetSkyCapColor(false)); - drawerargs.SetSolidBottom(frontskytex->GetSkyCapColor(true)); + auto& col = R_GetSkyCapColor(frontskytex->GetTexture()); + drawerargs.SetSolidTop(col.first); + drawerargs.SetSolidBottom(col.second); if (!backskytex) drawerargs.DrawSingleSkyColumn(Thread); diff --git a/src/rendering/swrenderer/textures/r_swtexture.h b/src/rendering/swrenderer/textures/r_swtexture.h index cfd97c2ee..3e462d36e 100644 --- a/src/rendering/swrenderer/textures/r_swtexture.h +++ b/src/rendering/swrenderer/textures/r_swtexture.h @@ -62,7 +62,6 @@ public: } int GetSkyOffset() const { return mTexture->GetSkyOffset(); } - PalEntry GetSkyCapColor(bool bottom) const { return mSource->GetSkyCapColor(bottom); } int GetWidth () { return mTexture->GetTexelWidth(); } int GetHeight () { return mTexture->GetTexelHeight(); }