Cascade selection working on shadow but not in Luci debug mode

This commit is contained in:
Olivier Prat 2017-11-13 18:42:34 +01:00
parent 28d46dc4a5
commit ac0e816f8c
12 changed files with 162 additions and 75 deletions

View file

@ -318,7 +318,10 @@ int GLBackend::makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slot
if (requestedBinding != slotBindings.end()) {
if (binding != (*requestedBinding)._location) {
binding = (*requestedBinding)._location;
glProgramUniform1i(glprogram, location, binding);
for (auto i = 0; i < size; i++) {
// If we are working with an array of textures, reserve for each elemet
glProgramUniform1i(glprogram, location+i, binding+i);
}
}
}

View file

@ -126,12 +126,14 @@ static const std::string DEFAULT_DEPTH_SHADER {
" return vec4(vec3(texture(depthMap, uv).x), 1.0);"
" }"
};
static const std::string DEFAULT_LIGHTING_SHADER {
"vec4 getFragmentColor() {"
" return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
" }"
};
static const std::string DEFAULT_SHADOW_SHADER {
static const std::string DEFAULT_SHADOW_SHADER{
"uniform sampler2DShadow shadowMap;"
"vec4 getFragmentColor() {"
" for (int i = 255; i >= 0; --i) {"
@ -144,6 +146,25 @@ static const std::string DEFAULT_SHADOW_SHADER {
" }"
};
static const std::string DEFAULT_SHADOW_CASCADE_SHADER{
"vec3 cascadeColors[4] = vec3[4]( vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(0,0,0) );"
"vec4 getFragmentColor() {"
" DeferredFrameTransform deferredTransform = getDeferredFrameTransform();"
" DeferredFragment frag = unpackDeferredFragment(deferredTransform, uv);"
" vec4 viewPosition = vec4(frag.position.xyz, 1.0);"
" vec4 worldPosition = getViewInverse() * viewPosition;"
" vec4 cascadeShadowCoords[4] = vec4[4]("
" evalShadowTexcoord(0, worldPosition),"
" evalShadowTexcoord(1, worldPosition),"
" evalShadowTexcoord(2, worldPosition),"
" evalShadowTexcoord(3, worldPosition)"
" );"
" ivec2 cascadeIndices;"
" float cascadeMix = evalCascadeIndicesAndMix(viewPosition, cascadeShadowCoords, cascadeIndices);"
" return vec4(mix(cascadeColors[cascadeIndices.x], cascadeColors[cascadeIndices.y], cascadeMix), 1.0);"
" }"
};
static const std::string DEFAULT_LINEAR_DEPTH_SHADER {
"vec4 getFragmentColor() {"
" return vec4(vec3(1.0 - texture(linearDepthMap, uv).x * 0.01), 1.0);"
@ -284,11 +305,13 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust
return DEFAULT_SCATTERING_SHADER;
case LightingMode:
return DEFAULT_LIGHTING_SHADER;
case Shadow0Mode:
case Shadow1Mode:
case Shadow2Mode:
case Shadow3Mode:
case ShadowCascade0Mode:
case ShadowCascade1Mode:
case ShadowCascade2Mode:
case ShadowCascade3Mode:
return DEFAULT_SHADOW_SHADER;
case ShadowCascadeIndicesMode:
return DEFAULT_SHADOW_CASCADE_SHADER;
case LinearDepthMode:
return DEFAULT_LINEAR_DEPTH_SHADER;
case HalfLinearDepthMode:
@ -424,8 +447,8 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
// TODO REMOVE: Temporary until UI
auto first = _customPipelines.begin()->first;
batch.setPipeline(getPipeline(_mode, first));
auto pipeline = getPipeline(_mode, first);
batch.setPipeline(pipeline);
if (deferredFramebuffer) {
batch.setResourceTexture(Albedo, deferredFramebuffer->getDeferredColorTexture());
@ -441,8 +464,12 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I
auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow();
const auto& globalShadow = lightAndShadow.second;
if (globalShadow) {
const auto cascadeIndex = glm::clamp(_mode - Mode::Shadow0Mode, 0, (int)globalShadow->getCascadeCount() - 1);
const auto cascadeIndex = glm::clamp(_mode - Mode::ShadowCascade0Mode, 0, (int)globalShadow->getCascadeCount() - 1);
const auto shadowBufferLoc = pipeline->getProgram()->getUniformBuffers().findLocation("shadowTransformBuffer");
batch.setResourceTexture(Shadow, globalShadow->getCascade(cascadeIndex).map);
if (shadowBufferLoc >= 0) {
batch.setUniformBuffer(shadowBufferLoc, globalShadow->getBuffer());
}
}
if (linearDepthTarget) {

View file

@ -64,10 +64,11 @@ protected:
LightmapMode,
ScatteringMode,
LightingMode,
Shadow0Mode,
Shadow1Mode,
Shadow2Mode,
Shadow3Mode,
ShadowCascade0Mode,
ShadowCascade1Mode,
ShadowCascade2Mode,
ShadowCascade3Mode,
ShadowCascadeIndicesMode,
LinearDepthMode,
HalfLinearDepthMode,
HalfNormalMode,

View file

@ -126,6 +126,8 @@ void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const Vie
schemaCascade.reprojection = _biasMatrix * ortho * viewInverse.getMatrix();
schemaCascade.minDistance = viewMinShadowDistance;
schemaCascade.maxDistance = viewMaxShadowDistance;
cascade.minDistance = viewMinShadowDistance;
cascade.maxDistance = viewMaxShadowDistance;
}
void LightStage::Shadow::setFrustum(unsigned int cascadeIndex, const ViewFrustum& shadowFrustum) {

View file

@ -56,6 +56,8 @@ public:
gpu::FramebufferPointer framebuffer;
gpu::TexturePointer map;
float minDistance;
float maxDistance;
const std::shared_ptr<ViewFrustum>& getFrustum() const { return _frustum; }
@ -95,8 +97,6 @@ public:
};
UniformBufferView _schemaBuffer = nullptr;
void setupCascades();
friend class Light;
};

View file

@ -253,8 +253,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
output.edit0() = args->_renderMode;
const auto globalShadow = lightStage->getCurrentKeyShadow();
const auto globalShadowCascadeCount = globalShadow->getCascadeCount();
if (globalShadow && _cascadeIndex<globalShadowCascadeCount) {
if (globalShadow && _cascadeIndex<globalShadow->getCascadeCount()) {
output.edit1() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered();
const auto nearClip = args->getViewFrustum().getNearClip();
@ -263,7 +262,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
static const float SHADOW_MAX_DISTANCE = 25.0f;
static const float SHADOW_OVERLAP_DISTANCE = 1.0f;
float maxCascadeDistance = SHADOW_MAX_DISTANCE / powf(2.0f, globalShadowCascadeCount - 1 - _cascadeIndex);
float maxCascadeDistance = SHADOW_MAX_DISTANCE / powf(2.0f, globalShadow->getCascadeCount() - 1 - _cascadeIndex);
float minCascadeDistance = maxCascadeDistance / 2.0f - SHADOW_OVERLAP_DISTANCE;
if (_cascadeIndex == 0) {

View file

@ -11,43 +11,11 @@
<@if not SHADOW_SLH@>
<@def SHADOW_SLH@>
<@include Shadows_shared.slh@>
<@include ShadowCore.slh@>
// the shadow texture
uniform sampler2DShadow shadowMaps[SHADOW_CASCADE_MAX_COUNT];
uniform shadowTransformBuffer {
ShadowParameters shadow;
};
int getShadowCascadeCount() {
return shadow.cascadeCount;
}
float getShadowCascadeMinDistance(int cascadeIndex) {
return shadow.cascades[cascadeIndex].minDistance;
}
mat4 getShadowReprojection(int cascadeIndex) {
return shadow.cascades[cascadeIndex].reprojection;
}
float getShadowScale() {
return shadow.invMapSize;
}
float getShadowBias(int cascadeIndex) {
return shadow.cascades[cascadeIndex].bias;
}
// Compute the texture coordinates from world coordinates
vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {
float bias = -getShadowBias(cascadeIndex);
vec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;
return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0);
}
// Sample the shadowMap with PCF (built-in)
float fetchShadow(int cascadeIndex, vec3 shadowTexcoord) {
return texture(shadowMaps[cascadeIndex], shadowTexcoord);
@ -109,8 +77,7 @@ float evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, ve
return shadowAttenuation;
}
float evalShadowCascadeAttenuation(int cascadeIndex, vec4 position, ShadowSampleOffsets offsets) {
vec4 shadowTexcoord = evalShadowTexcoord(cascadeIndex, position);
float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord) {
if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 ||
shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0 ||
shadowTexcoord.z < 0.0 || shadowTexcoord.z > 1.0) {
@ -120,25 +87,23 @@ float evalShadowCascadeAttenuation(int cascadeIndex, vec4 position, ShadowSample
return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord);
}
float evalShadowAttenuation(vec4 position) {
ShadowSampleOffsets offsets = evalShadowFilterOffsets(position);
// Cascade selection based on :
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee416307(v=vs.85).aspx
vec4 currentPixelDepth = position.zzzz;
vec4 cascadeDepthLimits = vec4(
getShadowCascadeMinDistance(0),
getShadowCascadeMinDistance(1),
getShadowCascadeMinDistance(2),
getShadowCascadeMinDistance(3)
float evalShadowAttenuation(vec4 worldPosition, vec4 viewPosition) {
ShadowSampleOffsets offsets = evalShadowFilterOffsets(worldPosition);
vec4 cascadeShadowCoords[4] = vec4[4] (
evalShadowTexcoord(0, worldPosition),
evalShadowTexcoord(1, worldPosition),
evalShadowTexcoord(2, worldPosition),
evalShadowTexcoord(3, worldPosition)
);
bvec4 comparison = greaterThan( currentPixelDepth, cascadeDepthLimits);
int cascadeCount = getShadowCascadeCount();
bvec4 cascadeCountMask = greaterThan(ivec4(cascadeCount), ivec4(0,1,2,3));
int cascadeIndex = int(dot(ivec4(cascadeCountMask), ivec4(comparison)));
cascadeIndex = min( cascadeIndex, cascadeCount-1 );
ivec2 cascadeIndices;
float cascadeMix = evalCascadeIndicesAndMix(viewPosition, cascadeShadowCoords, cascadeIndices);
return evalShadowCascadeAttenuation(cascadeIndex, position, offsets);
vec2 cascadeAttenuations = vec2(1.0, 1.0);
cascadeAttenuations.x = evalShadowCascadeAttenuation(cascadeIndices.x, offsets, cascadeShadowCoords[cascadeIndices.x]);
if (cascadeMix > 0.0) {
cascadeAttenuations.y = evalShadowCascadeAttenuation(cascadeIndices.y, offsets, cascadeShadowCoords[cascadeIndices.y]);
}
return mix(cascadeAttenuations.x, cascadeAttenuations.y, cascadeMix);
}
<@endif@>

View file

@ -0,0 +1,86 @@
<!
// ShadowCore.slh
// libraries/render-utils/src
//
// Created by Olivier Prat on 11/13/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
!>
<@if not SHADOW_CORE_SLH@>
<@def SHADOW_CORE_SLH@>
<@include Shadows_shared.slh@>
uniform shadowTransformBuffer {
ShadowParameters shadow;
};
int getShadowCascadeCount() {
return shadow.cascadeCount;
}
float getShadowCascadeMinDistance(int cascadeIndex) {
return shadow.cascades[cascadeIndex].minDistance;
}
mat4 getShadowReprojection(int cascadeIndex) {
return shadow.cascades[cascadeIndex].reprojection;
}
float getShadowScale() {
return shadow.invMapSize;
}
float getShadowBias(int cascadeIndex) {
return shadow.cascades[cascadeIndex].bias;
}
// Compute the texture coordinates from world coordinates
vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {
float bias = -getShadowBias(cascadeIndex);
vec4 shadowCoord = getShadowReprojection(cascadeIndex) * position;
return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0);
}
int getFirstValidShadowTexcoord(vec4 cascadeShadowCoords[4]) {
int cascadeIndex;
for (cascadeIndex=0 ; cascadeIndex<getShadowCascadeCount()-1 ; cascadeIndex++) {
vec4 shadowTexcoord = cascadeShadowCoords[cascadeIndex];
bvec2 greaterThanZero = greaterThanEqual(shadowTexcoord.xy, vec2(0));
bvec2 lessThanOne = lessThanEqual(shadowTexcoord.xy, vec2(1));
if (all(greaterThanZero) && all(lessThanOne)) {
return cascadeIndex;
}
}
return cascadeIndex;
}
float evalCascadeIndicesAndMix(vec4 viewPosition, vec4 cascadeShadowCoords[4], out ivec2 cascadeIndices) {
#if 0
// Cascade selection based on :
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee416307(v=vs.85).aspx
vec4 currentPixelDepth = viewPosition.zzzz;
vec4 cascadeDepthLimits = vec4(
getShadowCascadeMinDistance(0),
getShadowCascadeMinDistance(1),
getShadowCascadeMinDistance(2),
getShadowCascadeMinDistance(3)
);
bvec4 comparison = greaterThan( currentPixelDepth, cascadeDepthLimits);
int cascadeCount = getShadowCascadeCount();
bvec4 cascadeCountMask = greaterThan(ivec4(cascadeCount), ivec4(0,1,2,3));
int cascadeIndex = int(dot(ivec4(cascadeCountMask), ivec4(comparison)));
cascadeIndex = min( cascadeIndex, cascadeCount-1 );
#else
int cascadeIndex = getFirstValidShadowTexcoord(cascadeShadowCoords);
#endif
cascadeIndices.x = cascadeIndex;
cascadeIndices.y = cascadeIndex;
return 1.0;
}
<@endif@>

View file

@ -16,7 +16,6 @@
<@include gpu/Color.slh@>
<$declareColorWheel()$>
uniform sampler2D linearDepthMap;
uniform sampler2D halfLinearDepthMap;
uniform sampler2D halfNormalMap;
@ -24,6 +23,8 @@ uniform sampler2D occlusionMap;
uniform sampler2D occlusionBlurredMap;
uniform sampler2D scatteringMap;
<@include ShadowCore.slh@>
<$declareDeferredCurvature()$>
float curvatureAO(float k) {

View file

@ -26,8 +26,9 @@ void main(void) {
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
vec4 worldPos = getViewInverse() * vec4(frag.position.xyz, 1.0);
float shadowAttenuation = evalShadowAttenuation(worldPos);
vec4 viewPos = vec4(frag.position.xyz, 1.0);
vec4 worldPos = getViewInverse() * viewPos;
float shadowAttenuation = evalShadowAttenuation(worldPos, viewPos);
if (frag.mode == FRAG_MODE_UNLIT) {
discard;

View file

@ -26,8 +26,9 @@ void main(void) {
DeferredFrameTransform deferredTransform = getDeferredFrameTransform();
DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0);
vec4 worldPos = getViewInverse() * vec4(frag.position.xyz, 1.0);
float shadowAttenuation = evalShadowAttenuation(worldPos);
vec4 viewPos = vec4(frag.position.xyz, 1.0);
vec4 worldPos = getViewInverse() * viewPos;
float shadowAttenuation = evalShadowAttenuation(worldPos, viewPos);
// Light mapped or not ?
if (frag.mode == FRAG_MODE_UNLIT) {

View file

@ -188,6 +188,7 @@ Rectangle {
ListElement { text: "Shadow Cascade 1"; color: "White" }
ListElement { text: "Shadow Cascade 2"; color: "White" }
ListElement { text: "Shadow Cascade 3"; color: "White" }
ListElement { text: "Shadow Cascade Indices"; color: "White" }
ListElement { text: "Linear Depth"; color: "White" }
ListElement { text: "Half Linear Depth"; color: "White" }
ListElement { text: "Half Normal"; color: "White" }