From 3c0c1717a98951f6e0809911aaef12be3d29d37b Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 28 Mar 2024 07:43:33 +0300 Subject: [PATCH] Fix red-green normal map handling for terrain --- apps/opencs/model/world/data.cpp | 1 - apps/openmw/mwrender/renderingmanager.cpp | 1 - components/sceneutil/util.cpp | 14 ++++++++++++++ components/sceneutil/util.hpp | 2 ++ components/shader/shadervisitor.cpp | 15 +++++---------- components/terrain/material.cpp | 15 ++++++++++++++- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4198e1b980..470ce04131 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -152,7 +152,6 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data mResourceSystem = std::make_unique(mVFS.get(), expiryDelay, &mEncoder.getStatelessEncoder()); - // FIXME: this is severely out of date (see #7595) Shader::ShaderManager::DefineMap defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines(); Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines(); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index d5c5321f8e..dc71e455b2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -446,7 +446,6 @@ namespace MWRender globalDefines["useOVR_multiview"] = "0"; globalDefines["numViews"] = "1"; globalDefines["disableNormals"] = "1"; - globalDefines["reconstructNormalZ"] = "0"; for (auto itr = lightDefines.begin(); itr != lightDefines.end(); itr++) globalDefines[itr->first] = itr->second; diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index ab600de11d..a5629ee092 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -286,4 +286,18 @@ namespace SceneUtil mOperationQueue->add(operation); } + bool isRedGreenPixelFormat(GLenum format) + { + switch (format) + { + case GL_RG: + case GL_RG_INTEGER: + case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: + case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: + return true; + } + + return false; + } + } diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index 29fee09176..0f4b82bbe0 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -112,6 +112,8 @@ namespace SceneUtil protected: osg::ref_ptr mOperationQueue; }; + + bool isRedGreenPixelFormat(GLenum format); } #endif diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 3867f1f43e..600e35a22a 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -445,17 +446,11 @@ namespace Shader if (normalMap != nullptr && normalMap->getImage(0)) { - // Special handling for red-green normal maps (e.g. BC5 or R8G8). - switch (normalMap->getImage(0)->getPixelFormat()) + // Special handling for red-green normal maps (e.g. BC5 or R8G8) + if (SceneUtil::isRedGreenPixelFormat(normalMap->getImage(0)->getPixelFormat())) { - case GL_RG: - case GL_RG_INTEGER: - case GL_COMPRESSED_RED_GREEN_RGTC2_EXT: - case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: - { - mRequirements.back().mReconstructNormalZ = true; - mRequirements.back().mNormalHeight = false; - } + mRequirements.back().mReconstructNormalZ = true; + mRequirements.back().mNormalHeight = false; } } diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index fafe2dcb58..10dbeb9838 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -271,18 +272,30 @@ namespace Terrain stateset->addUniform(UniformCollection::value().mBlendMap); } + bool parallax = it->mNormalMap && it->mParallax; + bool reconstructNormalZ = false; + if (it->mNormalMap) { stateset->setTextureAttributeAndModes(2, it->mNormalMap); stateset->addUniform(UniformCollection::value().mNormalMap); + + // Special handling for red-green normal maps (e.g. BC5 or R8G8). + const osg::Image* image = it->mNormalMap->getImage(0); + if (image && SceneUtil::isRedGreenPixelFormat(image->getPixelFormat())) + { + reconstructNormalZ = true; + parallax = false; + } } Shader::ShaderManager::DefineMap defineMap; defineMap["normalMap"] = (it->mNormalMap) ? "1" : "0"; defineMap["blendMap"] = (!blendmaps.empty()) ? "1" : "0"; defineMap["specularMap"] = it->mSpecular ? "1" : "0"; - defineMap["parallax"] = (it->mNormalMap && it->mParallax) ? "1" : "0"; + defineMap["parallax"] = parallax ? "1" : "0"; defineMap["writeNormals"] = (it == layers.end() - 1) ? "1" : "0"; + defineMap["reconstructNormalZ"] = reconstructNormalZ ? "1" : "0"; Stereo::shaderStereoDefines(defineMap); stateset->setAttributeAndModes(shaderManager.getProgram("terrain", defineMap));