Added more control over shadow generation. Added documentation. Merged Master.

This commit is contained in:
Jonathas Costa
2019-12-08 14:50:19 -05:00
parent 10c1ff03e9
commit b41edb9c02
7 changed files with 137 additions and 47 deletions

View File

@@ -62,6 +62,8 @@ uniform float orenNayarRoughness;
#if SHADOW_MAPPING_ENABLED
in vec4 shadowCoords;
uniform sampler2DShadow shadowMapTexture;
uniform int nShadowSamples;
uniform float zFightingPercentage;
#endif
#if USE_ECLIPSE_SHADOWS
@@ -267,26 +269,23 @@ Fragment getFragment() {
float shadow = 1.0;
if ( shadowCoords.w > 1 ) {
vec4 normalizedShadowCoords = shadowCoords;
normalizedShadowCoords.z = normalizeFloat(normalizedShadowCoords.w - 0.005 * normalizedShadowCoords.w);
normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w;
normalizedShadowCoords.w = 1.0;
normalizedShadowCoords.z = normalizeFloat(zFightingPercentage * normalizedShadowCoords.w);
normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w;
normalizedShadowCoords.w = 1.0;
//shadow = textureProj(shadowMapTexture, normalizedShadowCoords);
float sum = 0;
int fStep = 5;
for (int i = 0; i < fStep; ++i) {
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep + i, -fStep + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep + i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep + i, fStep - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, -fStep + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, fStep - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep - i, -fStep + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep - i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep - i, fStep - i));
float sum = 0;
for (int i = 0; i < nShadowSamples; ++i) {
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, nShadowSamples - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0 , -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0 , nShadowSamples - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, nShadowSamples - i));
}
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, 0));
shadow = sum / (8.f * fStep + 1.f);
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(0, 0));
shadow = sum / (8.f * nShadowSamples + 1.f);
}
frag.color.xyz *= shadow < 0.99 ? clamp(shadow + 0.5, 0.0, 1.0) : shadow;
#endif

View File

@@ -37,6 +37,8 @@ uniform float transparency;
uniform bool hasSunPosition;
uniform vec3 sunPosition;
uniform float _nightFactor;
uniform int nShadowSamples;
uniform float zFightingPercentage;
// temp
in vec4 fragPosInLightSpace;
@@ -73,24 +75,23 @@ Fragment getFragment() {
float shadow = 1.0;
if ( shadowCoords.z >= 0 ) {
vec4 normalizedShadowCoords = shadowCoords;
normalizedShadowCoords.z = normalizeFloat(normalizedShadowCoords.w - 0.005 * normalizedShadowCoords.w);
normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w;
normalizedShadowCoords.w = 1.0;
//shadow = textureProj(shadowMapTexture, normalizedShadowCoords);
normalizedShadowCoords.z = normalizeFloat(zFightingPercentage * normalizedShadowCoords.w);
normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w;
normalizedShadowCoords.w = 1.0;
float sum = 0;
int fStep = 2;
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep, -fStep));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-fStep, fStep));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, -fStep));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, fStep));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep, -fStep));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( fStep, fStep));
shadow = sum / 9.f;
for (int i = 0; i < nShadowSamples; ++i) {
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-nShadowSamples + i, nShadowSamples - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0 , -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0 , nShadowSamples - i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, -nShadowSamples + i));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, 0));
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( nShadowSamples - i, nShadowSamples - i));
}
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(0, 0));
shadow = sum / (8.f * nShadowSamples + 1.f);
}
// The normal for the one plane depends on whether we are dealing

View File

@@ -190,6 +190,20 @@ namespace {
"Enables shadow mapping algorithm. Used by renderable rings too."
};
constexpr openspace::properties::Property::PropertyInfo ZFightingPercentageInfo = {
"ZFightingPercentage",
"Z-Fighting Percentage",
"The percentage of the correct distance to the surface being shadowed. "
"Possible values: [0.0, 1.0]"
};
constexpr openspace::properties::Property::PropertyInfo NumberShadowSamplesInfo = {
"NumberShadowSamples",
"Number of Shadow Samples",
"The number of samples used during shadow mapping calculation "
"(Percentage Closer Filtering)."
};
constexpr openspace::properties::Property::PropertyInfo TargetLodScaleFactorInfo = {
"TargetLodScaleFactor",
"Target Level of Detail Scale Factor",
@@ -502,12 +516,15 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
BoolProperty(EclipseInfo, false),
BoolProperty(EclipseHardShadowsInfo, false),
BoolProperty(ShadowMappingInfo, false),
FloatProperty(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f),
IntProperty(NumberShadowSamplesInfo, 5, 1, 20),
FloatProperty(TargetLodScaleFactorInfo, 15.f, 1.f, 50.f),
FloatProperty(CurrentLodScaleFactorInfo, 15.f, 1.f, 50.f),
FloatProperty(CameraMinHeightInfo, 100.f, 0.f, 1000.f),
FloatProperty(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f),
IntProperty(NActiveLayersInfo, 0, 0, OpenGLCap.maxTextureUnits() / 3)
})
, _shadowMappingPropertyOwner({ "Shadow Mapping" })
, _debugPropertyOwner({ "Debug" })
, _grid(DefaultSkirtedGridSegments, DefaultSkirtedGridSegments)
, _leftRoot(Chunk(LeftHemisphereIndex))
@@ -544,7 +561,12 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
addProperty(_generalProperties.useAccurateNormals);
addProperty(_generalProperties.eclipseShadowsEnabled);
addProperty(_generalProperties.eclipseHardShadows);
addProperty(_generalProperties.shadowMapping);
_shadowMappingPropertyOwner.addProperty(_generalProperties.shadowMapping);
_shadowMappingPropertyOwner.addProperty(_generalProperties.zFightingPercentage);
_shadowMappingPropertyOwner.addProperty(_generalProperties.nShadowSamples);
addPropertySubOwner(_shadowMappingPropertyOwner);
_generalProperties.targetLodScaleFactor.onChange([this]() {
float sf = _generalProperties.targetLodScaleFactor;
_generalProperties.currentLodScaleFactor = sf;
@@ -1296,6 +1318,8 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
program.setUniform("shadowMapTexture", shadowMapUnit);
program.setUniform("nShadowSamples", _generalProperties.nShadowSamples);
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
}
glEnable(GL_DEPTH_TEST);
@@ -1420,6 +1444,8 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
program.setUniform("shadowMapTexture", shadowMapUnit);
program.setUniform("nShadowSamples", _generalProperties.nShadowSamples);
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
}
glEnable(GL_DEPTH_TEST);

View File

@@ -129,25 +129,29 @@ private:
properties::BoolProperty showHeightIntensities;
properties::BoolProperty levelByProjectedAreaElseDistance;
properties::BoolProperty resetTileProviders;
properties::IntProperty modelSpaceRenderingCutoffLevel;
properties::IntProperty dynamicLodIterationCount;
properties::IntProperty modelSpaceRenderingCutoffLevel;
properties::IntProperty dynamicLodIterationCount;
} _debugProperties;
struct {
properties::BoolProperty performShading;
properties::BoolProperty useAccurateNormals;
properties::BoolProperty eclipseShadowsEnabled;
properties::BoolProperty eclipseHardShadows;
properties::BoolProperty shadowMapping;
properties::BoolProperty performShading;
properties::BoolProperty useAccurateNormals;
properties::BoolProperty eclipseShadowsEnabled;
properties::BoolProperty eclipseHardShadows;
properties::BoolProperty shadowMapping;
properties::FloatProperty zFightingPercentage;
properties::IntProperty nShadowSamples;
properties::FloatProperty targetLodScaleFactor;
properties::FloatProperty currentLodScaleFactor;
properties::FloatProperty cameraMinHeight;
properties::FloatProperty orenNayarRoughness;
properties::IntProperty nActiveLayers;
properties::IntProperty nActiveLayers;
} _generalProperties;
properties::PropertyOwner _debugPropertyOwner;
properties::PropertyOwner _shadowMappingPropertyOwner;
/**
* Test if a specific chunk can safely be culled without affecting the rendered
* image.

View File

@@ -56,9 +56,10 @@
#include <locale>
namespace {
constexpr const std::array<const char*, 8> UniformNames = {
constexpr const std::array<const char*, 10> UniformNames = {
"modelViewProjectionMatrix", "textureOffset", "transparency", "_nightFactor",
"sunPosition", "ringTexture", "shadowMatrix", "shadowMapTexture"
"sunPosition", "ringTexture", "shadowMatrix", "shadowMapTexture",
"nShadowSamples", "zFightingPercentage"
};
constexpr const std::array<const char*, 3> GeomUniformNames = {
@@ -101,6 +102,20 @@ namespace {
"This value determines the transparency of part of the rings depending on the "
"color values. For this value v, the transparency is equal to length(color) / v."
};
constexpr openspace::properties::Property::PropertyInfo ZFightingPercentageInfo = {
"ZFightingPercentage",
"Z-Fighting Percentage",
"The percentage of the correct distance to the surface being shadowed. "
"Possible values: [0.0, 1.0]"
};
constexpr openspace::properties::Property::PropertyInfo NumberShadowSamplesInfo = {
"NumberShadowSamples",
"Number of Shadow Samples",
"The number of samples used during shadow mapping calculation "
"(Percentage Closer Filtering)."
};
} // namespace
namespace openspace {
@@ -140,6 +155,18 @@ namespace openspace {
new DoubleVerifier,
Optional::Yes,
TransparencyInfo.description
},
{
ZFightingPercentageInfo.identifier,
new DoubleVerifier,
Optional::Yes,
ZFightingPercentageInfo.description
},
{
NumberShadowSamplesInfo.identifier,
new IntVerifier,
Optional::Yes,
NumberShadowSamplesInfo.description
}
}
};
@@ -153,6 +180,8 @@ namespace openspace {
, _nightFactor(NightFactorInfo, 0.33f, 0.f, 1.f)
, _transparency(TransparencyInfo, 0.15f, 0.f, 1.f)
, _enabled({ "Enabled", "Enabled", "Enable/Disable Rings" }, true)
, _zFightingPercentage(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f)
, _nShadowSamples(NumberShadowSamplesInfo, 2, 1, 20)
, _ringsDictionary(dictionary)
{
using ghoul::filesystem::File;
@@ -204,6 +233,22 @@ namespace openspace {
_ringsDictionary.value<double>(TransparencyInfo.identifier)
);
}
// Shadow Mapping Quality Controls
if (_ringsDictionary.hasKey(ZFightingPercentageInfo.identifier)) {
_zFightingPercentage = _ringsDictionary.value<float>(
ZFightingPercentageInfo.identifier
);
}
addProperty(_zFightingPercentage);
if (_ringsDictionary.hasKey(NumberShadowSamplesInfo.identifier)) {
_nShadowSamples = _ringsDictionary.value<int>(
NumberShadowSamplesInfo.identifier
);
}
addProperty(_nShadowSamples);
addProperty(_transparency);
}
@@ -287,6 +332,8 @@ namespace openspace {
_shader->setUniform(_uniformCache.transparency, _transparency);
_shader->setUniform(_uniformCache.nightFactor, _nightFactor);
_shader->setUniform(_uniformCache.sunPosition, _sunPosition);
_shader->setUniform(_uniformCache.nShadowSamples, _nShadowSamples);
_shader->setUniform(_uniformCache.zFightingPercentage, _zFightingPercentage);
ringTextureUnit.activate();
_texture->bind();

View File

@@ -92,11 +92,14 @@ namespace openspace {
properties::FloatProperty _nightFactor;
properties::FloatProperty _transparency;
properties::BoolProperty _enabled;
properties::FloatProperty _zFightingPercentage;
properties::IntProperty _nShadowSamples;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
std::unique_ptr<ghoul::opengl::ProgramObject> _geometryOnlyShader;
UniformCache(modelViewProjectionMatrix, textureOffset, transparency, nightFactor,
sunPosition, ringTexture, shadowMatrix, shadowMapTexture
sunPosition, ringTexture, shadowMatrix, shadowMapTexture,
nShadowSamples, zFightingPercentage
) _uniformCache;
UniformCache(modelViewProjectionMatrix, textureOffset, ringTexture)
_geomUniformCache;

View File

@@ -163,13 +163,19 @@ namespace openspace {
new DoubleVerifier,
Optional::Yes,
DistanceFractionInfo.description
},
{
DepthMapSizeInfo.identifier,
new Vector2ListVerifier<float>,
Optional::Yes,
DepthMapSizeInfo.description
}
}
};
}
ShadowComponent::ShadowComponent(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "Shadows" })
: properties::PropertyOwner({ "Shadows Component" })
, _saveDepthTexture(SaveDepthTextureInfo)
, _distanceFraction(DistanceFractionInfo, 20, 1, 10000)
, _enabled({ "Enabled", "Enabled", "Enable/Disable Shadows" }, true)
@@ -222,6 +228,10 @@ namespace openspace {
_dynamicDepthTextureRes = true;
}
_saveDepthTexture.onChange([&]() {
_executeDepthTextureSave = true;
});
_viewDepthMap = false;
addProperty(_enabled);