mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 22:53:41 +02:00
Cascade selection working on shadow but not in Luci debug mode
This commit is contained in:
parent
28d46dc4a5
commit
ac0e816f8c
12 changed files with 162 additions and 75 deletions
libraries
gpu-gl/src/gpu/gl
render-utils/src
scripts/developer/utilities/render
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -64,10 +64,11 @@ protected:
|
|||
LightmapMode,
|
||||
ScatteringMode,
|
||||
LightingMode,
|
||||
Shadow0Mode,
|
||||
Shadow1Mode,
|
||||
Shadow2Mode,
|
||||
Shadow3Mode,
|
||||
ShadowCascade0Mode,
|
||||
ShadowCascade1Mode,
|
||||
ShadowCascade2Mode,
|
||||
ShadowCascade3Mode,
|
||||
ShadowCascadeIndicesMode,
|
||||
LinearDepthMode,
|
||||
HalfLinearDepthMode,
|
||||
HalfNormalMode,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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@>
|
||||
|
|
86
libraries/render-utils/src/ShadowCore.slh
Normal file
86
libraries/render-utils/src/ShadowCore.slh
Normal 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@>
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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" }
|
||||
|
|
Loading…
Reference in a new issue