Index: ps/trunk/source/renderer/PostprocManager.h =================================================================== --- ps/trunk/source/renderer/PostprocManager.h +++ ps/trunk/source/renderer/PostprocManager.h @@ -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 @@ -85,14 +86,16 @@ GLuint m_PingFbo, m_PongFbo; // Unique color textures for the framebuffers. - GLuint m_ColorTex1, m_ColorTex2; + std::unique_ptr m_ColorTex1, m_ColorTex2; // The framebuffers share a depth/stencil texture. - GLuint m_DepthTex; + std::unique_ptr 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 + 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 @@ CShaderTechniquePtr m_AATech; bool m_UsingMultisampleBuffer; GLuint m_MultisampleFBO; - GLuint m_MultisampleColorTex, m_MultisampleDepthTex; + std::unique_ptr + m_MultisampleColorTex, m_MultisampleDepthTex; GLsizei m_MultisampleCount; std::vector m_AllowedSampleCounts; Index: ps/trunk/source/renderer/PostprocManager.cpp =================================================================== --- ps/trunk/source/renderer/PostprocManager.cpp +++ ps/trunk/source/renderer/PostprocManager.cpp @@ -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 @@ 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; - - 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_ColorTex1.reset(); + m_ColorTex2.reset(); + m_DepthTex.reset(); + + 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 @@ 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 @@ #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 @@ 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 @@ 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 @@ 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 @@ // 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 @@ } 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 @@ { 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 @@ 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 @@ 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); } Index: ps/trunk/source/renderer/SkyManager.h =================================================================== --- ps/trunk/source/renderer/SkyManager.h +++ ps/trunk/source/renderer/SkyManager.h @@ -23,6 +23,7 @@ #define INCLUDED_SKYMANAGER #include "graphics/Texture.h" +#include "renderer/backend/gl/Texture.h" #include @@ -49,7 +50,7 @@ GLuint GetSkyCube() { - return m_SkyCubeMap; + return m_SkyCubeMap->GetHandle(); } /** @@ -95,7 +96,7 @@ // Sky textures CTexturePtr m_SkyTexture[NUMBER_OF_TEXTURES]; - GLuint m_SkyCubeMap; + std::unique_ptr m_SkyCubeMap; }; Index: ps/trunk/source/renderer/SkyManager.cpp =================================================================== --- ps/trunk/source/renderer/SkyManager.cpp +++ ps/trunk/source/renderer/SkyManager.cpp @@ -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 SkyManager::SkyManager() - : m_RenderSky(true), m_SkyCubeMap(0) + : m_RenderSky(true) { CFG_GET_VAL("showsky", m_RenderSky); } @@ -62,6 +63,7 @@ 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,76 +79,89 @@ // 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); - - static const int types[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - }; + Tex textures[NUMBER_OF_TEXTURES + 1]; 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"); + VfsPath path = VfsPath("art/textures/skies") / m_SkySet / (Path::String(images[i]) + L".dds"); std::shared_ptr 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"); + 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."); + LOGERROR("Error creating sky cubemap '%s', can't load file: '%s'.", m_SkySet.ToUTF8().c_str(), path.string8().c_str()); return; } } - Tex tex; - tex.decode(file, fileSize); + textures[i].decode(file, fileSize); + textures[i].transform_to((textures[i].m_Flags | TEX_BOTTOM_UP | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)); - tex.transform_to((tex.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; + } + } - u8* data = tex.get_data(); + 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, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y + }; + + std::vector rotated; + for (size_t i = 0; i < NUMBER_OF_TEXTURES + 1; ++i) + { + 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 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 @@ 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 @@ // 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 @@ 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; Index: ps/trunk/source/renderer/backend/Format.h =================================================================== --- ps/trunk/source/renderer/backend/Format.h +++ ps/trunk/source/renderer/backend/Format.h @@ -31,6 +31,7 @@ A8, D16, D24, + D24_S8, D32 }; Index: ps/trunk/source/renderer/backend/gl/Texture.h =================================================================== --- ps/trunk/source/renderer/backend/gl/Texture.h +++ ps/trunk/source/renderer/backend/gl/Texture.h @@ -39,16 +39,29 @@ 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 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 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 @@ 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; Index: ps/trunk/source/renderer/backend/gl/Texture.cpp =================================================================== --- ps/trunk/source/renderer/backend/gl/Texture.cpp +++ ps/trunk/source/renderer/backend/gl/Texture.cpp @@ -58,6 +58,28 @@ 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 @@ -65,6 +87,14 @@ 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::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 texture(new CTexture()); ENSURE(format != Format::UNDEFINED); @@ -77,34 +107,50 @@ 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); + + 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(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, AddressModeToGLEnum(defaultSamplerDesc.addressModeU)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, AddressModeToGLEnum(defaultSamplerDesc.addressModeV)); + 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; }