diff --git a/source/graphics/LOSTexture.cpp b/source/graphics/LOSTexture.cpp index 0708a675df..7ee6af78b9 100644 --- a/source/graphics/LOSTexture.cpp +++ b/source/graphics/LOSTexture.cpp @@ -61,8 +61,7 @@ static const size_t g_SubTextureAlignment = 4; CLOSTexture::CLOSTexture(CSimulation2& simulation) : m_Simulation(simulation), m_Dirty(true), m_ShaderInitialized(false), - m_Texture(0), m_TextureSmooth1(0), m_TextureSmooth2(0), m_smoothFbo(0), - m_MapSize(0), m_TextureSize(0), whichTex(true) + m_smoothFbo(0), m_MapSize(0), m_TextureSize(0), whichTex(true) { if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS()) CreateShader(); @@ -98,17 +97,9 @@ bool CLOSTexture::CreateShader() void CLOSTexture::DeleteTexture() { - glDeleteTextures(1, &m_Texture); - - if (m_TextureSmooth1) - glDeleteTextures(1, &m_TextureSmooth1); - - if (m_TextureSmooth2) - glDeleteTextures(1, &m_TextureSmooth2); - - m_Texture = 0; - m_TextureSmooth1 = 0; - m_TextureSmooth2 = 0; + m_Texture.reset(); + m_TextureSmooth1.reset(); + m_TextureSmooth2.reset(); } void CLOSTexture::MakeDirty() @@ -116,23 +107,12 @@ void CLOSTexture::MakeDirty() m_Dirty = true; } -void CLOSTexture::BindTexture(int unit) -{ - if (m_Dirty) - { - RecomputeTexture(unit); - m_Dirty = false; - } - - g_Renderer.BindTexture(unit, m_Texture); -} - GLuint CLOSTexture::GetTextureSmooth() { if (CRenderer::IsInitialised() && !g_RenderingOptions.GetSmoothLOS()) return GetTexture(); else - return whichTex ? m_TextureSmooth1 : m_TextureSmooth2; + return (whichTex ? m_TextureSmooth1 : m_TextureSmooth2)->GetHandle(); } void CLOSTexture::InterpolateLOS() @@ -148,19 +128,19 @@ void CLOSTexture::InterpolateLOS() // RecomputeTexture(0) will not cause the ConstructTexture to run. // Force the textures to be created. DeleteTexture(); - ConstructTexture(0); + ConstructTexture(); m_Dirty = true; } if (m_Dirty) { - RecomputeTexture(0); + RecomputeTexture(); m_Dirty = false; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_smoothFbo); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, - whichTex ? m_TextureSmooth2 : m_TextureSmooth1, 0); + (whichTex ? m_TextureSmooth2 : m_TextureSmooth1)->GetHandle(), 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) @@ -175,8 +155,8 @@ void CLOSTexture::InterpolateLOS() shader->Bind(); - shader->BindTexture(str_losTex1, m_Texture); - shader->BindTexture(str_losTex2, whichTex ? m_TextureSmooth1 : m_TextureSmooth2); + shader->BindTexture(str_losTex1, m_Texture->GetHandle()); + shader->BindTexture(str_losTex2, (whichTex ? m_TextureSmooth1 : m_TextureSmooth2)->GetHandle()); shader->Uniform(str_delta, (float)g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f, 0.0f, 0.0f, 0.0f); @@ -224,11 +204,11 @@ GLuint CLOSTexture::GetTexture() { if (m_Dirty) { - RecomputeTexture(0); + RecomputeTexture(); m_Dirty = false; } - return m_Texture; + return m_Texture->GetHandle(); } const CMatrix3D& CLOSTexture::GetTextureMatrix() @@ -243,7 +223,7 @@ const CMatrix3D* CLOSTexture::GetMinimapTextureMatrix() return &m_MinimapTextureMatrix; } -void CLOSTexture::ConstructTexture(int unit) +void CLOSTexture::ConstructTexture() { CmpPtr cmpRangeManager(m_Simulation, SYSTEM_ENTITY); if (!cmpRangeManager) @@ -253,7 +233,13 @@ void CLOSTexture::ConstructTexture(int unit) m_TextureSize = (GLsizei)round_up_to_pow2(round_up((size_t)m_MapSize + g_BlurSize - 1, g_SubTextureAlignment)); - glGenTextures(1, &m_Texture); + const Renderer::Backend::Sampler::Desc defaultSamplerDesc = + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE); + + m_Texture = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); // Initialise texture with SoD color, for the areas we don't // overwrite with glTexSubImage2D later @@ -262,30 +248,20 @@ void CLOSTexture::ConstructTexture(int unit) if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS()) { - glGenTextures(1, &m_TextureSmooth1); - glGenTextures(1, &m_TextureSmooth2); + m_TextureSmooth1 = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); + m_TextureSmooth2 = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); - g_Renderer.BindTexture(unit, m_TextureSmooth1); + g_Renderer.BindTexture(0, m_TextureSmooth1->GetHandle()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - g_Renderer.BindTexture(unit, m_TextureSmooth2); + g_Renderer.BindTexture(0, m_TextureSmooth2->GetHandle()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - g_Renderer.BindTexture(unit, m_Texture); + g_Renderer.BindTexture(0, m_Texture->GetHandle()); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_TextureSize, m_TextureSize, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); delete[] texData; @@ -317,7 +293,7 @@ void CLOSTexture::ConstructTexture(int unit) } } -void CLOSTexture::RecomputeTexture(int unit) +void CLOSTexture::RecomputeTexture() { // If the map was resized, delete and regenerate the texture if (m_Texture) @@ -330,7 +306,7 @@ void CLOSTexture::RecomputeTexture(int unit) bool recreated = false; if (!m_Texture) { - ConstructTexture(unit); + ConstructTexture(); recreated = true; } @@ -350,13 +326,13 @@ void CLOSTexture::RecomputeTexture(int unit) if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS() && recreated) { - g_Renderer.BindTexture(unit, m_TextureSmooth1); + g_Renderer.BindTexture(0, m_TextureSmooth1->GetHandle()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); - g_Renderer.BindTexture(unit, m_TextureSmooth2); + g_Renderer.BindTexture(0, m_TextureSmooth2->GetHandle()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); } - g_Renderer.BindTexture(unit, m_Texture); + g_Renderer.BindTexture(0, m_Texture->GetHandle()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, pitch, m_MapSize, GL_ALPHA, GL_UNSIGNED_BYTE, &losData[0]); } diff --git a/source/graphics/LOSTexture.h b/source/graphics/LOSTexture.h index 0d2ebe66bc..342f247786 100644 --- a/source/graphics/LOSTexture.h +++ b/source/graphics/LOSTexture.h @@ -22,6 +22,7 @@ #include "graphics/ShaderTechniquePtr.h" #include "maths/Matrix3D.h" +#include "renderer/backend/gl/Texture.h" class CLosQuerier; class CSimulation2; @@ -45,14 +46,6 @@ public: */ void MakeDirty(); - /** - * Recomputes the LOS texture if necessary, and binds it to the requested - * texture unit. - * Also switches the current active texture unit, and enables texturing on it. - * The texture is in 8-bit ALPHA format. - */ - void BindTexture(int unit); - /** * Recomputes the LOS texture if necessary, and returns the texture handle. * Also potentially switches the current active texture unit, and enables texturing on it. @@ -80,8 +73,8 @@ public: private: void DeleteTexture(); bool CreateShader(); - void ConstructTexture(int unit); - void RecomputeTexture(int unit); + void ConstructTexture(); + void RecomputeTexture(); size_t GetBitmapSize(size_t w, size_t h, size_t* pitch); void GenerateBitmap(const CLosQuerier& los, u8* losData, size_t w, size_t h, size_t pitch); @@ -92,8 +85,8 @@ private: bool m_ShaderInitialized; - GLuint m_Texture; - GLuint m_TextureSmooth1, m_TextureSmooth2; + std::unique_ptr + m_Texture, m_TextureSmooth1, m_TextureSmooth2; bool whichTex; @@ -107,4 +100,4 @@ private: CMatrix3D m_MinimapTextureMatrix; }; -#endif // INCLUDED_LOSTEXTURE \ No newline at end of file +#endif // INCLUDED_LOSTEXTURE diff --git a/source/graphics/MiniMapTexture.cpp b/source/graphics/MiniMapTexture.cpp index b2d7d723b2..c697568c4b 100644 --- a/source/graphics/MiniMapTexture.cpp +++ b/source/graphics/MiniMapTexture.cpp @@ -210,36 +210,35 @@ void CMiniMapTexture::CreateTextures(const CTerrain* terrain) m_MapSize = terrain->GetVerticesPerSide(); m_TextureSize = static_cast(round_up_to_pow2(static_cast(m_MapSize))); + const Renderer::Backend::Sampler::Desc defaultSamplerDesc = + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE); + // Create terrain texture - glGenTextures(1, &m_TerrainTexture); - g_Renderer.BindTexture(0, m_TerrainTexture); + m_TerrainTexture = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, defaultSamplerDesc); // Initialise texture with solid black, for the areas we don't // overwrite with glTexSubImage2D later u32* texData = new u32[m_TextureSize * m_TextureSize]; for (ssize_t i = 0; i < m_TextureSize * m_TextureSize; ++i) texData[i] = 0xFF000000; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); + g_Renderer.BindTexture(0, m_TerrainTexture->GetHandle()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TextureSize, m_TextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); delete[] texData; m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)]; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glGenTextures(1, &m_FinalTexture); - g_Renderer.BindTexture(0, m_FinalTexture); + m_FinalTexture = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::R8G8B8A8, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, defaultSamplerDesc); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + g_Renderer.BindTexture(0, m_FinalTexture->GetHandle()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glGenFramebuffersEXT(1, &m_FinalTextureFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FinalTextureFBO); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_FinalTexture, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_FinalTexture->GetHandle(), 0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) @@ -252,17 +251,8 @@ void CMiniMapTexture::CreateTextures(const CTerrain* terrain) void CMiniMapTexture::DestroyTextures() { - if (m_TerrainTexture) - { - glDeleteTextures(1, &m_TerrainTexture); - m_TerrainTexture = 0; - } - - if (m_FinalTexture) - { - glDeleteTextures(1, &m_FinalTexture); - m_FinalTexture = 0; - } + m_TerrainTexture.reset(); + m_FinalTexture.reset(); SAFE_ARRAY_DELETE(m_TerrainData); } @@ -326,7 +316,7 @@ void CMiniMapTexture::RebuildTerrainTexture(const CTerrain* terrain) } // Upload the texture - g_Renderer.BindTexture(0, m_TerrainTexture); + g_Renderer.BindTexture(0, m_TerrainTexture->GetHandle()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, m_TerrainData); g_Renderer.BindTexture(0, 0); } @@ -369,7 +359,7 @@ void CMiniMapTexture::RenderFinalTexture() shader = tech->GetShader(); if (m_TerrainTexture) - shader->BindTexture(str_baseTex, m_TerrainTexture); + shader->BindTexture(str_baseTex, m_TerrainTexture->GetHandle()); CMatrix3D baseTransform; baseTransform.SetIdentity(); diff --git a/source/graphics/MiniMapTexture.h b/source/graphics/MiniMapTexture.h index 711dab4edb..c80c27166c 100644 --- a/source/graphics/MiniMapTexture.h +++ b/source/graphics/MiniMapTexture.h @@ -19,6 +19,7 @@ #define INCLUDED_MINIMAPTEXTURE #include "lib/ogl.h" +#include "renderer/backend/gl/Texture.h" #include "renderer/VertexArray.h" class CSimulation2; @@ -41,7 +42,7 @@ public: */ void Render(); - GLuint GetTexture() const { return m_FinalTexture; } + GLuint GetTexture() const { return m_FinalTexture->GetHandle(); } /** * @return The maximum height for unit passage in water. @@ -61,8 +62,8 @@ private: double m_LastFinalTextureUpdate = 0.0; // minimap texture handles - GLuint m_TerrainTexture = 0; - GLuint m_FinalTexture = 0; + std::unique_ptr + m_TerrainTexture, m_FinalTexture; GLuint m_FinalTextureFBO = 0; diff --git a/source/graphics/TerritoryTexture.cpp b/source/graphics/TerritoryTexture.cpp index f6ec761ff0..4098cce73c 100644 --- a/source/graphics/TerritoryTexture.cpp +++ b/source/graphics/TerritoryTexture.cpp @@ -35,20 +35,18 @@ // TODO: There's a lot of duplication with CLOSTexture - might be nice to refactor a bit CTerritoryTexture::CTerritoryTexture(CSimulation2& simulation) : - m_Simulation(simulation), m_DirtyID(0), m_Texture(0), m_MapSize(0), m_TextureSize(0) + m_Simulation(simulation), m_DirtyID(0), m_MapSize(0), m_TextureSize(0) { } CTerritoryTexture::~CTerritoryTexture() { - if (m_Texture) - DeleteTexture(); + DeleteTexture(); } void CTerritoryTexture::DeleteTexture() { - glDeleteTextures(1, &m_Texture); - m_Texture = 0; + m_Texture.reset(); } bool CTerritoryTexture::UpdateDirty() @@ -57,20 +55,12 @@ bool CTerritoryTexture::UpdateDirty() return cmpTerritoryManager && cmpTerritoryManager->NeedUpdateTexture(&m_DirtyID); } -void CTerritoryTexture::BindTexture(int unit) -{ - if (UpdateDirty()) - RecomputeTexture(unit); - - g_Renderer.BindTexture(unit, m_Texture); -} - GLuint CTerritoryTexture::GetTexture() { if (UpdateDirty()) - RecomputeTexture(0); + RecomputeTexture(); - return m_Texture; + return m_Texture->GetHandle(); } const float* CTerritoryTexture::GetTextureMatrix() @@ -85,7 +75,7 @@ const CMatrix3D* CTerritoryTexture::GetMinimapTextureMatrix() return &m_MinimapTextureMatrix; } -void CTerritoryTexture::ConstructTexture(int unit) +void CTerritoryTexture::ConstructTexture() { CmpPtr cmpTerrain(m_Simulation, SYSTEM_ENTITY); if (!cmpTerrain) @@ -96,21 +86,20 @@ void CTerritoryTexture::ConstructTexture(int unit) m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize); - glGenTextures(1, &m_Texture); - g_Renderer.BindTexture(unit, m_Texture); + m_Texture = Renderer::Backend::GL::CTexture::Create2D( + Renderer::Backend::Format::R8G8B8A8, m_TextureSize, m_TextureSize, + Renderer::Backend::Sampler::MakeDefaultSampler( + Renderer::Backend::Sampler::Filter::LINEAR, + Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); // Initialise texture with transparency, for the areas we don't // overwrite with glTexSubImage2D later u8* texData = new u8[m_TextureSize * m_TextureSize * 4]; memset(texData, 0x00, m_TextureSize * m_TextureSize * 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); + g_Renderer.BindTexture(0, m_Texture->GetHandle()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_TextureSize, m_TextureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData); delete[] texData; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - { // Texture matrix: We want to map // world pos (0, y, 0) (i.e. bottom-left of first tile) @@ -139,7 +128,7 @@ void CTerritoryTexture::ConstructTexture(int unit) } } -void CTerritoryTexture::RecomputeTexture(int unit) +void CTerritoryTexture::RecomputeTexture() { // If the map was resized, delete and regenerate the texture if (m_Texture) @@ -150,7 +139,7 @@ void CTerritoryTexture::RecomputeTexture(int unit) } if (!m_Texture) - ConstructTexture(unit); + ConstructTexture(); PROFILE("recompute territory texture"); @@ -161,7 +150,7 @@ void CTerritoryTexture::RecomputeTexture(int unit) std::vector bitmap(m_MapSize * m_MapSize * 4); GenerateBitmap(cmpTerritoryManager->GetTerritoryGrid(), &bitmap[0], m_MapSize, m_MapSize); - g_Renderer.BindTexture(unit, m_Texture); + g_Renderer.BindTexture(0, m_Texture->GetHandle()); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize, m_MapSize, GL_RGBA, GL_UNSIGNED_BYTE, &bitmap[0]); } diff --git a/source/graphics/TerritoryTexture.h b/source/graphics/TerritoryTexture.h index a3c4f27128..b3db0b0654 100644 --- a/source/graphics/TerritoryTexture.h +++ b/source/graphics/TerritoryTexture.h @@ -16,8 +16,8 @@ */ #include "lib/ogl.h" - #include "maths/Matrix3D.h" +#include "renderer/backend/gl/Texture.h" class CSimulation2; template @@ -35,14 +35,6 @@ public: CTerritoryTexture(CSimulation2& simulation); ~CTerritoryTexture(); - /** - * Recomputes the territory texture if necessary, and binds it to the requested - * texture unit. - * Also switches the current active texture unit, and enables texturing on it. - * The texture is in 32-bit BGRA format. - */ - void BindTexture(int unit); - /** * Recomputes the territory texture if necessary, and returns the texture handle. * Also potentially switches the current active texture unit, and enables texturing on it. @@ -71,8 +63,8 @@ private: bool UpdateDirty(); void DeleteTexture(); - void ConstructTexture(int unit); - void RecomputeTexture(int unit); + void ConstructTexture(); + void RecomputeTexture(); void GenerateBitmap(const Grid& territories, u8* bitmap, ssize_t w, ssize_t h); @@ -80,7 +72,7 @@ private: size_t m_DirtyID; - GLuint m_Texture; + std::unique_ptr m_Texture; ssize_t m_MapSize; // tiles per side GLsizei m_TextureSize; // texels per side diff --git a/source/lib/external_libraries/opengles2_wrapper.h b/source/lib/external_libraries/opengles2_wrapper.h index a85ec5bb3e..e23f165972 100644 --- a/source/lib/external_libraries/opengles2_wrapper.h +++ b/source/lib/external_libraries/opengles2_wrapper.h @@ -76,6 +76,7 @@ // GL_OES_texture_border_clamp #define GL_CLAMP_TO_BORDER GL_CLAMP_TO_BORDER_OES +#define GL_TEXTURE_BORDER_COLOR GL_TEXTURE_BORDER_COLOR_OES // GL_OES_rgb8_rgba8 #define GL_RGBA8 GL_RGBA8_OES diff --git a/source/renderer/backend/Format.h b/source/renderer/backend/Format.h new file mode 100644 index 0000000000..26368cb27c --- /dev/null +++ b/source/renderer/backend/Format.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_FORMAT +#define INCLUDED_RENDERER_BACKEND_FORMAT + +namespace Renderer +{ + +namespace Backend +{ + +enum class Format +{ + UNDEFINED, + R8G8B8A8, + A8, +}; + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_FORMAT diff --git a/source/renderer/backend/Sampler.cpp b/source/renderer/backend/Sampler.cpp new file mode 100644 index 0000000000..fae961f137 --- /dev/null +++ b/source/renderer/backend/Sampler.cpp @@ -0,0 +1,49 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "Sampler.h" + +namespace Renderer +{ + +namespace Backend +{ + +namespace Sampler +{ + +Desc MakeDefaultSampler(Filter filter, AddressMode addressMode) +{ + Desc desc{}; + desc.minFilter = filter; + desc.magFilter = filter; + desc.mipFilter = filter; + desc.addressModeU = addressMode; + desc.addressModeV = addressMode; + desc.addressModeW = addressMode; + desc.anisotropyEnabled = false; + desc.mipLODBias = 0.0f; + return desc; +} + +} // namespace Sampler + +} // namespace Backend + +} // namespace Renderer diff --git a/source/renderer/backend/Sampler.h b/source/renderer/backend/Sampler.h new file mode 100644 index 0000000000..fc18987e28 --- /dev/null +++ b/source/renderer/backend/Sampler.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_SAMPLER +#define INCLUDED_RENDERER_BACKEND_SAMPLER + +#include "graphics/Color.h" + +#include + +namespace Renderer +{ + +namespace Backend +{ + +namespace Sampler +{ + +enum class Filter +{ + NEAREST, + LINEAR +}; + +enum class AddressMode +{ + REPEAT, + MIRRORED_REPEAT, + CLAMP_TO_EDGE, + CLAMP_TO_BORDER, +}; + +struct Desc +{ + Filter magFilter; + Filter minFilter; + Filter mipFilter; + AddressMode addressModeU; + AddressMode addressModeV; + AddressMode addressModeW; + float mipLODBias; + bool anisotropyEnabled; + float maxAnisotropy; + // When some filter is CLAMP_TO_BORDER. + CColor borderColor; +}; + +Desc MakeDefaultSampler(Filter filter, AddressMode addressMode); + +} // namespace Sampler + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_SAMPLER diff --git a/source/renderer/backend/gl/Texture.cpp b/source/renderer/backend/gl/Texture.cpp new file mode 100644 index 0000000000..b5914f5eb8 --- /dev/null +++ b/source/renderer/backend/gl/Texture.cpp @@ -0,0 +1,120 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "Texture.h" + +#include "lib/config2.h" +#include "renderer/backend/gl/Device.h" + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +namespace +{ + +GLint CalculateMinFilter(const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount) +{ + if (mipCount == 1) + return defaultSamplerDesc.minFilter == Sampler::Filter::LINEAR ? GL_LINEAR : GL_NEAREST; + + if (defaultSamplerDesc.minFilter == Sampler::Filter::LINEAR) + return defaultSamplerDesc.mipFilter == Sampler::Filter::LINEAR ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_NEAREST; + + return defaultSamplerDesc.mipFilter == Sampler::Filter::LINEAR ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST; +} + +GLint AddressModeToGLEnum(Sampler::AddressMode addressMode) +{ + switch (addressMode) + { + case Sampler::AddressMode::REPEAT: return GL_REPEAT; + case Sampler::AddressMode::MIRRORED_REPEAT: return GL_MIRRORED_REPEAT; + case Sampler::AddressMode::CLAMP_TO_EDGE: return GL_CLAMP_TO_EDGE; + case Sampler::AddressMode::CLAMP_TO_BORDER: return GL_CLAMP_TO_BORDER; + } + return GL_REPEAT; +} + +} // anonymous namespace + +// static +std::unique_ptr CTexture::Create2D(const Format format, + const uint32_t width, const uint32_t height, + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount) +{ + std::unique_ptr texture(new CTexture()); + + ENSURE(format != Format::UNDEFINED); + ENSURE(width > 0 && height > 0 && mipCount > 0); + + texture->m_Format = format; + texture->m_Width = width; + texture->m_Height = height; + texture->m_MipCount = mipCount; + + glGenTextures(1, &texture->m_Handle); + + glActiveTextureARB(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture->m_Handle); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, CalculateMinFilter(defaultSamplerDesc, mipCount)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, defaultSamplerDesc.magFilter == Sampler::Filter::LINEAR ? GL_LINEAR : GL_NEAREST); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, AddressModeToGLEnum(defaultSamplerDesc.addressModeU)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, AddressModeToGLEnum(defaultSamplerDesc.addressModeV)); + +#if !CONFIG2_GLES + if (defaultSamplerDesc.mipLODBias != 0.0f) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, defaultSamplerDesc.mipLODBias); +#endif + + if (defaultSamplerDesc.anisotropyEnabled) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, defaultSamplerDesc.maxAnisotropy); + + if (defaultSamplerDesc.addressModeU == Sampler::AddressMode::CLAMP_TO_BORDER || + defaultSamplerDesc.addressModeV == Sampler::AddressMode::CLAMP_TO_BORDER || + defaultSamplerDesc.addressModeW == Sampler::AddressMode::CLAMP_TO_BORDER) + { + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, defaultSamplerDesc.borderColor.AsFloatArray()); + } + + glBindTexture(GL_TEXTURE_2D, 0); + + return texture; +} + +CTexture::CTexture() = default; + +CTexture::~CTexture() +{ + if (m_Handle) + glDeleteTextures(1, &m_Handle); +} + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer diff --git a/source/renderer/backend/gl/Texture.h b/source/renderer/backend/gl/Texture.h new file mode 100644 index 0000000000..20143b9a9b --- /dev/null +++ b/source/renderer/backend/gl/Texture.h @@ -0,0 +1,74 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_GL_TEXTURE +#define INCLUDED_RENDERER_BACKEND_GL_TEXTURE + +#include "lib/ogl.h" +#include "renderer/backend/Format.h" +#include "renderer/backend/Sampler.h" + +#include + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +/** + * Represents a low-level GL texture, encapsulates all properties initialization. + */ +class CTexture +{ +public: + ~CTexture(); + + // GL before 3.3 doesn't support sampler objects, so each texture should have + // an own default sampler. + static std::unique_ptr Create2D(const Format format, + const uint32_t width, const uint32_t height, + const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount = 1); + + GLuint GetHandle() const { return m_Handle; } + + Format GetFormat() const { return m_Format; } + uint32_t GetWidth() const { return m_Width; } + uint32_t GetHeight() const { return m_Height; } + uint32_t GetMipCount() const { return m_MipCount; } + +private: + CTexture(); + + GLuint m_Handle = 0; + + Format m_Format = Format::UNDEFINED; + uint32_t m_Width = 0; + uint32_t m_Height = 0; + uint32_t m_MipCount = 0; +}; + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_GL_TEXTURE