From 8f50bb4f20b66b0c34b90a24abd93dede9c4c00c Mon Sep 17 00:00:00 2001 From: Shu Date: Sun, 11 Oct 2020 20:07:21 +0200 Subject: [PATCH] Skip mipmap gen on GL --- src/client/Client.cpp | 2 +- src/client/config.hpp | 8 ++++---- src/client/render/Renderer.hpp | 9 ++++++--- src/client/render/UI.cpp | 6 ++++-- src/client/render/api/Images.hpp | 1 + src/client/render/gl/Renderer.cpp | 9 ++++----- src/client/render/gl/texture.cpp | 27 +++++++++++++++----------- src/client/render/vk/CommandCenter.cpp | 2 +- src/client/render/vk/api/Images.cpp | 2 +- 9 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index bf41153..34fd8fc 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -102,7 +102,7 @@ void Client::run(server_handle* const localHandle) { pipeline->reloadShaders(options.renderer.voxel); } if(actions && render::UI::Actions::RendererTextures) { - pipeline->reloadTextures(options.renderer.textures, options.renderer.mipMapLOD, options.renderer.anisotropy); + pipeline->reloadTextures(options.renderer.textures, options.renderer.getMipmapLodBias(), options.renderer.getAnisotropy()); } if(actions && render::UI::Actions::World) { //FIXME: server options world->setOptions(options.world); diff --git a/src/client/config.hpp b/src/client/config.hpp index 15e9953..3575eca 100644 --- a/src/client/config.hpp +++ b/src/client/config.hpp @@ -35,8 +35,8 @@ public: preferVulkan = config["render"]["prefer_vulkan"].value_or(preferVulkan); renderer.textures = config["render"]["textures"].value_or(renderer.textures); - renderer.mipMapLOD = config["render"]["texture_quality"].value_or(renderer.mipMapLOD); - renderer.anisotropy = config["render"]["texture_angular_quality"].value_or(renderer.anisotropy); + renderer.textureQuality = config["render"]["texture_quality"].value_or(renderer.textureQuality); + renderer.textureSharpness = config["render"]["texture_angular_quality"].value_or(renderer.textureSharpness); renderer.voxel.pbr = config["render"]["pbr"].value_or(renderer.voxel.pbr); renderer.voxel.triplanar = config["render"]["triplanar"].value_or(renderer.voxel.triplanar); renderer.voxel.stochastic = config["render"]["stochastic"].value_or(renderer.voxel.stochastic); @@ -103,8 +103,8 @@ public: config.insert_or_assign("render", toml::table({ {"prefer_vulkan", preferVulkan}, {"textures", renderer.textures}, - {"texture_quality", renderer.mipMapLOD}, - {"texture_angular_quality", renderer.anisotropy}, + {"texture_quality", renderer.textureQuality}, + {"texture_angular_quality", renderer.textureSharpness}, {"pbr", renderer.voxel.pbr}, {"triplanar", renderer.voxel.triplanar}, {"stochastic", renderer.voxel.stochastic}, diff --git a/src/client/render/Renderer.hpp b/src/client/render/Renderer.hpp index a6c994a..085ce81 100644 --- a/src/client/render/Renderer.hpp +++ b/src/client/render/Renderer.hpp @@ -22,7 +22,7 @@ struct passOptions { /// Transform texture UV bool stochastic = false; /// Active geometry pass - bool geometry = false; + bool geometry = true; /// Blend voxel with mixed materials (requires geometry) bool blend = true; /// Depth fog @@ -44,14 +44,17 @@ struct renderOptions { /// Texture pack name std::string textures = "1024-realistic"; /// Textures quality - float mipMapLOD = -.5; + int textureQuality = 100; /// Textures anisotropic mapping - int anisotropy = 0; + int textureSharpness = 0; /// Depth color glm::vec4 clear_color; /// Parallel processing frames /// Incease FPS but also a bit latency (Vulkan only) int inFlightFrames = 2; + + constexpr float getMipmapLodBias() const { return 1 - (textureQuality / 100.f); } + constexpr int getAnisotropy() const { return textureSharpness >= 1 ? (1 << (textureSharpness - 1)) : 0; } }; /// Rendering plateform interface diff --git a/src/client/render/UI.cpp b/src/client/render/UI.cpp index 4763be6..1be726e 100644 --- a/src/client/render/UI.cpp +++ b/src/client/render/UI.cpp @@ -106,10 +106,12 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons actions |= Actions::FillMode; } ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select - if (ImGui::SliderFloat("LOD", &options.renderer.mipMapLOD, -1, 1) | - ImGui::SliderInt("Anisotropy", &options.renderer.anisotropy, 0, 8)) { + if (ImGui::SliderInt("Quality", &options.renderer.textureQuality, 0, 200, "%d%%") | + ImGui::SliderInt("Sharpness", &options.renderer.textureSharpness, 0, 8)) { actions |= Actions::RendererTextures; } + if(ImGui::IsItemHovered()) + ImGui::SetTooltip("Better texture quality especially at low angles"); ImGui::End(); } diff --git a/src/client/render/api/Images.hpp b/src/client/render/api/Images.hpp index f0d9557..f6f61bb 100644 --- a/src/client/render/api/Images.hpp +++ b/src/client/render/api/Images.hpp @@ -108,6 +108,7 @@ public: Wrap wrap = Wrap::MIRRORED_REPEAT; int anisotropy = 0; bool mipmap = true; + float mipmapLod = 0; }; /// Only supports dds files diff --git a/src/client/render/gl/Renderer.cpp b/src/client/render/gl/Renderer.cpp index 0432d33..58ccf43 100644 --- a/src/client/render/gl/Renderer.cpp +++ b/src/client/render/gl/Renderer.cpp @@ -51,7 +51,7 @@ Renderer::Renderer(const renderOptions& options): IndicatorPass = std::make_unique(); FogColor = glm::vec3(options.clear_color.x, options.clear_color.y, options.clear_color.z); - loadTextures(options.textures, options.mipMapLOD, options.anisotropy); + loadTextures(options.textures, options.getMipmapLodBias(), options.getAnisotropy()); } Renderer::~Renderer() { @@ -170,10 +170,9 @@ void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD, flo for(const auto& texture: world::materials::textures) { terrainTextures.emplace_back(texturePath + "/terrain/" + texture); } - const auto ani = anisotropy >= 1 ? (1 << (static_cast(anisotropy)-1)) : 0; - TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD, ani); - NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD, ani); - HOSAtlas = pass::Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD, ani); + TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD, anisotropy); + NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD, anisotropy); + HOSAtlas = pass::Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD, anisotropy); Skybox = pass::Program::loadTextureCube(texturePath + "/sky/Space_tray"); } diff --git a/src/client/render/gl/texture.cpp b/src/client/render/gl/texture.cpp index e159832..a861404 100644 --- a/src/client/render/gl/texture.cpp +++ b/src/client/render/gl/texture.cpp @@ -88,8 +88,8 @@ GLuint loadDDS(const std::string& imagepath, bool linear){ { unsigned int size = ((width+3)/4)*((height+3)/4)*blockSize; glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, - 0, size, buffer + offset); - + 0, size, buffer + offset); + offset += size; width /= 2; height /= 2; @@ -98,15 +98,13 @@ GLuint loadDDS(const std::string& imagepath, bool linear){ if(width < 1) width = 1; if(height < 1) height = 1; - } + } free(buffer); glTextureParameteri(textureID, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST); glTextureParameteri(textureID, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST); - glGenerateTextureMipmap(textureID); - return textureID; } @@ -164,13 +162,22 @@ GLuint loadDDSArray(const std::vector& imagepaths, float mipMapLOD, // Create one OpenGL texture array GLuint textureID; glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &textureID); - glTextureStorage3D(textureID, 1 + std::floor(std::log2(std::max(mainWidth, mainHeight))), mainFormat, mainWidth, mainHeight, imagepaths.size()); + uint levels = 1 + std::floor(std::log2(std::max(mainWidth, mainHeight))); + glTextureStorage3D(textureID, levels, mainFormat, mainWidth, mainHeight, imagepaths.size()); ushort layer = 0; - for (imagepath = imagepaths.begin(); imagepath != imagepaths.end(); ++imagepath, ++layer) - { + for (imagepath = imagepaths.begin(); imagepath != imagepaths.end(); ++imagepath, ++layer) { GLuint subTextureID = loadDDS(*imagepath, false); - glCopyImageSubData(subTextureID, GL_TEXTURE_2D, 0, 0, 0, 0, textureID, GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, mainWidth, mainHeight, 1); + auto width = mainWidth; + auto height = mainHeight; + for (uint level = 0; level < levels; level++) { + glCopyImageSubData(subTextureID, GL_TEXTURE_2D, level, 0, 0, 0, textureID, GL_TEXTURE_2D_ARRAY, level, 0, 0, layer, width, height, 1); + width /= 2; + height /= 2; + + if(width < 1) width = 1; + if(height < 1) height = 1; + } glDeleteTextures(1, &subTextureID); } @@ -179,8 +186,6 @@ GLuint loadDDSArray(const std::vector& imagepaths, float mipMapLOD, glTextureParameterf(textureID, GL_TEXTURE_LOD_BIAS, mipMapLOD); glTextureParameterf(textureID, GL_TEXTURE_MAX_ANISOTROPY, anisotropy); - glGenerateTextureMipmap(textureID); - return textureID; } diff --git a/src/client/render/vk/CommandCenter.cpp b/src/client/render/vk/CommandCenter.cpp index e9e98d1..d815329 100644 --- a/src/client/render/vk/CommandCenter.cpp +++ b/src/client/render/vk/CommandCenter.cpp @@ -29,7 +29,7 @@ CommandCenter::CommandCenter(VkDevice device, const PhysicalDeviceInfo &info, co } } { // Texture sampler (const) - sampleTexture = Texture::LoadFromFile(TEXTURES_DIR "1024-realistic/terrain/Mapl.dds", {true, true, Texture::Wrap::MIRRORED_REPEAT, opt.anisotropy}); + sampleTexture = Texture::LoadFromFile(TEXTURES_DIR "1024-realistic/terrain/Mapl.dds", {true, true, Texture::Wrap::MIRRORED_REPEAT, opt.getAnisotropy(), true, opt.getMipmapLodBias()}); if (!sampleTexture) { FATAL("Failed to create texture sampler!"); } diff --git a/src/client/render/vk/api/Images.cpp b/src/client/render/vk/api/Images.cpp index 49ff48b..998c2e2 100644 --- a/src/client/render/vk/api/Images.cpp +++ b/src/client/render/vk/api/Images.cpp @@ -136,7 +136,7 @@ std::unique_ptr Texture::LoadFromFile(const std::string& path, const sa samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS; samplerInfo.mipmapMode = props.minLinear ? VK_SAMPLER_MIPMAP_MODE_LINEAR : VK_SAMPLER_MIPMAP_MODE_NEAREST; - samplerInfo.mipLodBias = 0.0f; //TODO: + samplerInfo.mipLodBias = std::min(Allocator::GetDefault()->getCapabilities().maxLodBias, props.mipmapLod); samplerInfo.minLod = 0.0f; samplerInfo.maxLod = props.mipmap ? header.mipmapLevels : 0.0f;