Compare commits

...

15 Commits

Author SHA1 Message Date
Benjamin Doherty
18dab53920 All changes 2022-11-14 22:20:59 -08:00
Benjamin Doherty
b754b81e6f Almost all the changes 2022-11-14 22:16:58 -08:00
Benjamin Doherty
65bb66f90c Even more shader changes 2022-11-14 22:00:10 -08:00
Benjamin Doherty
a0af84d034 Some more shader changes 2022-11-14 21:56:50 -08:00
Benjamin Doherty
3cdaf3feeb ShadowMapManager.h changes 2022-11-14 17:18:00 -08:00
Benjamin Doherty
da7d1b6fa9 Update Scene.cpp 2022-11-14 17:09:55 -08:00
Benjamin Doherty
3129226839 Fix literal 0 2022-11-14 17:07:55 -08:00
Benjamin Doherty
6935acafff Changes to ShadowMapManager 2022-11-14 17:07:25 -08:00
Benjamin Doherty
d8103f4fd6 Update ShaderGenerator.cpp 2022-11-14 16:55:50 -08:00
Benjamin Doherty
09a13f4015 Some shadowing changes 2022-11-14 15:25:08 -08:00
Benjamin Doherty
e888023102 Some shader changes 2022-11-14 15:00:09 -08:00
Benjamin Doherty
f62f4736f0 Adjust LightsUib 2022-11-14 13:39:08 -08:00
Benjamin Doherty
a378272d56 Remove some more uniforms 2022-11-14 13:34:26 -08:00
Benjamin Doherty
3d61938fcf Remove lightFromWorldMatrix from PerViewUniforms 2022-11-14 13:30:54 -08:00
Benjamin Doherty
a9f3937da6 Trivial changes 2022-11-14 13:05:52 -08:00
19 changed files with 98 additions and 90 deletions

View File

@@ -9,6 +9,7 @@ A new header is inserted each time a *tag* is created.
- gltfio: recompute bounding boxes with morph targets
- engine: add missing getters on `MaterialInstance`
- WebGL: add missing `ColorGrading` JS bindings
- engine: improvements/cleanup of Shadow mapping code [⚠️ **Recompile Materials**]
## v1.28.3

View File

@@ -290,14 +290,10 @@ void PerViewUniforms::prepareShadowMapping(bool highPrecision) noexcept {
void PerViewUniforms::prepareShadowSampling(PerViewUib& uniforms,
ShadowMappingUniforms const& shadowMappingUniforms) noexcept {
uniforms.lightFromWorldMatrix = shadowMappingUniforms.lightFromWorldMatrix;
uniforms.cascadeSplits = shadowMappingUniforms.cascadeSplits;
uniforms.shadowBulbRadiusLs = shadowMappingUniforms.shadowBulbRadiusLs;
uniforms.shadowBias = shadowMappingUniforms.shadowBias;
uniforms.ssContactShadowDistance = shadowMappingUniforms.ssContactShadowDistance;
uniforms.directionalShadows = shadowMappingUniforms.directionalShadows;
uniforms.cascades = shadowMappingUniforms.cascades;
uniforms.cascades |= uint32_t(shadowMappingUniforms.elvsm) << 31u;
}
void PerViewUniforms::prepareShadowVSM(Handle<HwTexture> texture,

View File

@@ -97,8 +97,10 @@ void ShadowMapManager::setDirectionalShadowMap(size_t lightIndex,
LightManager::ShadowOptions const* options) noexcept {
assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES);
for (size_t c = 0; c < options->shadowCascades; c++) {
auto* pShadowMap = getCascadeShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, c, 0, options);
const size_t i = c;
assert_invariant(i < CONFIG_MAX_SHADOW_CASCADES);
auto* pShadowMap = getCascadeShadowMap(i);
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, i, 0, options);
mCascadeShadowMaps.push_back(pShadowMap);
}
}
@@ -107,17 +109,19 @@ void ShadowMapManager::addShadowMap(size_t lightIndex, bool spotlight,
LightManager::ShadowOptions const* options) noexcept {
if (spotlight) {
const size_t c = mSpotShadowMaps.size();
assert_invariant(c < CONFIG_MAX_SHADOWMAPS);
auto* pShadowMap = getPointOrSpotShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::SPOT, c, 0, options);
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
auto* pShadowMap = getPointOrSpotShadowMap(i);
pShadowMap->initialize(lightIndex, ShadowType::SPOT, i, 0, options);
mSpotShadowMaps.push_back(pShadowMap);
} else {
// point-light, generate 6 independent shadowmaps
for (size_t face = 0; face < 6; face++) {
const size_t c = mSpotShadowMaps.size();
assert_invariant(c < CONFIG_MAX_SHADOWMAPS);
auto* pShadowMap = getPointOrSpotShadowMap(c);
pShadowMap->initialize(lightIndex, ShadowType::POINT, c, face, options);
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
auto* pShadowMap = getPointOrSpotShadowMap(i);
pShadowMap->initialize(lightIndex, ShadowType::POINT, i, face, options);
mSpotShadowMaps.push_back(pShadowMap);
}
}
@@ -455,7 +459,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
// entire camera frustum, as if we only had a single cascade.
ShadowMap& shadowMap = *mCascadeShadowMaps[0];
auto shaderParameters = shadowMap.updateDirectional(mEngine,
shadowMap.updateDirectional(mEngine,
lightData, 0, cameraInfo, shadowMapInfo, *scene, sceneInfo);
hasVisibleShadows = shadowMap.hasVisibleShadows();
@@ -464,18 +468,6 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
Frustum const& frustum = shadowMap.getCamera().getCullingFrustum();
FView::cullRenderables(engine.getJobSystem(), renderableData, frustum,
VISIBLE_DIR_SHADOW_RENDERABLE_BIT);
// Set shadowBias, using the first directional cascade.
// when computing the required bias we need a half-texel size, so we multiply by 0.5 here.
// note: normalBias is set to zero for VSM
const float normalBias = shadowMapInfo.vsm ? 0.0f : 0.5f * lcm.getShadowNormalBias(0);
// Texel size is constant for directional light (although that's not true when LISPSM
// is used, but in that case we're pretending it is).
const float wsTexelSize = shaderParameters.texelSizeAtOneMeterWs;
mShadowMappingUniforms.shadowBias = normalBias * wsTexelSize;
mShadowMappingUniforms.shadowBulbRadiusLs =
mSoftShadowOptions.penumbraScale * options.shadowBulbRadius / wsTexelSize;
mShadowMappingUniforms.elvsm = options.vsm.elvsm;
}
}
@@ -528,6 +520,10 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
mShadowMappingUniforms.cascadeSplits = wsSplitPositionUniform;
// when computing the required bias we need a half-texel size, so we multiply by 0.5 here.
// note: normalBias is set to zero for VSM
const float normalBias = shadowMapInfo.vsm ? 0.0f : 0.5f * lcm.getShadowNormalBias(0);
for (size_t i = 0, c = mCascadeShadowMaps.size(); i < c; i++) {
assert_invariant(mCascadeShadowMaps[i]);
@@ -541,7 +537,22 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
lightData, 0, cameraInfo, shadowMapInfo, *scene, sceneInfo);
if (shadowMap.hasVisibleShadows()) {
mShadowMappingUniforms.lightFromWorldMatrix[i] = shaderParameters.lightSpace;
const size_t shadowIndex = shadowMap.getShadowIndex();
assert_invariant(shadowIndex == i);
// Texel size is constant for directional light (although that's not true when LISPSM
// is used, but in that case we're pretending it is).
const float wsTexelSize = shaderParameters.texelSizeAtOneMeterWs;
auto& s = mShadowUb.edit();
s.shadows[shadowIndex].layer = shadowMap.getLayer();
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSize;
s.shadows[shadowIndex].texelSizeAtOneMeter = wsTexelSize;
s.shadows[shadowIndex].elvsm = options.vsm.elvsm;
s.shadows[shadowIndex].bulbRadiusLs =
mSoftShadowOptions.penumbraScale * options.shadowBulbRadius / wsTexelSize;
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
cascadeHasVisibleShadows |= 0x1u << i;
}
@@ -669,6 +680,7 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
auto& s = mShadowUb.edit();
const double n = shadowMap.getCamera().getNear();
const double f = shadowMap.getCamera().getCullingFar();
s.shadows[shadowIndex].layer = shadowMap.getLayer();
s.shadows[shadowIndex].lightFromWorldMatrix = shaderParameters.lightSpace;
s.shadows[shadowIndex].direction = direction;
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSizeAtOneMeter;
@@ -679,6 +691,7 @@ void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap,
s.shadows[shadowIndex].bulbRadiusLs =
mSoftShadowOptions.penumbraScale * options->shadowBulbRadius
/ wsTexelSizeAtOneMeter;
}
}
@@ -740,7 +753,6 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
// and if we need to generate it, update all the UBO data
// Note: this below is done for all six faces even if it sets identical values each time
if (shadowMap.hasVisibleShadows()) {
const size_t shadowIndex = shadowMap.getShadowIndex();
const float wsTexelSizeAtOneMeter = shaderParameters.texelSizeAtOneMeterWs;
@@ -750,7 +762,7 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap,
auto& s = mShadowUb.edit();
const double n = shadowMap.getCamera().getNear();
const double f = shadowMap.getCamera().getCullingFar();
s.shadows[shadowIndex].layer = shadowMap.getLayer();
s.shadows[shadowIndex].lightFromWorldMatrix = {}; // no texture matrix for point lights
s.shadows[shadowIndex].direction = {}; // no direction of point lights
s.shadows[shadowIndex].normalBias = normalBias * wsTexelSizeAtOneMeter;
@@ -779,14 +791,12 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
for (auto const* pShadowMap : mSpotShadowMaps) {
const size_t lightIndex = pShadowMap->getLightIndex();
// FIXME: currently we have one slot per shadowmap in the UBO, but we now have up to
// 6 shadowmap per light. So for now, we only write the data of the face 0,
// and the shader will figure out where to find the other face (layer+face)
// gather the per-light (not per shadow map) information. For point lights we will
// "see" 6 shadowmaps (one per face), we must use the first face one, the shader
// knows how to find the entry for other faces (they're guaranteed to be sequential).
if (pShadowMap->getFace() == 0) {
shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly?
shadowInfo[lightIndex].index = pShadowMap->getShadowIndex();
shadowInfo[lightIndex].layer = pShadowMap->getLayer();
}
}
}

View File

@@ -45,14 +45,10 @@ class FrameGraph;
class RenderPass;
struct ShadowMappingUniforms {
std::array<math::mat4f, CONFIG_MAX_SHADOW_CASCADES> lightFromWorldMatrix;
math::float4 cascadeSplits;
float shadowBulbRadiusLs;
float shadowBias;
float ssContactShadowDistance;
uint32_t directionalShadows;
uint32_t cascades;
bool elvsm;
};
class ShadowMapManager {
@@ -105,7 +101,7 @@ public:
ShadowMap* getPointOrSpotShadowMap(size_t index) noexcept {
assert_invariant(index < CONFIG_MAX_SHADOWMAPS);
return std::launder(reinterpret_cast<ShadowMap*>(
&mShadowMapCache[CONFIG_MAX_SHADOW_CASCADES + index]));
&mShadowMapCache[index]));
}
ShadowMap const* getPointOrSpotShadowMap(size_t spot) const noexcept {
@@ -215,13 +211,13 @@ private:
utils::FixedCapacityVector<ShadowMap*> mSpotShadowMaps{
utils::FixedCapacityVector<ShadowMap*>::with_capacity(
CONFIG_MAX_SHADOWMAPS) };
CONFIG_MAX_SHADOWMAPS - CONFIG_MAX_SHADOW_CASCADES) };
// inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
// because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
// Each ShadowMap is currently 40 bytes (total of 2.5KB for 64 shadow maps)
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap), alignof(ShadowMap)>::type;
std::array<ShadowMapStorage, CONFIG_MAX_SHADOW_CASCADES + CONFIG_MAX_SHADOWMAPS> mShadowMapCache;
std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS> mShadowMapCache;
};
} // namespace filament

View File

@@ -343,9 +343,10 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, ArenaScope& rootAren
lp[gpuIndex].typeShadow = LightsUib::packTypeShadow(
lcm.isPointLight(li) ? 0u : 1u,
shadowInfo[i].contactShadows,
shadowInfo[i].index,
shadowInfo[i].layer);
lp[gpuIndex].channels = LightsUib::packChannels(lcm.getLightChannels(li), shadowInfo[i].castsShadows);
shadowInfo[i].index);
lp[gpuIndex].channels = LightsUib::packChannels(
lcm.getLightChannels(li),
shadowInfo[i].castsShadows);
}
driver.updateBufferObject(lightUbh, { lp, positionalLightCount * sizeof(LightsUib) }, 0);

View File

@@ -155,7 +155,6 @@ public:
bool castsShadows = false; // whether this light casts shadows
bool contactShadows = false; // whether this light casts contact shadows
uint8_t index = 0; // an index into the arrays in the Shadows uniform buffer
uint8_t layer = 0; // which layer of the shadow texture array to sample from
};
enum {
@@ -179,7 +178,8 @@ public:
LightSoa const& getLightData() const noexcept { return mLightData; }
LightSoa& getLightData() noexcept { return mLightData; }
void updateUBOs(utils::Range<uint32_t> visibleRenderables, backend::Handle<backend::HwBufferObject> renderableUbh) noexcept;
void updateUBOs(utils::Range<uint32_t> visibleRenderables,
backend::Handle<backend::HwBufferObject> renderableUbh) noexcept;
bool hasContactShadows() const noexcept;

View File

@@ -27,7 +27,7 @@
namespace filament {
// update this when a new version of filament wouldn't work with older materials
static constexpr size_t MATERIAL_VERSION = 28;
static constexpr size_t MATERIAL_VERSION = 29;
/**
* Supported shading models

View File

@@ -124,12 +124,10 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
// bit 0-3: cascade count
// bit 4: visualize cascades
// bit 8-11: cascade has visible shadows
// bit 31: elvsm
uint32_t cascades;
float shadowBulbRadiusLs; // light radius in light-space
float shadowBias; // normal bias
float reserved0;
float reserved1; // normal bias
float shadowPenumbraRatioScale; // For DPCF or PCSS, scale penumbra ratio for artistic use
std::array<math::mat4f, CONFIG_MAX_SHADOW_CASCADES> lightFromWorldMatrix;
// --------------------------------------------------------------------------------------------
// VSM shadows [variant: VSM]
@@ -164,7 +162,7 @@ struct PerViewUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
float ssrStride; // ssr texel stride, >= 1.0
// bring PerViewUib to 2 KiB
math::float4 reserved[47];
math::float4 reserved[63];
};
// 2 KiB == 128 float4s
@@ -229,11 +227,11 @@ struct LightsUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
math::float2 spotScaleOffset; // { scale, offset }
float reserved3; // 0
float intensity; // float
uint32_t typeShadow; // 0x00.ll.ii.ct (t: 0=point, 1=spot, c:contact, ii: index, ll: layer)
uint32_t typeShadow; // 0x00.00.ii.ct (t: 0=point, 1=spot, c:contact, ii: index)
uint32_t channels; // 0x000c00ll (ll: light channels, c: caster)
static uint32_t packTypeShadow(uint8_t type, bool contactShadow, uint8_t index, uint8_t layer) noexcept {
return (type & 0xF) | (contactShadow ? 0x10 : 0x00) | (index << 8) | (layer << 16);
static uint32_t packTypeShadow(uint8_t type, bool contactShadow, uint8_t index) noexcept {
return (type & 0xF) | (contactShadow ? 0x10 : 0x00) | (index << 8);
}
static uint32_t packChannels(uint8_t lightChannels, bool castShadows) noexcept {
return lightChannels | (castShadows ? 0x10000 : 0);
@@ -258,6 +256,11 @@ struct ShadowUib { // NOLINT(cppcoreguidelines-pro-type-member-init)
float bulbRadiusLs; // 4
float nearOverFarMinusNear; // 4
bool elvsm; // 4
uint32_t layer; // 4
uint32_t reserved0; // 4
uint32_t reserved1; // 4
uint32_t reserved2; // 4
};
ShadowData shadows[CONFIG_MAX_SHADOWMAPS];
};

View File

@@ -105,10 +105,9 @@ BufferInterfaceBlock const& UibGenerator::getPerViewUib() noexcept {
{ "cascadeSplits", 0, Type::FLOAT4, Precision::HIGH },
{ "cascades", 0, Type::UINT },
{ "shadowBulbRadiusLs", 0, Type::FLOAT },
{ "shadowBias", 0, Type::FLOAT },
{ "reserved0", 0, Type::FLOAT },
{ "reserved1", 0, Type::FLOAT },
{ "shadowPenumbraRatioScale", 0, Type::FLOAT },
{ "lightFromWorldMatrix", 4, Type::MAT4, Precision::HIGH },
// ------------------------------------------------------------------------------------
// VSM shadows [variant: VSM]

View File

@@ -287,6 +287,10 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel,
UniformBindingPoints::PER_VIEW, UibGenerator::getPerViewUib());
cg.generateUniforms(vs, ShaderStage::VERTEX,
UniformBindingPoints::PER_RENDERABLE, UibGenerator::getPerRenderableUib());
if (litVariants && filament::Variant::isShadowReceiverVariant(variant)) {
cg.generateUniforms(vs, ShaderStage::FRAGMENT,
UniformBindingPoints::SHADOW, UibGenerator::getShadowUib());
}
if (variant.hasSkinningOrMorphing()) {
cg.generateUniforms(vs, ShaderStage::VERTEX,
UniformBindingPoints::PER_RENDERABLE_BONES,

View File

@@ -9,7 +9,6 @@ struct Light {
bool contactShadows;
uint type;
uint shadowIndex;
uint shadowLayer;
uint channels;
};

View File

@@ -9,6 +9,10 @@ struct ShadowData {
float bulbRadiusLs;
float nearOverFarMinusNear;
bool elvsm;
uint layer;
uint reserved0;
uint reserved1;
uint reserved2;
};
struct BoneData {

View File

@@ -134,8 +134,9 @@ highp vec4 getCascadeLightSpacePosition(uint cascade) {
}
return computeLightSpacePosition(getWorldPosition(), getWorldNormalVector(),
frameUniforms.lightDirection, frameUniforms.shadowBias,
frameUniforms.lightFromWorldMatrix[cascade]);
frameUniforms.lightDirection,
shadowUniforms.shadows[cascade].normalBias,
shadowUniforms.shadows[cascade].lightFromWorldMatrix);
}
#endif

View File

@@ -13,10 +13,6 @@ int getInstanceIndex() {
// Uniforms access
//------------------------------------------------------------------------------
mat4 getLightFromWorldMatrix() {
return frameUniforms.lightFromWorldMatrix[0];
}
PerRenderableData getObjectUniforms() {
#if defined(MATERIAL_HAS_INSTANCES)
// the material manages instancing, all instances share the same uniform block.

View File

@@ -56,9 +56,8 @@ void evaluateDirectionalLight(const MaterialInputs material,
bool cascadeHasVisibleShadows = bool(frameUniforms.cascades & ((1u << cascade) << 8u));
bool hasDirectionalShadows = bool(frameUniforms.directionalShadows & 1u);
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
uint layer = cascade;
highp vec4 shadowPosition = getShadowPosition(true, 0u, cascade, 0.0f);
visibility = shadow(true, light_shadowMap, layer, 0u, shadowPosition, 0.0f);
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
}
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {

View File

@@ -158,7 +158,6 @@ Light getLight(const uint lightIndex) {
light.type = (typeShadow & 0x1u);
#if defined(VARIANT_HAS_SHADOWING)
light.shadowIndex = (typeShadow >> 8u) & 0xFFu;
light.shadowLayer = (typeShadow >> 16u) & 0xFFu;
light.castsShadows = bool(channels & 0x10000u);
if (light.type == LIGHT_TYPE_SPOT) {
light.zLight = dot(shadowUniforms.shadows[light.shadowIndex].lightFromWorldZ, vec4(worldPosition, 1.0));
@@ -211,19 +210,20 @@ void evaluatePunctualLights(const MaterialInputs material,
#if defined(VARIANT_HAS_SHADOWING)
if (light.NoL > 0.0) {
if (light.castsShadows) {
uint layer = light.shadowLayer;
uint shadowIndex = light.shadowIndex;
highp vec4 shadowPosition;
if (light.type == LIGHT_TYPE_POINT) {
// point-light shadows are sampled from a direction
highp vec3 r = getWorldPosition() - light.worldPosition;
highp vec4 nf = shadowUniforms.shadows[light.shadowIndex].lightFromWorldZ;
highp uint face = 0u;
// getShadowPosition returns zLight which is needed for PCSS/DPCF
shadowPosition = getShadowPosition(r, nf, layer, light.zLight);
shadowPosition = getShadowPosition(r, shadowIndex, light.zLight, face);
shadowIndex += face;
} else {
// getShadowPosition needs zLight for applying the normal bias
shadowPosition = getShadowPosition(false, light.shadowIndex, 0u, light.zLight);
shadowPosition = getShadowPosition(false, shadowIndex, 0u, light.zLight);
}
visibility = shadow(false, light_shadowMap, layer, light.shadowIndex,
visibility = shadow(false, light_shadowMap, shadowIndex,
shadowPosition, light.zLight);
}
if (light.contactShadows && visibility > 0.0) {

View File

@@ -143,7 +143,9 @@ void main() {
#if defined(VARIANT_HAS_SHADOWING) && defined(VARIANT_HAS_DIRECTIONAL_LIGHTING)
vertex_lightSpacePosition = computeLightSpacePosition(
vertex_worldPosition.xyz, vertex_worldNormal,
frameUniforms.lightDirection, frameUniforms.shadowBias, getLightFromWorldMatrix());
frameUniforms.lightDirection,
shadowUniforms.shadows[0].normalBias,
shadowUniforms.shadows[0].lightFromWorldMatrix);
#endif
#endif // !defined(USE_OPTIMIZED_DEPTH_VERTEX_SHADER)

View File

@@ -50,9 +50,8 @@ vec4 evaluateMaterial(const MaterialInputs material) {
bool cascadeHasVisibleShadows = bool(frameUniforms.cascades & ((1u << cascade) << 8u));
bool hasDirectionalShadows = bool(frameUniforms.directionalShadows & 1u);
if (hasDirectionalShadows && cascadeHasVisibleShadows) {
uint layer = cascade;
highp vec4 shadowPosition = getShadowPosition(true, 0u, cascade, 0.0f);
visibility = shadow(true, light_shadowMap, layer, 0u, shadowPosition, 0.0f);
visibility = shadow(true, light_shadowMap, cascade, shadowPosition, 0.0f);
}
if ((frameUniforms.directionalShadows & 0x2u) != 0u && visibility > 0.0) {
if ((getObjectUniforms().flagsChannels & FILAMENT_OBJECT_CONTACT_SHADOWS_BIT) != 0u) {

View File

@@ -161,7 +161,7 @@ float getPenumbraLs(const bool DIRECTIONAL, const uint index, const highp float
float penumbra;
// This conditional is resolved at compile time
if (DIRECTIONAL) {
penumbra = frameUniforms.shadowBulbRadiusLs;
penumbra = shadowUniforms.shadows[index].bulbRadiusLs;
} else {
// the penumbra radius depends on the light-space z for spotlights
penumbra = shadowUniforms.shadows[index].bulbRadiusLs / zLight;
@@ -495,8 +495,8 @@ highp vec4 getShadowPosition(const bool DIRECTIONAL,
}
// get {texture coordinate, layer} for point shadow maps
highp vec4 getShadowPosition(const highp vec3 r, const highp vec4 nf,
inout uint layer, out highp float d) {
highp vec4 getShadowPosition(const highp vec3 r, const highp uint shadowIndex,
out highp float d, out highp uint face) {
highp vec4 tc;
highp float rx = abs(r.x);
highp float ry = abs(r.y);
@@ -506,20 +506,22 @@ highp vec4 getShadowPosition(const highp vec3 r, const highp vec4 nf,
if (d == rx) {
tc.x = r.x >= 0.0 ? r.z : -r.z;
tc.y = r.y;
layer += (r.x >= 0.0 ? 0u : 1u);
face = (r.x >= 0.0 ? 0u : 1u);
} else if (d == ry) {
tc.x = r.y >= 0.0 ? r.x : -r.x;
tc.y = r.z;
layer += (r.y >= 0.0 ? 2u : 3u);
face = (r.y >= 0.0 ? 2u : 3u);
} else {
tc.x = r.z >= 0.0 ? -r.x : r.x;
tc.y = r.y;
layer += (r.z >= 0.0 ? 4u : 5u);
face = (r.z >= 0.0 ? 4u : 5u);
}
// ma is guaranteed to be >= sc and tc
tc.xy = (tc.xy * ma + vec2(1.0)) * 0.5;
highp vec4 nf = shadowUniforms.shadows[shadowIndex + face].lightFromWorldZ;
// z coordinate of the normalized fragment position in light-space
// i.e.: remap [near, far] to [0,1] : d = (d - n) / (f - n)
d = nf[2] + nf[3] * d;
@@ -542,7 +544,8 @@ highp vec4 getShadowPosition(const highp vec3 r, const highp vec4 nf,
// PCF sampling
float shadow(const bool DIRECTIONAL,
const mediump sampler2DArrayShadow shadowMap,
const uint layer, const uint index, highp vec4 shadowPosition, highp float zLight) {
const uint index, highp vec4 shadowPosition, highp float zLight) {
uint layer = shadowUniforms.shadows[index].layer;
#if SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_HARD
return ShadowSample_PCF_Hard(shadowMap, layer, shadowPosition);
#elif SHADOW_SAMPLING_METHOD == SHADOW_SAMPLING_PCF_LOW
@@ -553,16 +556,11 @@ float shadow(const bool DIRECTIONAL,
// Shadow requiring a sampler2D sampler (VSM, DPCF and PCSS)
float shadow(const bool DIRECTIONAL,
const mediump sampler2DArray shadowMap,
const uint layer, const uint index, highp vec4 shadowPosition, highp float zLight) {
const uint index, highp vec4 shadowPosition, highp float zLight) {
uint layer = shadowUniforms.shadows[index].layer;
// This conditional is resolved at compile time
if (frameUniforms.shadowSamplingType == SHADOW_SAMPLING_RUNTIME_EVSM) {
bool elvsm = false;
if (DIRECTIONAL) {
elvsm = bool((frameUniforms.cascades >> 31u) & 1u);
} else {
elvsm = shadowUniforms.shadows[index].elvsm;
}
bool elvsm = shadowUniforms.shadows[index].elvsm;
return ShadowSample_VSM(elvsm, shadowMap, layer, shadowPosition);
}