mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-07 19:23:04 +02:00
Introducing the Normal fitting algorithm for better normal in the deferred buffer
This commit is contained in:
parent
a4f105f6c3
commit
95682e6270
8 changed files with 47 additions and 3 deletions
BIN
interface/resources/images/normalFittingScale.dds
Normal file
BIN
interface/resources/images/normalFittingScale.dds
Normal file
Binary file not shown.
|
@ -21,6 +21,23 @@ uniform float glowIntensity;
|
|||
// the alpha threshold
|
||||
uniform float alphaThreshold;
|
||||
|
||||
uniform sampler2D normalFittingMap;
|
||||
|
||||
vec3 bestFitNormal(vec3 normal) {
|
||||
vec3 absNorm = abs(normal);
|
||||
float maxNAbs = max(absNorm.z, max(absNorm.x, absNorm.y));
|
||||
|
||||
vec2 texcoord = (absNorm.z < maxNAbs ?
|
||||
(absNorm.y < maxNAbs ? absNorm.yz : absNorm.xz) :
|
||||
absNorm.xy);
|
||||
texcoord = (texcoord.x < texcoord.y ? texcoord.yx : texcoord.xy);
|
||||
texcoord.y /= texcoord.x;
|
||||
vec3 cN = normal / maxNAbs;
|
||||
float fittingScale = texture2D(normalFittingMap, texcoord).a;
|
||||
cN *= fittingScale;
|
||||
return (cN * 0.5 + 0.5);
|
||||
}
|
||||
|
||||
float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
|
||||
return mix(alpha * glowIntensity, 1.0 - alpha * glowIntensity, step(mapAlpha, alphaThreshold));
|
||||
}
|
||||
|
@ -33,7 +50,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular,
|
|||
discard;
|
||||
}
|
||||
_fragColor0 = vec4(diffuse.rgb, alpha);
|
||||
_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
_fragColor1 = vec4(bestFitNormal(normal), 1.0);
|
||||
_fragColor2 = vec4(specular, shininess / 128.0);
|
||||
}
|
||||
|
||||
|
@ -44,7 +61,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s
|
|||
|
||||
_fragColor0 = vec4(diffuse.rgb, alpha);
|
||||
//_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||
_fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);
|
||||
_fragColor1 = vec4(bestFitNormal(normal), 0.5);
|
||||
_fragColor2 = vec4(emissive, shininess / 128.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ void DeferredLightingEffect::init(AbstractViewStateInterface* viewState) {
|
|||
_emissiveShader = gpu::ShaderPointer(gpu::Shader::createProgram(VS, PSEmissive));
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
|
||||
gpu::Shader::makeProgram(*_simpleShader, slotBindings);
|
||||
gpu::Shader::makeProgram(*_emissiveShader, slotBindings);
|
||||
|
||||
|
@ -151,6 +152,8 @@ void DeferredLightingEffect::bindSimpleProgram(gpu::Batch& batch, bool textured,
|
|||
// If it is not textured, bind white texture and keep using textured pipeline
|
||||
batch.setResourceTexture(0, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
|
||||
batch.setResourceTexture(NORMAL_FITTING_MAP_SLOT, DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
|
||||
void DeferredLightingEffect::renderSolidSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color) {
|
||||
|
|
|
@ -30,7 +30,8 @@ class DeferredLightingEffect : public Dependency {
|
|||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
|
||||
static const int NORMAL_FITTING_MAP_SLOT = 10;
|
||||
|
||||
void init(AbstractViewStateInterface* viewState);
|
||||
|
||||
/// Sets up the state necessary to render static untextured geometry with the simple program.
|
||||
|
|
|
@ -105,6 +105,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
|
|||
slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), 4));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT));
|
||||
|
||||
|
||||
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
@ -180,6 +182,8 @@ void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model:
|
|||
locations.emissiveParams = program->getUniforms().findLocation("emissiveParams");
|
||||
locations.glowIntensity = program->getUniforms().findLocation("glowIntensity");
|
||||
|
||||
locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap");
|
||||
|
||||
locations.specularTextureUnit = program->getTextures().findLocation("specularMap");
|
||||
locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap");
|
||||
|
||||
|
@ -1864,6 +1868,10 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
|||
const float DEFAULT_GLOW_INTENSITY = 1.0f; // FIXME - glow is removed
|
||||
batch._glUniform1f(locations->glowIntensity, DEFAULT_GLOW_INTENSITY);
|
||||
}
|
||||
|
||||
if ((locations->normalFittingMapUnit > -1)) {
|
||||
batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get<TextureCache>()->getNormalFittingTexture());
|
||||
}
|
||||
}
|
||||
|
||||
bool Model::initWhenReady(render::ScenePointer scene) {
|
||||
|
|
|
@ -350,6 +350,7 @@ private:
|
|||
int emissiveTextureUnit;
|
||||
int emissiveParams;
|
||||
int glowIntensity;
|
||||
int normalFittingMapUnit;
|
||||
int materialBufferUnit;
|
||||
int clusterMatrices;
|
||||
int clusterIndices;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <QRunnable>
|
||||
#include <QThreadPool>
|
||||
#include <qimagereader.h>
|
||||
#include "PathUtils.h"
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
|
@ -129,6 +130,14 @@ const gpu::TexturePointer& TextureCache::getBlackTexture() {
|
|||
return _blackTexture;
|
||||
}
|
||||
|
||||
|
||||
const gpu::TexturePointer& TextureCache::getNormalFittingTexture() {
|
||||
if (!_normalFittingTexture) {
|
||||
_normalFittingTexture = getImageTexture(PathUtils::resourcesPath() + "images/normalFittingScale.dds");
|
||||
}
|
||||
return _normalFittingTexture;
|
||||
}
|
||||
|
||||
/// Extra data for creating textures.
|
||||
class TextureExtra {
|
||||
public:
|
||||
|
@ -170,6 +179,7 @@ gpu::TexturePointer TextureCache::getImageTexture(const QString& path) {
|
|||
return texture;
|
||||
}
|
||||
|
||||
|
||||
QSharedPointer<Resource> TextureCache::createResource(const QUrl& url,
|
||||
const QSharedPointer<Resource>& fallback, bool delayLoad, const void* extra) {
|
||||
const TextureExtra* textureExtra = static_cast<const TextureExtra*>(extra);
|
||||
|
|
|
@ -54,6 +54,9 @@ public:
|
|||
/// Returns the a black texture (useful for a default).
|
||||
const gpu::TexturePointer& getBlackTexture();
|
||||
|
||||
// Returns a map used to compress the normals through a fitting scale algorithm
|
||||
const gpu::TexturePointer& getNormalFittingTexture();
|
||||
|
||||
/// Returns a texture version of an image file
|
||||
static gpu::TexturePointer getImageTexture(const QString& path);
|
||||
|
||||
|
@ -76,6 +79,7 @@ private:
|
|||
gpu::TexturePointer _grayTexture;
|
||||
gpu::TexturePointer _blueTexture;
|
||||
gpu::TexturePointer _blackTexture;
|
||||
gpu::TexturePointer _normalFittingTexture;
|
||||
|
||||
QHash<QUrl, QWeakPointer<NetworkTexture> > _dilatableNetworkTextures;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue