Encapsulates GL texture creation in a separate class.

Tested By: Stan
Differential Revision: https://code.wildfiregames.com/D4389
This was SVN commit r26107.
This commit is contained in:
Vladislav Belov 2021-12-25 00:26:10 +00:00
parent 381bbb59e8
commit 57ba7c4a1c
12 changed files with 433 additions and 139 deletions

View File

@ -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<ICmpRangeManager> 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]);
}

View File

@ -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<Renderer::Backend::GL::CTexture>
m_Texture, m_TextureSmooth1, m_TextureSmooth2;
bool whichTex;
@ -107,4 +100,4 @@ private:
CMatrix3D m_MinimapTextureMatrix;
};
#endif // INCLUDED_LOSTEXTURE
#endif // INCLUDED_LOSTEXTURE

View File

@ -210,36 +210,35 @@ void CMiniMapTexture::CreateTextures(const CTerrain* terrain)
m_MapSize = terrain->GetVerticesPerSide();
m_TextureSize = static_cast<GLsizei>(round_up_to_pow2(static_cast<size_t>(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();

View File

@ -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<Renderer::Backend::GL::CTexture>
m_TerrainTexture, m_FinalTexture;
GLuint m_FinalTextureFBO = 0;

View File

@ -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<ICmpTerrain> 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<u8> 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]);
}

View File

@ -16,8 +16,8 @@
*/
#include "lib/ogl.h"
#include "maths/Matrix3D.h"
#include "renderer/backend/gl/Texture.h"
class CSimulation2;
template<typename T>
@ -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<u8>& territories, u8* bitmap, ssize_t w, ssize_t h);
@ -80,7 +72,7 @@ private:
size_t m_DirtyID;
GLuint m_Texture;
std::unique_ptr<Renderer::Backend::GL::CTexture> m_Texture;
ssize_t m_MapSize; // tiles per side
GLsizei m_TextureSize; // texels per side

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_RENDERER_BACKEND_SAMPLER
#define INCLUDED_RENDERER_BACKEND_SAMPLER
#include "graphics/Color.h"
#include <cstdint>
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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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> CTexture::Create2D(const Format format,
const uint32_t width, const uint32_t height,
const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount)
{
std::unique_ptr<CTexture> 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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <cstdint>
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<CTexture> 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