mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 08:14:48 +02:00
Merge pull request #15411 from Zvork/shadow
Case 22117: Shadows Appear Incorrectly Placed Relative to Avatars
This commit is contained in:
commit
7a9dd49eed
21 changed files with 220 additions and 103 deletions
|
@ -313,11 +313,9 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true);
|
||||
|
||||
// bind the material
|
||||
RenderPipelines::bindMaterial(drawMaterial, batch, args->_enableTexturing);
|
||||
drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true);
|
||||
// bind the material
|
||||
if (RenderPipelines::bindMaterial(drawMaterial, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,8 +291,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
|
|||
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
|
||||
}
|
||||
} else {
|
||||
if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
RenderPipelines::bindMaterials(materials, batch, args->_enableTexturing);
|
||||
if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,22 @@ bool Light::getCastShadows() const {
|
|||
return _castShadows;
|
||||
}
|
||||
|
||||
void Light::setShadowsMaxDistance(const float maxDistance) {
|
||||
_shadowsMaxDistance = std::max(0.0f, maxDistance);
|
||||
}
|
||||
|
||||
float Light::getShadowsMaxDistance() const {
|
||||
return _shadowsMaxDistance;
|
||||
}
|
||||
|
||||
void Light::setShadowsBiasScale(const float scale) {
|
||||
_shadowsBiasScale = std::max(0.0f, scale);
|
||||
}
|
||||
|
||||
float Light::getShadowsBiasScale() const {
|
||||
return _shadowsBiasScale;
|
||||
}
|
||||
|
||||
void Light::setColor(const Color& color) {
|
||||
_lightSchemaBuffer.edit().irradiance.color = color;
|
||||
updateLightRadius();
|
||||
|
|
|
@ -106,6 +106,12 @@ public:
|
|||
void setCastShadows(const bool castShadows);
|
||||
bool getCastShadows() const;
|
||||
|
||||
void setShadowsMaxDistance(const float maxDistance);
|
||||
float getShadowsMaxDistance() const;
|
||||
|
||||
void setShadowsBiasScale(const float scale);
|
||||
float getShadowsBiasScale() const;
|
||||
|
||||
void setOrientation(const Quat& orientation);
|
||||
const glm::quat& getOrientation() const { return _transform.getRotation(); }
|
||||
|
||||
|
@ -192,10 +198,11 @@ protected:
|
|||
Type _type { SUN };
|
||||
float _spotCos { -1.0f }; // stored here to be able to reset the spot angle when turning the type spot on/off
|
||||
|
||||
void updateLightRadius();
|
||||
|
||||
float _shadowsMaxDistance{ 40.0f };
|
||||
float _shadowsBiasScale{ 1.0f };
|
||||
bool _castShadows{ false };
|
||||
|
||||
void updateLightRadius();
|
||||
};
|
||||
typedef std::shared_ptr< Light > LightPointer;
|
||||
|
||||
|
|
|
@ -149,7 +149,6 @@ float fetchScatteringMap(vec2 uv) {
|
|||
|
||||
<@endfunc@>
|
||||
|
||||
|
||||
<@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@>
|
||||
if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) {
|
||||
discard;
|
||||
|
|
|
@ -120,7 +120,7 @@ float LightStage::Shadow::Cascade::computeFarDistance(const ViewFrustum& viewFru
|
|||
return far;
|
||||
}
|
||||
|
||||
LightStage::Shadow::Shadow(graphics::LightPointer light, float maxDistance, unsigned int cascadeCount) :
|
||||
LightStage::Shadow::Shadow(graphics::LightPointer light, unsigned int cascadeCount) :
|
||||
_light{ light } {
|
||||
cascadeCount = std::min(cascadeCount, (unsigned int)SHADOW_CASCADE_MAX_COUNT);
|
||||
Schema schema;
|
||||
|
@ -149,70 +149,79 @@ LightStage::Shadow::Shadow(graphics::LightPointer light, float maxDistance, unsi
|
|||
cascade.framebuffer->setDepthBuffer(map, depthFormat, cascadeIndex);
|
||||
}
|
||||
|
||||
setMaxDistance(maxDistance);
|
||||
if (light) {
|
||||
setMaxDistance(light->getShadowsMaxDistance());
|
||||
}
|
||||
}
|
||||
|
||||
void LightStage::Shadow::setLight(graphics::LightPointer light) {
|
||||
_light = light;
|
||||
if (light) {
|
||||
setMaxDistance(light->getShadowsMaxDistance());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LightStage::Shadow::setMaxDistance(float value) {
|
||||
// This overlaping factor isn't really used directly for blending of shadow cascades. It
|
||||
// just there to be sure the cascades do overlap. The blending width used is relative
|
||||
// to the UV space and is set in the Schema with invCascadeBlendWidth.
|
||||
static const auto OVERLAP_FACTOR = 1.0f / 5.0f;
|
||||
static const auto MINIMUM_MAXDISTANCE = 1e-3f;
|
||||
|
||||
_maxDistance = std::max(0.0f, value);
|
||||
value = std::max(MINIMUM_MAXDISTANCE, value);
|
||||
if (value != _maxDistance) {
|
||||
// This overlaping factor isn't really used directly for blending of shadow cascades. It's
|
||||
// just there to be sure the cascades do overlap. The blending width used is relative
|
||||
// to the UV space and is set in the Schema with invCascadeBlendWidth.
|
||||
static const auto OVERLAP_FACTOR = 1.0f / 5.0f;
|
||||
|
||||
if (_cascades.size() == 1) {
|
||||
_cascades.front().setMinDistance(0.0f);
|
||||
_cascades.front().setMaxDistance(_maxDistance);
|
||||
} else {
|
||||
// Distribute the cascades along that distance
|
||||
// TODO : these parameters should be exposed to the user as part of the light entity parameters, no?
|
||||
static const auto LOW_MAX_DISTANCE = 2.0f;
|
||||
static const auto MAX_RESOLUTION_LOSS = 0.6f; // Between 0 and 1, 0 giving tighter distributions
|
||||
_maxDistance = value;
|
||||
|
||||
// The max cascade distance is computed by multiplying the previous cascade's max distance by a certain
|
||||
// factor. There is a "user" factor that is computed from a desired max resolution loss in the shadow
|
||||
// and an optimal one based on the global min and max shadow distance, all cascades considered. The final
|
||||
// distance is a gradual blend between the two
|
||||
const auto userDistanceScale = 1.0f / (1.0f - MAX_RESOLUTION_LOSS);
|
||||
const auto optimalDistanceScale = powf(_maxDistance / LOW_MAX_DISTANCE, 1.0f / (_cascades.size() - 1));
|
||||
if (_cascades.size() == 1) {
|
||||
_cascades.front().setMinDistance(0.0f);
|
||||
_cascades.front().setMaxDistance(_maxDistance);
|
||||
} else {
|
||||
// Distribute the cascades along that distance
|
||||
// TODO : these parameters should be exposed to the user as part of the light entity parameters, no?
|
||||
static const auto LOW_MAX_DISTANCE = 2.0f;
|
||||
static const auto MAX_RESOLUTION_LOSS = 0.6f; // Between 0 and 1, 0 giving tighter distributions
|
||||
|
||||
float maxCascadeUserDistance = LOW_MAX_DISTANCE;
|
||||
float maxCascadeOptimalDistance = LOW_MAX_DISTANCE;
|
||||
float minCascadeDistance = 0.0f;
|
||||
// The max cascade distance is computed by multiplying the previous cascade's max distance by a certain
|
||||
// factor. There is a "user" factor that is computed from a desired max resolution loss in the shadow
|
||||
// and an optimal one based on the global min and max shadow distance, all cascades considered. The final
|
||||
// distance is a gradual blend between the two
|
||||
const auto userDistanceScale = 1.0f / (1.0f - MAX_RESOLUTION_LOSS);
|
||||
const auto optimalDistanceScale = powf(_maxDistance / LOW_MAX_DISTANCE, 1.0f / (_cascades.size() - 1));
|
||||
|
||||
for (size_t cascadeIndex = 0; cascadeIndex < _cascades.size(); ++cascadeIndex) {
|
||||
float blendFactor = cascadeIndex / float(_cascades.size() - 1);
|
||||
float maxCascadeDistance;
|
||||
float maxCascadeUserDistance = LOW_MAX_DISTANCE;
|
||||
float maxCascadeOptimalDistance = LOW_MAX_DISTANCE;
|
||||
float minCascadeDistance = 0.0f;
|
||||
|
||||
if (cascadeIndex == size_t(_cascades.size() - 1)) {
|
||||
maxCascadeDistance = _maxDistance;
|
||||
} else {
|
||||
maxCascadeDistance = maxCascadeUserDistance + (maxCascadeOptimalDistance - maxCascadeUserDistance)*blendFactor*blendFactor;
|
||||
for (size_t cascadeIndex = 0; cascadeIndex < _cascades.size(); ++cascadeIndex) {
|
||||
float blendFactor = cascadeIndex / float(_cascades.size() - 1);
|
||||
float maxCascadeDistance;
|
||||
|
||||
if (cascadeIndex == size_t(_cascades.size() - 1)) {
|
||||
maxCascadeDistance = _maxDistance;
|
||||
} else {
|
||||
maxCascadeDistance = maxCascadeUserDistance + (maxCascadeOptimalDistance - maxCascadeUserDistance)*blendFactor*blendFactor;
|
||||
}
|
||||
|
||||
float shadowOverlapDistance = maxCascadeDistance * OVERLAP_FACTOR;
|
||||
|
||||
_cascades[cascadeIndex].setMinDistance(minCascadeDistance);
|
||||
_cascades[cascadeIndex].setMaxDistance(maxCascadeDistance + shadowOverlapDistance);
|
||||
|
||||
// Compute distances for next cascade
|
||||
minCascadeDistance = maxCascadeDistance;
|
||||
maxCascadeUserDistance = maxCascadeUserDistance * userDistanceScale;
|
||||
maxCascadeOptimalDistance = maxCascadeOptimalDistance * optimalDistanceScale;
|
||||
maxCascadeUserDistance = std::min(maxCascadeUserDistance, _maxDistance);
|
||||
}
|
||||
|
||||
float shadowOverlapDistance = maxCascadeDistance * OVERLAP_FACTOR;
|
||||
|
||||
_cascades[cascadeIndex].setMinDistance(minCascadeDistance);
|
||||
_cascades[cascadeIndex].setMaxDistance(maxCascadeDistance + shadowOverlapDistance);
|
||||
|
||||
// Compute distances for next cascade
|
||||
minCascadeDistance = maxCascadeDistance;
|
||||
maxCascadeUserDistance = maxCascadeUserDistance * userDistanceScale;
|
||||
maxCascadeOptimalDistance = maxCascadeOptimalDistance * optimalDistanceScale;
|
||||
maxCascadeUserDistance = std::min(maxCascadeUserDistance, _maxDistance);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the buffer
|
||||
const auto& lastCascade = _cascades.back();
|
||||
auto& schema = _schemaBuffer.edit<Schema>();
|
||||
schema.maxDistance = _maxDistance;
|
||||
schema.invFalloffDistance = 1.0f / (OVERLAP_FACTOR*lastCascade.getMaxDistance());
|
||||
// Update the buffer
|
||||
const auto& lastCascade = _cascades.back();
|
||||
auto& schema = _schemaBuffer.edit<Schema>();
|
||||
schema.maxDistance = _maxDistance;
|
||||
schema.invFalloffDistance = 1.0f / (OVERLAP_FACTOR*lastCascade.getMaxDistance());
|
||||
}
|
||||
}
|
||||
|
||||
void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum,
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
float left, float right, float bottom, float top, float viewMaxShadowDistance) const;
|
||||
};
|
||||
|
||||
Shadow(graphics::LightPointer light, float maxDistance, unsigned int cascadeCount = 1);
|
||||
Shadow(graphics::LightPointer light, unsigned int cascadeCount = 1);
|
||||
|
||||
void setLight(graphics::LightPointer light);
|
||||
|
||||
|
@ -104,16 +104,14 @@ public:
|
|||
};
|
||||
protected:
|
||||
|
||||
|
||||
using Cascades = std::vector<Cascade>;
|
||||
|
||||
static const glm::mat4 _biasMatrix;
|
||||
|
||||
graphics::LightPointer _light;
|
||||
float _maxDistance;
|
||||
float _maxDistance{ 0.0f };
|
||||
Cascades _cascades;
|
||||
|
||||
|
||||
UniformBufferView _schemaBuffer = nullptr;
|
||||
};
|
||||
|
||||
|
|
|
@ -154,8 +154,7 @@ void MeshPartPayload::render(RenderArgs* args) {
|
|||
bindMesh(batch);
|
||||
|
||||
// apply material properties
|
||||
if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
RenderPipelines::bindMaterials(_drawMaterials, batch, args->_enableTexturing);
|
||||
if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
|
@ -434,8 +433,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
|
|||
}
|
||||
|
||||
// apply material properties
|
||||
if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
RenderPipelines::bindMaterials(_drawMaterials, batch, args->_enableTexturing);
|
||||
if (RenderPipelines::bindMaterials(_drawMaterials, batch, args->_renderMode, args->_enableTexturing)) {
|
||||
args->_details._materialSwitches++;
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input
|
|||
sprintf(jobName, "DrawShadowFrustum%d", i);
|
||||
task.addJob<DrawFrustum>(jobName, shadowFrustum, glm::vec3(0.0f, tint, 1.0f));
|
||||
if (!renderShadowTaskOut.isNull()) {
|
||||
const auto& shadowCascadeSceneBBoxes = renderShadowTaskOut;
|
||||
const auto& shadowCascadeSceneBBoxes = renderShadowTaskOut.get<RenderShadowTask::CascadeBoxes>();
|
||||
const auto shadowBBox = shadowCascadeSceneBBoxes[ExtractFrustums::SHADOW_CASCADE0_FRUSTUM + i];
|
||||
sprintf(jobName, "DrawShadowBBox%d", i);
|
||||
task.addJob<DrawAABox>(jobName, shadowBBox, glm::vec3(1.0f, tint, 0.0f));
|
||||
|
|
|
@ -373,10 +373,10 @@ void initZPassPipelines(ShapePlumber& shapePlumber, gpu::StatePointer state, con
|
|||
gpu::Shader::createProgram(deformed_model_shadow_fade_dq), state, extraBatchSetter, itemSetter);
|
||||
}
|
||||
|
||||
void RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures) {
|
||||
bool RenderPipelines::bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) {
|
||||
graphics::MultiMaterial multiMaterial;
|
||||
multiMaterial.push(graphics::MaterialLayer(material, 0));
|
||||
bindMaterials(multiMaterial, batch, enableTextures);
|
||||
return bindMaterials(multiMaterial, batch, renderMode, enableTextures);
|
||||
}
|
||||
|
||||
void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial) {
|
||||
|
@ -730,7 +730,7 @@ void RenderPipelines::updateMultiMaterial(graphics::MultiMaterial& multiMaterial
|
|||
multiMaterial.setInitialized();
|
||||
}
|
||||
|
||||
void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures) {
|
||||
bool RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures) {
|
||||
if (multiMaterial.shouldUpdate()) {
|
||||
updateMultiMaterial(multiMaterial);
|
||||
}
|
||||
|
@ -738,8 +738,13 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu:
|
|||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
||||
static gpu::TextureTablePointer defaultMaterialTextures = std::make_shared<gpu::TextureTable>();
|
||||
static gpu::BufferView defaultMaterialSchema;
|
||||
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [textureCache] {
|
||||
graphics::MultiMaterial::Schema schema;
|
||||
defaultMaterialSchema = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(schema), (const gpu::Byte*) &schema, sizeof(schema)));
|
||||
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialAlbedo, textureCache->getWhiteTexture());
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialMetallic, textureCache->getBlackTexture());
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialRoughness, textureCache->getWhiteTexture());
|
||||
|
@ -749,17 +754,29 @@ void RenderPipelines::bindMaterials(graphics::MultiMaterial& multiMaterial, gpu:
|
|||
// MaterialEmissiveLightmap has to be set later
|
||||
});
|
||||
|
||||
auto& schemaBuffer = multiMaterial.getSchemaBuffer();
|
||||
batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer);
|
||||
if (enableTextures) {
|
||||
batch.setResourceTextureTable(multiMaterial.getTextureTable());
|
||||
} else {
|
||||
auto key = multiMaterial.getMaterialKey();
|
||||
if (key.isLightmapMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture());
|
||||
} else if (key.isEmissiveMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture());
|
||||
// For shadows, we only need opacity mask information
|
||||
auto key = multiMaterial.getMaterialKey();
|
||||
if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE || key.isOpacityMaskMap()) {
|
||||
auto& schemaBuffer = multiMaterial.getSchemaBuffer();
|
||||
batch.setUniformBuffer(gr::Buffer::Material, schemaBuffer);
|
||||
if (enableTextures) {
|
||||
batch.setResourceTextureTable(multiMaterial.getTextureTable());
|
||||
} else {
|
||||
if (renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {
|
||||
if (key.isLightmapMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getBlackTexture());
|
||||
} else if (key.isEmissiveMap()) {
|
||||
defaultMaterialTextures->setTexture(gr::Texture::MaterialEmissiveLightmap, textureCache->getGrayTexture());
|
||||
}
|
||||
}
|
||||
|
||||
batch.setResourceTextureTable(defaultMaterialTextures);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
batch.setResourceTextureTable(defaultMaterialTextures);
|
||||
batch.setUniformBuffer(gr::Buffer::Material, defaultMaterialSchema);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
#define hifi_RenderPipelines_h
|
||||
|
||||
#include <graphics/Material.h>
|
||||
#include <render/Args.h>
|
||||
|
||||
class RenderPipelines {
|
||||
public:
|
||||
static void bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, bool enableTextures);
|
||||
static void updateMultiMaterial(graphics::MultiMaterial& multiMaterial);
|
||||
static void bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, bool enableTextures);
|
||||
static bool bindMaterial(graphics::MaterialPointer& material, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures);
|
||||
static bool bindMaterials(graphics::MultiMaterial& multiMaterial, gpu::Batch& batch, render::Args::RenderMode renderMode, bool enableTextures);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#define SHADOW_FRUSTUM_NEAR 1.0f
|
||||
#define SHADOW_FRUSTUM_FAR 500.0f
|
||||
static const unsigned int SHADOW_CASCADE_COUNT{ 4 };
|
||||
static const float SHADOW_MAX_DISTANCE{ 40.0f };
|
||||
|
||||
using namespace render;
|
||||
|
||||
|
@ -90,7 +89,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
#endif
|
||||
};
|
||||
|
||||
render::VaryingArray<AABox,4> cascadeSceneBBoxes;
|
||||
CascadeBoxes cascadeSceneBBoxes;
|
||||
|
||||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||
char jobName[64];
|
||||
|
@ -336,7 +335,7 @@ void RenderShadowSetup::setConstantBias(int cascadeIndex, float value) {
|
|||
}
|
||||
|
||||
void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) {
|
||||
_bias[cascadeIndex]._slope = value * value * value * 0.01f;
|
||||
_bias[cascadeIndex]._slope = value * value * value * 0.001f;
|
||||
}
|
||||
|
||||
void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) {
|
||||
|
@ -367,7 +366,7 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c
|
|||
output.edit2() = _cameraFrustum;
|
||||
|
||||
if (!_globalShadowObject) {
|
||||
_globalShadowObject = std::make_shared<LightStage::Shadow>(graphics::LightPointer(), SHADOW_MAX_DISTANCE, SHADOW_CASCADE_COUNT);
|
||||
_globalShadowObject = std::make_shared<LightStage::Shadow>(currentKeyLight, SHADOW_CASCADE_COUNT);
|
||||
}
|
||||
|
||||
_globalShadowObject->setLight(currentKeyLight);
|
||||
|
@ -378,11 +377,12 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c
|
|||
unsigned int cascadeIndex;
|
||||
|
||||
// Adjust each cascade frustum
|
||||
const auto biasScale = currentKeyLight->getShadowsBiasScale();
|
||||
for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) {
|
||||
auto& bias = _bias[cascadeIndex];
|
||||
_globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(),
|
||||
SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR,
|
||||
bias._constant, bias._slope);
|
||||
SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR,
|
||||
bias._constant, bias._slope * biasScale);
|
||||
}
|
||||
|
||||
_shadowFrameCache->pushShadow(_globalShadowObject);
|
||||
|
|
|
@ -52,8 +52,9 @@ class RenderShadowTask {
|
|||
public:
|
||||
|
||||
// There is one AABox per shadow cascade
|
||||
using CascadeBoxes = render::VaryingArray<AABox, SHADOW_CASCADE_MAX_COUNT>;
|
||||
using Input = render::VaryingSet2<LightStage::FramePointer, LightingModelPointer>;
|
||||
using Output = render::VaryingSet2<render::VaryingArray<AABox, SHADOW_CASCADE_MAX_COUNT>, LightStage::ShadowFramePointer>;
|
||||
using Output = render::VaryingSet2<CascadeBoxes, LightStage::ShadowFramePointer>;
|
||||
using Config = RenderShadowTaskConfig;
|
||||
using JobModel = render::Task::ModelIO<RenderShadowTask, Input, Output, Config>;
|
||||
|
||||
|
@ -92,10 +93,10 @@ public:
|
|||
float constantBias1{ 0.15f };
|
||||
float constantBias2{ 0.175f };
|
||||
float constantBias3{ 0.2f };
|
||||
float slopeBias0{ 0.6f };
|
||||
float slopeBias1{ 0.6f };
|
||||
float slopeBias2{ 0.7f };
|
||||
float slopeBias3{ 0.82f };
|
||||
float slopeBias0{ 0.4f };
|
||||
float slopeBias1{ 0.45f };
|
||||
float slopeBias2{ 0.65f };
|
||||
float slopeBias3{ 0.7f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
|
|
|
@ -90,8 +90,8 @@ float evalShadowAttenuationPCF(int cascadeIndex, ShadowSampleOffsets offsets, ve
|
|||
return shadowAttenuation;
|
||||
}
|
||||
|
||||
float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float oneMinusNdotL) {
|
||||
float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * oneMinusNdotL;
|
||||
float evalShadowCascadeAttenuation(int cascadeIndex, ShadowSampleOffsets offsets, vec4 shadowTexcoord, float slopeNdotL) {
|
||||
float bias = getShadowFixedBias(cascadeIndex) + getShadowSlopeBias(cascadeIndex) * slopeNdotL;
|
||||
return evalShadowAttenuationPCF(cascadeIndex, offsets, shadowTexcoord, bias);
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,8 @@ float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDe
|
|||
vec3 cascadeMix;
|
||||
bvec4 isPixelOnCascade;
|
||||
int cascadeIndex;
|
||||
float oneMinusNdotL = 1.0 - clamp(dot(worldLightDir, worldNormal), 0.0, 1.0);
|
||||
float NdotL = clamp(dot(worldLightDir, worldNormal), 0.0, 1.0);
|
||||
float slopeNdotL = min(2.0, sqrt(1.0-NdotL*NdotL) / NdotL);
|
||||
|
||||
for (cascadeIndex=0 ; cascadeIndex<getShadowCascadeCount() ; cascadeIndex++) {
|
||||
cascadeShadowCoords[cascadeIndex] = evalShadowTexcoord(cascadeIndex, worldPosition);
|
||||
|
@ -115,10 +116,10 @@ float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDe
|
|||
isPixelOnCascade.z = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[2]);
|
||||
isPixelOnCascade.w = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[3]);
|
||||
|
||||
cascadeAttenuations.x = mix(1.0, evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], oneMinusNdotL), float(isPixelOnCascade.x));
|
||||
cascadeAttenuations.y = mix(1.0, evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], oneMinusNdotL), float(isPixelOnCascade.y));
|
||||
cascadeAttenuations.z = mix(1.0, evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], oneMinusNdotL), float(isPixelOnCascade.z));
|
||||
cascadeAttenuations.w = mix(1.0, evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], oneMinusNdotL), float(isPixelOnCascade.w));
|
||||
cascadeAttenuations.x = mix(1.0, evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], slopeNdotL), float(isPixelOnCascade.x));
|
||||
cascadeAttenuations.y = mix(1.0, evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], slopeNdotL), float(isPixelOnCascade.y));
|
||||
cascadeAttenuations.z = mix(1.0, evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], slopeNdotL), float(isPixelOnCascade.z));
|
||||
cascadeAttenuations.w = mix(1.0, evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], slopeNdotL), float(isPixelOnCascade.w));
|
||||
|
||||
cascadeWeights.x = evalShadowCascadeWeight(cascadeShadowCoords[0]);
|
||||
cascadeWeights.y = evalShadowCascadeWeight(cascadeShadowCoords[1]);
|
||||
|
|
|
@ -18,9 +18,15 @@
|
|||
<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, _SCRIBE_NULL, 1)$>
|
||||
<$declareMeshDeformerActivation(1, 1)$>
|
||||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include graphics/MaterialTextures.slh@>
|
||||
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS;
|
||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
||||
|
||||
void main(void) {
|
||||
vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
@ -33,5 +39,14 @@ void main(void) {
|
|||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, deformedPosition, _positionWS)$>
|
||||
|
||||
Material mat = getMaterial();
|
||||
BITFIELD matKey = getMaterialKey(mat);
|
||||
_texCoord01 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
// If we have an opacity mask than we need the first tex coord
|
||||
if ((matKey & OPACITY_MASK_MAP_BIT) != 0) {
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$>
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,15 @@
|
|||
<$declareMeshDeformer(_SCRIBE_NULL, _SCRIBE_NULL, 1, 1, 1)$>
|
||||
<$declareMeshDeformerActivation(1, 1)$>
|
||||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include graphics/MaterialTextures.slh@>
|
||||
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS;
|
||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
||||
|
||||
void main(void) {
|
||||
vec4 deformedPosition = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
@ -33,4 +39,13 @@ void main(void) {
|
|||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, deformedPosition, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, deformedPosition, _positionWS)$>
|
||||
|
||||
Material mat = getMaterial();
|
||||
BITFIELD matKey = getMaterialKey(mat);
|
||||
_texCoord01 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
// If we have an opacity mask than we need the first tex coord
|
||||
if ((matKey & OPACITY_MASK_MAP_BIT) != 0) {
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ void main(void) {
|
|||
<$fetchMaterialTexturesCoord1(matKey, _texCoord1, occlusionTex)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
vec3 albedo = getMaterialAlbedo(mat);
|
||||
|
|
|
@ -9,10 +9,26 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
<@include graphics/Material.slh@>
|
||||
<@include graphics/MaterialTextures.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
|
||||
#define _texCoord0 _texCoord01.xy
|
||||
|
||||
layout(location=0) out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
Material mat = getMaterial();
|
||||
BITFIELD matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -13,12 +13,16 @@
|
|||
<@include gpu/Inputs.slh@>
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<@include graphics/Material.slh@>
|
||||
<@include graphics/MaterialTextures.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
<$declareMaterialTexMapArrayBuffer()$>
|
||||
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) out vec4 _positionWS;
|
||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
|
||||
|
||||
void main(void) {
|
||||
// standard transform
|
||||
|
@ -26,4 +30,13 @@ void main(void) {
|
|||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _positionWS)$>
|
||||
|
||||
Material mat = getMaterial();
|
||||
BITFIELD matKey = getMaterialKey(mat);
|
||||
_texCoord01 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
// If we have an opacity mask than we need the first tex coord
|
||||
if ((matKey & OPACITY_MASK_MAP_BIT) != 0) {
|
||||
TexMapArray texMapArray = getTexMapArray();
|
||||
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,18 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
<@include graphics/Material.slh@>
|
||||
<@include graphics/MaterialTextures.slh@>
|
||||
<@include render-utils/ShaderConstants.h@>
|
||||
|
||||
<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
layout(location=RENDER_UTILS_ATTR_POSITION_WS) in vec4 _positionWS;
|
||||
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
|
||||
#define _texCoord0 _texCoord01.xy
|
||||
|
||||
layout(location=0) out vec4 _fragColor;
|
||||
|
||||
|
@ -24,6 +29,14 @@ void main(void) {
|
|||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFadeClip(fadeParams, _positionWS.xyz);
|
||||
|
||||
Material mat = getMaterial();
|
||||
BITFIELD matKey = getMaterialKey(mat);
|
||||
<$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$>
|
||||
|
||||
float opacity = 1.0;
|
||||
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
|
||||
<$discardTransparent(opacity)$>;
|
||||
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ public:
|
|||
|
||||
template <class... A>
|
||||
static std::shared_ptr<Model> create(const std::string& name, const Varying& input, A&&... args) {
|
||||
assert(input.canCast<I>());
|
||||
return std::make_shared<Model>(name, input, std::make_shared<C>(), std::forward<A>(args)...);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue