1
0
forked from 0ad/0ad

Moves PostProcManager and SkyManager to GL texture class continuing 57ba7c4a1c.

Tested By: Stan
Differential Revision: https://code.wildfiregames.com/D4398
This was SVN commit r26126.
This commit is contained in:
Vladislav Belov 2021-12-27 21:01:43 +00:00
parent c4de86973d
commit 0837e369cf
7 changed files with 206 additions and 124 deletions

View File

@ -40,11 +40,8 @@
CPostprocManager::CPostprocManager()
: m_IsInitialized(false), m_PingFbo(0), m_PongFbo(0), m_PostProcEffect(L"default"),
m_ColorTex1(0), m_ColorTex2(0), m_DepthTex(0), m_BloomFbo(0), m_BlurTex2a(0),
m_BlurTex2b(0), m_BlurTex4a(0), m_BlurTex4b(0), m_BlurTex8a(0), m_BlurTex8b(0),
m_WhichBuffer(true), m_Sharpness(0.3f), m_UsingMultisampleBuffer(false),
m_MultisampleFBO(0), m_MultisampleColorTex(0), m_MultisampleDepthTex(0),
m_MultisampleCount(0)
m_BloomFbo(0), m_WhichBuffer(true), m_Sharpness(0.3f), m_UsingMultisampleBuffer(false),
m_MultisampleFBO(0), m_MultisampleCount(0)
{
}
@ -63,18 +60,16 @@ void CPostprocManager::Cleanup()
if (m_BloomFbo) glDeleteFramebuffersEXT(1, &m_BloomFbo);
m_PingFbo = m_PongFbo = m_BloomFbo = 0;
if (m_ColorTex1) glDeleteTextures(1, &m_ColorTex1);
if (m_ColorTex2) glDeleteTextures(1, &m_ColorTex2);
if (m_DepthTex) glDeleteTextures(1, &m_DepthTex);
m_ColorTex1 = m_ColorTex2 = m_DepthTex = 0;
m_ColorTex1.reset();
m_ColorTex2.reset();
m_DepthTex.reset();
if (m_BlurTex2a) glDeleteTextures(1, &m_BlurTex2a);
if (m_BlurTex2b) glDeleteTextures(1, &m_BlurTex2b);
if (m_BlurTex4a) glDeleteTextures(1, &m_BlurTex4a);
if (m_BlurTex4b) glDeleteTextures(1, &m_BlurTex4b);
if (m_BlurTex8a) glDeleteTextures(1, &m_BlurTex8a);
if (m_BlurTex8b) glDeleteTextures(1, &m_BlurTex8b);
m_BlurTex2a = m_BlurTex2b = m_BlurTex4a = m_BlurTex4b = m_BlurTex8a = m_BlurTex8b = 0;
m_BlurTex2a.reset();
m_BlurTex2b.reset();
m_BlurTex4a.reset();
m_BlurTex4b.reset();
m_BlurTex8a.reset();
m_BlurTex8b.reset();
}
void CPostprocManager::Initialize()
@ -121,13 +116,13 @@ void CPostprocManager::RecreateBuffers()
Cleanup();
#define GEN_BUFFER_RGBA(name, w, h) \
glGenTextures(1, (GLuint*)&name); \
glBindTexture(GL_TEXTURE_2D, name); \
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); \
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);
name = Renderer::Backend::GL::CTexture::Create2D( \
Renderer::Backend::Format::R8G8B8A8, w, h, \
Renderer::Backend::Sampler::MakeDefaultSampler( \
Renderer::Backend::Sampler::Filter::LINEAR, \
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE)); \
glBindTexture(GL_TEXTURE_2D, name->GetHandle()); \
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Two fullscreen ping-pong textures.
GEN_BUFFER_RGBA(m_ColorTex1, m_Width, m_Height);
@ -149,17 +144,16 @@ void CPostprocManager::RecreateBuffers()
#undef GEN_BUFFER_RGBA
// Allocate the Depth/Stencil texture.
glGenTextures(1, (GLuint*)&m_DepthTex);
glBindTexture(GL_TEXTURE_2D, m_DepthTex);
m_DepthTex = Renderer::Backend::GL::CTexture::Create2D(
Renderer::Backend::Format::D24_S8, m_Width, m_Height,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE));
glBindTexture(GL_TEXTURE_2D, m_DepthTex->GetHandle());
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height,
0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
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);
glBindTexture(GL_TEXTURE_2D, 0);
@ -169,10 +163,10 @@ void CPostprocManager::RecreateBuffers()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_ColorTex1, 0);
GL_TEXTURE_2D, m_ColorTex1->GetHandle(), 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, m_DepthTex, 0);
GL_TEXTURE_2D, m_DepthTex->GetHandle(), 0);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
@ -184,10 +178,10 @@ void CPostprocManager::RecreateBuffers()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, m_ColorTex2, 0);
GL_TEXTURE_2D, m_ColorTex2->GetHandle(), 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D, m_DepthTex, 0);
GL_TEXTURE_2D, m_DepthTex->GetHandle(), 0);
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
@ -359,10 +353,10 @@ void CPostprocManager::ApplyBlur()
int width = m_Width, height = m_Height;
#define SCALE_AND_BLUR(tex1, tex2, temptex) \
ApplyBlurDownscale2x(tex1, tex2, width, height); \
ApplyBlurDownscale2x((tex1)->GetHandle(), (tex2)->GetHandle(), width, height); \
width /= 2; \
height /= 2; \
ApplyBlurGauss(tex2, temptex, width, height);
ApplyBlurGauss((tex2)->GetHandle(), (temptex)->GetHandle(), width, height);
// We do the same thing for each scale, incrementally adding more and more blur.
SCALE_AND_BLUR(m_WhichBuffer ? m_ColorTex1 : m_ColorTex2, m_BlurTex2a, m_BlurTex2b);
@ -437,15 +431,15 @@ void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
// We also bind a bunch of other textures and parameters, but since
// this only happens once per frame the overhead is negligible.
if (m_WhichBuffer)
shader->BindTexture(str_renderedTex, m_ColorTex1);
shader->BindTexture(str_renderedTex, m_ColorTex1->GetHandle());
else
shader->BindTexture(str_renderedTex, m_ColorTex2);
shader->BindTexture(str_renderedTex, m_ColorTex2->GetHandle());
shader->BindTexture(str_depthTex, m_DepthTex);
shader->BindTexture(str_depthTex, m_DepthTex->GetHandle());
shader->BindTexture(str_blurTex2, m_BlurTex2a);
shader->BindTexture(str_blurTex4, m_BlurTex4a);
shader->BindTexture(str_blurTex8, m_BlurTex8a);
shader->BindTexture(str_blurTex2, m_BlurTex2a->GetHandle());
shader->BindTexture(str_blurTex4, m_BlurTex4a->GetHandle());
shader->BindTexture(str_blurTex8, m_BlurTex8a->GetHandle());
shader->Uniform(str_width, m_Width);
shader->Uniform(str_height, m_Height);
@ -543,10 +537,10 @@ void CPostprocManager::ApplyPostproc()
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex->GetHandle(), 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_DepthTex->GetHandle(), 0);
}
@ -679,15 +673,28 @@ void CPostprocManager::CreateMultisampleBuffer()
{
glEnable(GL_MULTISAMPLE);
glGenTextures(1, &m_MultisampleColorTex);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex);
m_MultisampleColorTex = Renderer::Backend::GL::CTexture::Create(
Renderer::Backend::GL::CTexture::Type::TEXTURE_2D_MULTISAMPLE,
Renderer::Backend::Format::R8G8B8A8, m_Width, m_Height,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex->GetHandle());
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_RGBA, m_Width, m_Height, GL_TRUE);
// Allocate the Depth/Stencil texture.
glGenTextures(1, &m_MultisampleDepthTex);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex);
m_MultisampleDepthTex = Renderer::Backend::GL::CTexture::Create(
Renderer::Backend::GL::CTexture::Type::TEXTURE_2D_MULTISAMPLE,
Renderer::Backend::Format::D24_S8, m_Width, m_Height,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex->GetHandle());
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleCount, GL_DEPTH24_STENCIL8_EXT, m_Width, m_Height, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
ogl_WarnIfError();
@ -697,10 +704,10 @@ void CPostprocManager::CreateMultisampleBuffer()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_MultisampleFBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex, 0);
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleColorTex->GetHandle(), 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT,
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex, 0);
GL_TEXTURE_2D_MULTISAMPLE, m_MultisampleDepthTex->GetHandle(), 0);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
@ -722,10 +729,8 @@ void CPostprocManager::DestroyMultisampleBuffer()
return;
if (m_MultisampleFBO)
glDeleteFramebuffersEXT(1, &m_MultisampleFBO);
if (m_MultisampleColorTex)
glDeleteTextures(1, &m_MultisampleColorTex);
if (m_MultisampleDepthTex)
glDeleteTextures(1, &m_MultisampleDepthTex);
m_MultisampleColorTex.reset();
m_MultisampleDepthTex.reset();
glDisable(GL_MULTISAMPLE);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2020 Wildfire Games.
/* 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
@ -21,6 +21,7 @@
#include "graphics/ShaderTechniquePtr.h"
#include "lib/ogl.h"
#include "ps/CStr.h"
#include "renderer/backend/gl/Texture.h"
#include <vector>
@ -85,14 +86,16 @@ private:
GLuint m_PingFbo, m_PongFbo;
// Unique color textures for the framebuffers.
GLuint m_ColorTex1, m_ColorTex2;
std::unique_ptr<Renderer::Backend::GL::CTexture> m_ColorTex1, m_ColorTex2;
// The framebuffers share a depth/stencil texture.
GLuint m_DepthTex;
std::unique_ptr<Renderer::Backend::GL::CTexture> m_DepthTex;
float m_NearPlane, m_FarPlane;
// A framebuffer and textures x2 for each blur level we render.
GLuint m_BloomFbo, m_BlurTex2a, m_BlurTex2b, m_BlurTex4a, m_BlurTex4b, m_BlurTex8a, m_BlurTex8b;
GLuint m_BloomFbo;
std::unique_ptr<Renderer::Backend::GL::CTexture>
m_BlurTex2a, m_BlurTex2b, m_BlurTex4a, m_BlurTex4b, m_BlurTex8a, m_BlurTex8b;
// Indicates which of the ping-pong buffers is used for reading and which for drawing.
bool m_WhichBuffer;
@ -110,7 +113,8 @@ private:
CShaderTechniquePtr m_AATech;
bool m_UsingMultisampleBuffer;
GLuint m_MultisampleFBO;
GLuint m_MultisampleColorTex, m_MultisampleDepthTex;
std::unique_ptr<Renderer::Backend::GL::CTexture>
m_MultisampleColorTex, m_MultisampleDepthTex;
GLsizei m_MultisampleCount;
std::vector<GLsizei> m_AllowedSampleCounts;

View File

@ -27,6 +27,7 @@
#include "graphics/ShaderManager.h"
#include "graphics/Terrain.h"
#include "graphics/TextureManager.h"
#include "lib/bits.h"
#include "lib/ogl.h"
#include "lib/tex/tex.h"
#include "lib/timer.h"
@ -45,7 +46,7 @@
#include <algorithm>
SkyManager::SkyManager()
: m_RenderSky(true), m_SkyCubeMap(0)
: m_RenderSky(true)
{
CFG_GET_VAL("showsky", m_RenderSky);
}
@ -62,6 +63,7 @@ void SkyManager::LoadSkyTextures()
L"top",
L"top"
};
/*for (size_t i = 0; i < ARRAY_SIZE(m_SkyTexture); ++i)
{
VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(s_imageNames[i])+L".dds");
@ -77,10 +79,50 @@ void SkyManager::LoadSkyTextures()
// HACK: THE HORRIBLENESS HERE IS OVER 9000. The following code is a HUGE hack and will be removed completely
// as soon as all the hardcoded GL_TEXTURE_2D references are corrected in the TextureManager/OGL/tex libs.
glGenTextures(1, &m_SkyCubeMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_SkyCubeMap);
Tex textures[NUMBER_OF_TEXTURES + 1];
static const int types[] = {
for (size_t i = 0; i < NUMBER_OF_TEXTURES + 1; ++i)
{
VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i]) + L".dds");
std::shared_ptr<u8> file;
size_t fileSize;
if (g_VFS->LoadFile(path, file, fileSize) != INFO::OK)
{
path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i]) + L".dds.cached.dds");
if (g_VFS->LoadFile(path, file, fileSize) != INFO::OK)
{
LOGERROR("Error creating sky cubemap '%s', can't load file: '%s'.", m_SkySet.ToUTF8().c_str(), path.string8().c_str());
return;
}
}
textures[i].decode(file, fileSize);
textures[i].transform_to((textures[i].m_Flags | TEX_BOTTOM_UP | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS));
if (!is_pow2(textures[i].m_Width) || !is_pow2(textures[i].m_Height))
{
LOGERROR("Error creating sky cubemap '%s', cube textures should have power of 2 sizes.", m_SkySet.ToUTF8().c_str());
return;
}
if (textures[i].m_Width != textures[0].m_Width || textures[i].m_Height != textures[0].m_Height)
{
LOGERROR("Error creating sky cubemap '%s', cube textures have different sizes.", m_SkySet.ToUTF8().c_str());
return;
}
}
m_SkyCubeMap = Renderer::Backend::GL::CTexture::Create(Renderer::Backend::GL::CTexture::Type::TEXTURE_CUBE,
Renderer::Backend::Format::R8G8B8A8, textures[0].m_Width, textures[0].m_Height,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_SkyCubeMap->GetHandle());
static const int types[] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
@ -89,64 +131,37 @@ void SkyManager::LoadSkyTextures()
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
};
std::vector<u8> rotated;
for (size_t i = 0; i < NUMBER_OF_TEXTURES + 1; ++i)
{
VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i])+L".dds");
std::shared_ptr<u8> file;
size_t fileSize;
if (g_VFS->LoadFile(path, file, fileSize) != INFO::OK)
{
path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i])+L".dds.cached.dds");
if (g_VFS->LoadFile(path, file, fileSize) != INFO::OK)
{
glDeleteTextures(1, &m_SkyCubeMap);
LOGERROR("Error creating sky cubemap.");
return;
}
}
Tex tex;
tex.decode(file, fileSize);
tex.transform_to((tex.m_Flags | TEX_BOTTOM_UP | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS));
u8* data = tex.get_data();
u8* data = textures[i].get_data();
if (types[i] == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y || types[i] == GL_TEXTURE_CUBE_MAP_POSITIVE_Y)
{
std::vector<u8> rotated(tex.m_DataSize);
rotated.reserve(textures[i].m_DataSize);
for (size_t y = 0; y < tex.m_Height; ++y)
for (size_t y = 0; y < textures[i].m_Height; ++y)
{
for (size_t x = 0; x < tex.m_Width; ++x)
for (size_t x = 0; x < textures[i].m_Width; ++x)
{
size_t invx = y, invy = tex.m_Width-x-1;
const size_t invX = y;
const size_t invY = textures[i].m_Width - x - 1;
rotated[(y*tex.m_Width + x) * 4 + 0] = data[(invy*tex.m_Width + invx) * 4 + 0];
rotated[(y*tex.m_Width + x) * 4 + 1] = data[(invy*tex.m_Width + invx) * 4 + 1];
rotated[(y*tex.m_Width + x) * 4 + 2] = data[(invy*tex.m_Width + invx) * 4 + 2];
rotated[(y*tex.m_Width + x) * 4 + 3] = data[(invy*tex.m_Width + invx) * 4 + 3];
rotated[(y * textures[i].m_Width + x) * 4 + 0] = data[(invY * textures[i].m_Width + invX) * 4 + 0];
rotated[(y * textures[i].m_Width + x) * 4 + 1] = data[(invY * textures[i].m_Width + invX) * 4 + 1];
rotated[(y * textures[i].m_Width + x) * 4 + 2] = data[(invY * textures[i].m_Width + invX) * 4 + 2];
rotated[(y * textures[i].m_Width + x) * 4 + 3] = data[(invY * textures[i].m_Width + invX) * 4 + 3];
}
}
glTexImage2D(types[i], 0, GL_RGBA, tex.m_Width, tex.m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rotated[0]);
glTexImage2D(types[i], 0, GL_RGBA, textures[i].m_Width, textures[i].m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &rotated[0]);
}
else
{
glTexImage2D(types[i], 0, GL_RGBA, tex.m_Width, tex.m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glTexImage2D(types[i], 0, GL_RGBA, textures[i].m_Width, textures[i].m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#if CONFIG2_GLES
#warning TODO: fix SkyManager::LoadSkyTextures for GLES
#else
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
#endif
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
///////////////////////////////////////////////////////////////////////////
}
@ -159,11 +174,7 @@ void SkyManager::SetSkySet(const CStrW& newSet)
if (newSet == m_SkySet)
return;
if (m_SkyCubeMap)
{
glDeleteTextures(1, &m_SkyCubeMap);
m_SkyCubeMap = 0;
}
m_SkyCubeMap.reset();
m_SkySet = newSet;
@ -208,7 +219,7 @@ void SkyManager::RenderSky()
// everything else.
// Do nothing unless SetSkySet was called
if (m_SkySet.empty())
if (m_SkySet.empty() || !m_SkyCubeMap)
return;
glDepthMask(GL_FALSE);
@ -219,7 +230,7 @@ void SkyManager::RenderSky()
g_Renderer.GetShaderManager().LoadEffect(str_sky_simple);
skytech->BeginPass();
CShaderProgramPtr shader = skytech->GetShader();
shader->BindTexture(str_baseTex, m_SkyCubeMap);
shader->BindTexture(str_baseTex, m_SkyCubeMap->GetHandle());
// Translate so the sky center is at the camera space origin.
CMatrix3D translate;

View File

@ -23,6 +23,7 @@
#define INCLUDED_SKYMANAGER
#include "graphics/Texture.h"
#include "renderer/backend/gl/Texture.h"
#include <vector>
@ -49,7 +50,7 @@ public:
GLuint GetSkyCube()
{
return m_SkyCubeMap;
return m_SkyCubeMap->GetHandle();
}
/**
@ -95,7 +96,7 @@ private:
// Sky textures
CTexturePtr m_SkyTexture[NUMBER_OF_TEXTURES];
GLuint m_SkyCubeMap;
std::unique_ptr<Renderer::Backend::GL::CTexture> m_SkyCubeMap;
};

View File

@ -31,6 +31,7 @@ enum class Format
A8,
D16,
D24,
D24_S8,
D32
};

View File

@ -58,12 +58,42 @@ GLint AddressModeToGLEnum(Sampler::AddressMode addressMode)
return GL_REPEAT;
}
GLenum TypeToGLEnum(CTexture::Type type)
{
GLenum target = GL_TEXTURE_2D;
switch (type)
{
case CTexture::Type::TEXTURE_2D:
target = GL_TEXTURE_2D;
break;
case CTexture::Type::TEXTURE_2D_MULTISAMPLE:
#if CONFIG2_GLES
ENSURE(false && "Multisample textures are unsupported on GLES");
#else
target = GL_TEXTURE_2D_MULTISAMPLE;
#endif
break;
case CTexture::Type::TEXTURE_CUBE:
target = GL_TEXTURE_CUBE_MAP;
break;
}
return target;
}
} // 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)
{
return Create(Type::TEXTURE_2D, format, width, height, defaultSamplerDesc, mipCount);
}
// static
std::unique_ptr<CTexture> CTexture::Create(const Type type, 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());
@ -77,34 +107,50 @@ std::unique_ptr<CTexture> CTexture::Create2D(const Format format,
glGenTextures(1, &texture->m_Handle);
ogl_WarnIfError();
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);
const GLenum target = TypeToGLEnum(type);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, AddressModeToGLEnum(defaultSamplerDesc.addressModeU));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, AddressModeToGLEnum(defaultSamplerDesc.addressModeV));
glBindTexture(target, texture->m_Handle);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, CalculateMinFilter(defaultSamplerDesc, mipCount));
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, defaultSamplerDesc.magFilter == Sampler::Filter::LINEAR ? GL_LINEAR : GL_NEAREST);
ogl_WarnIfError();
glTexParameteri(target, GL_TEXTURE_WRAP_S, AddressModeToGLEnum(defaultSamplerDesc.addressModeU));
glTexParameteri(target, GL_TEXTURE_WRAP_T, AddressModeToGLEnum(defaultSamplerDesc.addressModeV));
#if !CONFIG2_GLES
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipCount - 1);
if (type == Type::TEXTURE_CUBE)
glTexParameteri(target, GL_TEXTURE_WRAP_R, AddressModeToGLEnum(defaultSamplerDesc.addressModeW));
#endif
ogl_WarnIfError();
#if !CONFIG2_GLES
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipCount - 1);
if (defaultSamplerDesc.mipLODBias != 0.0f)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, defaultSamplerDesc.mipLODBias);
glTexParameteri(target, GL_TEXTURE_LOD_BIAS, defaultSamplerDesc.mipLODBias);
#endif // !CONFIG2_GLES
if (defaultSamplerDesc.anisotropyEnabled && ogl_tex_has_anisotropy())
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, defaultSamplerDesc.maxAnisotropy);
if (type == Type::TEXTURE_2D && defaultSamplerDesc.anisotropyEnabled && ogl_tex_has_anisotropy())
glTexParameterf(target, 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());
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, defaultSamplerDesc.borderColor.AsFloatArray());
}
glBindTexture(GL_TEXTURE_2D, 0);
ogl_WarnIfError();
glBindTexture(target, 0);
return texture;
}

View File

@ -39,16 +39,29 @@ namespace GL
class CTexture
{
public:
enum class Type
{
TEXTURE_2D,
TEXTURE_2D_MULTISAMPLE,
TEXTURE_CUBE
};
~CTexture();
// GL before 3.3 doesn't support sampler objects, so each texture should have
// an own default sampler.
static std::unique_ptr<CTexture> Create(const Type type, const Format format,
const uint32_t width, const uint32_t height,
const Sampler::Desc& defaultSamplerDesc, const uint32_t mipCount);
// Shorthands for particular types.
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; }
Type GetType() const { return m_Type; }
Format GetFormat() const { return m_Format; }
uint32_t GetWidth() const { return m_Width; }
uint32_t GetHeight() const { return m_Height; }
@ -59,6 +72,7 @@ private:
GLuint m_Handle = 0;
Type m_Type = Type::TEXTURE_2D;
Format m_Format = Format::UNDEFINED;
uint32_t m_Width = 0;
uint32_t m_Height = 0;