mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-16 22:30:42 +02:00
Merge pull request #6859 from zzmp/flag/shadows
Add shadows behind a render-menu flag
This commit is contained in:
commit
338342cdec
19 changed files with 130 additions and 79 deletions
|
@ -99,6 +99,7 @@
|
|||
#include <plugins/PluginContainer.h>
|
||||
#include <plugins/PluginManager.h>
|
||||
#include <RenderableWebEntityItem.h>
|
||||
#include <RenderShadowTask.h>
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <ResourceCache.h>
|
||||
#include <RenderScriptingInterface.h>
|
||||
|
@ -673,7 +674,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
initializeGL();
|
||||
|
||||
// Start rendering
|
||||
_renderEngine->addTask(make_shared<RenderDeferredTask>(LODManager::shouldRender));
|
||||
render::CullFunctor cullFunctor = LODManager::shouldRender;
|
||||
_renderEngine->addTask(make_shared<RenderShadowTask>(cullFunctor));
|
||||
_renderEngine->addTask(make_shared<RenderDeferredTask>(cullFunctor));
|
||||
_renderEngine->registerScene(_main3DScene);
|
||||
|
||||
_offscreenContext->makeCurrent();
|
||||
|
@ -3760,9 +3763,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
renderContext.setArgs(renderArgs);
|
||||
|
||||
bool occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion);
|
||||
bool shadowStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugShadows);
|
||||
bool antialiasingStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing);
|
||||
bool showOwnedStatus = Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned);
|
||||
renderContext.setOptions(occlusionStatus, antialiasingStatus, showOwnedStatus);
|
||||
renderContext.setOptions(occlusionStatus, antialiasingStatus, showOwnedStatus, shadowStatus);
|
||||
|
||||
_renderEngine->setRenderContext(renderContext);
|
||||
|
||||
|
|
|
@ -325,6 +325,7 @@ Menu::Menu() {
|
|||
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugAmbientOcclusion);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugShadows);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Antialiasing);
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, 0, true);
|
||||
|
||||
|
|
|
@ -186,6 +186,7 @@ namespace MenuOption {
|
|||
const QString CopyPath = "Copy Path to Clipboard";
|
||||
const QString CoupleEyelids = "Couple Eyelids";
|
||||
const QString CrashInterface = "Crash Interface";
|
||||
const QString DebugShadows = "Shadows";
|
||||
const QString DebugAmbientOcclusion = "Ambient Occlusion";
|
||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||
const QString DeleteBookmark = "Delete Bookmark...";
|
||||
|
|
|
@ -63,10 +63,6 @@ Framebuffer* Framebuffer::createShadowmap(uint16 width) {
|
|||
depthTexture->setSampler(Sampler(samplerDesc));
|
||||
framebuffer->setDepthStencilBuffer(depthTexture, depthFormat);
|
||||
|
||||
// Use a render buffer to allow use of the DebugDeferredBuffer Job
|
||||
gpu::TexturePointer colorbuffer{gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, width)};
|
||||
framebuffer->setRenderBuffer(0, colorbuffer);
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,12 +70,16 @@ static const std::string DEFAULT_LIGHTING_SHADER {
|
|||
" return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
|
||||
" }"
|
||||
};
|
||||
|
||||
static const std::string DEFAULT_SHADOW_SHADER{
|
||||
"uniform sampler2D shadowMapColor;"
|
||||
// The actual shadowMap is a sampler2DShadow, so we cannot normally sample it
|
||||
static const std::string DEFAULT_SHADOW_SHADER {
|
||||
"uniform sampler2DShadow shadowMap;"
|
||||
"vec4 getFragmentColor() {"
|
||||
" return vec4(texture(shadowMapColor, uv).xyz, 1.0);"
|
||||
" for (int i = 255; i >= 0; --i) {"
|
||||
" float depth = i / 255.0;"
|
||||
" if (texture(shadowMap, vec3(uv, depth)) > 0.5) {"
|
||||
" return vec4(vec3(depth), 1.0);"
|
||||
" }"
|
||||
" }"
|
||||
" return vec4(vec3(0.0), 1.0);"
|
||||
" }"
|
||||
};
|
||||
|
||||
|
@ -194,7 +198,7 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::st
|
|||
slotBindings.insert(gpu::Shader::Binding("specularMap", Specular));
|
||||
slotBindings.insert(gpu::Shader::Binding("depthMap", Depth));
|
||||
slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting));
|
||||
slotBindings.insert(gpu::Shader::Binding("shadowMapColor", Shadow));
|
||||
slotBindings.insert(gpu::Shader::Binding("shadowMap", Shadow));
|
||||
slotBindings.insert(gpu::Shader::Binding("pyramidMap", Pyramid));
|
||||
slotBindings.insert(gpu::Shader::Binding("occlusionMap", AmbientOcclusion));
|
||||
slotBindings.insert(gpu::Shader::Binding("occlusionBlurredMap", AmbientOcclusionBlurred));
|
||||
|
@ -253,7 +257,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
|
|||
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
|
||||
batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture());
|
||||
batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture());
|
||||
batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getRenderBuffer(0));
|
||||
batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getDepthStencilBuffer());
|
||||
batch.setResourceTexture(Pyramid, framebufferCache->getDepthPyramidTexture());
|
||||
batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture());
|
||||
batch.setResourceTexture(AmbientOcclusionBlurred, framebufferCache->getOcclusionBlurredTexture());
|
||||
|
|
|
@ -64,14 +64,21 @@ void DeferredLightingEffect::init() {
|
|||
_directionalAmbientSphereLightLocations = std::make_shared<LightLocations>();
|
||||
_directionalSkyboxLightLocations = std::make_shared<LightLocations>();
|
||||
|
||||
_directionalLightShadowLocations = std::make_shared<LightLocations>();
|
||||
_directionalAmbientSphereLightShadowLocations = std::make_shared<LightLocations>();
|
||||
_directionalSkyboxLightShadowLocations = std::make_shared<LightLocations>();
|
||||
|
||||
_pointLightLocations = std::make_shared<LightLocations>();
|
||||
_spotLightLocations = std::make_shared<LightLocations>();
|
||||
|
||||
// TODO: To use shadowmaps, replace directional_*_light_frag with directional_*_light_shadow_frag shaders.
|
||||
loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations);
|
||||
|
||||
loadLightProgram(deferred_light_vert, directional_light_shadow_frag, false, _directionalLightShadow, _directionalLightShadowLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_ambient_light_shadow_frag, false, _directionalAmbientSphereLightShadow, _directionalAmbientSphereLightShadowLocations);
|
||||
loadLightProgram(deferred_light_vert, directional_skybox_light_shadow_frag, false, _directionalSkyboxLightShadow, _directionalSkyboxLightShadowLocations);
|
||||
|
||||
loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations);
|
||||
loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations);
|
||||
|
||||
|
@ -306,18 +313,27 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
|
|||
{
|
||||
bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap());
|
||||
|
||||
auto& program = _directionalLight;
|
||||
LightLocationsPtr locations = _directionalLightLocations;
|
||||
auto& program = _shadowMapStatus ? _directionalLightShadow : _directionalLight;
|
||||
LightLocationsPtr locations = _shadowMapStatus ? _directionalLightShadowLocations : _directionalLightLocations;
|
||||
|
||||
// TODO: At some point bring back the shadows...
|
||||
// Setup the global directional pass pipeline
|
||||
{
|
||||
if (useSkyboxCubemap) {
|
||||
program = _directionalSkyboxLight;
|
||||
locations = _directionalSkyboxLightLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = _directionalAmbientSphereLight;
|
||||
locations = _directionalAmbientSphereLightLocations;
|
||||
if (_shadowMapStatus) {
|
||||
if (useSkyboxCubemap) {
|
||||
program = _directionalSkyboxLightShadow;
|
||||
locations = _directionalSkyboxLightShadowLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = _directionalAmbientSphereLightShadow;
|
||||
locations = _directionalAmbientSphereLightShadowLocations;
|
||||
}
|
||||
} else {
|
||||
if (useSkyboxCubemap) {
|
||||
program = _directionalSkyboxLight;
|
||||
locations = _directionalSkyboxLightLocations;
|
||||
} else if (_ambientLightMode > -1) {
|
||||
program = _directionalAmbientSphereLight;
|
||||
locations = _directionalAmbientSphereLightLocations;
|
||||
}
|
||||
}
|
||||
|
||||
if (locations->shadowTransformBuffer >= 0) {
|
||||
|
|
|
@ -54,27 +54,37 @@ public:
|
|||
void setGlobalSkybox(const model::SkyboxPointer& skybox);
|
||||
|
||||
const LightStage& getLightStage() { return _lightStage; }
|
||||
void setShadowMapStatus(bool enable) { _shadowMapStatus = enable; };
|
||||
|
||||
private:
|
||||
LightStage _lightStage;
|
||||
bool _shadowMapStatus{ false };
|
||||
|
||||
DeferredLightingEffect() = default;
|
||||
|
||||
model::MeshPointer _spotLightMesh;
|
||||
model::MeshPointer getSpotLightMesh();
|
||||
|
||||
|
||||
gpu::PipelinePointer _directionalSkyboxLight;
|
||||
LightLocationsPtr _directionalSkyboxLightLocations;
|
||||
|
||||
gpu::PipelinePointer _directionalAmbientSphereLight;
|
||||
LightLocationsPtr _directionalAmbientSphereLightLocations;
|
||||
|
||||
gpu::PipelinePointer _directionalLight;
|
||||
LightLocationsPtr _directionalLightLocations;
|
||||
|
||||
gpu::PipelinePointer _directionalSkyboxLightShadow;
|
||||
gpu::PipelinePointer _directionalAmbientSphereLightShadow;
|
||||
gpu::PipelinePointer _directionalLightShadow;
|
||||
|
||||
gpu::PipelinePointer _pointLight;
|
||||
LightLocationsPtr _pointLightLocations;
|
||||
gpu::PipelinePointer _spotLight;
|
||||
|
||||
LightLocationsPtr _directionalSkyboxLightLocations;
|
||||
LightLocationsPtr _directionalAmbientSphereLightLocations;
|
||||
LightLocationsPtr _directionalLightLocations;
|
||||
|
||||
LightLocationsPtr _directionalSkyboxLightShadowLocations;
|
||||
LightLocationsPtr _directionalAmbientSphereLightShadowLocations;
|
||||
LightLocationsPtr _directionalLightShadowLocations;
|
||||
|
||||
LightLocationsPtr _pointLightLocations;
|
||||
LightLocationsPtr _spotLightLocations;
|
||||
|
||||
using Lights = std::vector<model::LightPointer>;
|
||||
|
|
|
@ -27,7 +27,9 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near
|
|||
const auto& direction = glm::normalize(_light->getDirection());
|
||||
glm::quat orientation;
|
||||
if (direction == IDENTITY_UP) {
|
||||
orientation = glm::quat(glm::mat3(IDENTITY_RIGHT, IDENTITY_UP, IDENTITY_FRONT));
|
||||
orientation = glm::quat(glm::mat3(-IDENTITY_RIGHT, IDENTITY_FRONT, -IDENTITY_UP));
|
||||
} else if (direction == -IDENTITY_UP) {
|
||||
orientation = glm::quat(glm::mat3(IDENTITY_RIGHT, IDENTITY_FRONT, IDENTITY_UP));
|
||||
} else {
|
||||
auto side = glm::normalize(glm::cross(direction, IDENTITY_UP));
|
||||
auto up = glm::normalize(glm::cross(side, direction));
|
||||
|
@ -70,6 +72,9 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near
|
|||
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, -max.z, -min.z);
|
||||
_frustum->setProjection(ortho);
|
||||
|
||||
// Calculate the frustum's internal state
|
||||
_frustum->calculate();
|
||||
|
||||
// Update the buffer
|
||||
_schemaBuffer.edit<Schema>().projection = ortho;
|
||||
_schemaBuffer.edit<Schema>().viewInverse = viewInverse.getMatrix();
|
||||
|
|
|
@ -215,7 +215,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat
|
|||
}
|
||||
}
|
||||
|
||||
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const {
|
||||
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool canCauterize) const {
|
||||
batch.setModelTransform(_drawTransform);
|
||||
}
|
||||
|
||||
|
@ -442,25 +442,25 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
|
|||
}
|
||||
}
|
||||
|
||||
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const {
|
||||
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool canCauterize) const {
|
||||
// Still relying on the raw data from the model
|
||||
const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
|
||||
|
||||
Transform transform;
|
||||
if (state.clusterBuffer) {
|
||||
if (_model->_cauterizeBones) {
|
||||
if (canCauterize && _model->getCauterizeBones()) {
|
||||
batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer);
|
||||
} else {
|
||||
batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.clusterBuffer);
|
||||
}
|
||||
} else {
|
||||
if (_model->_cauterizeBones) {
|
||||
if (canCauterize && _model->getCauterizeBones()) {
|
||||
transform = Transform(state.cauterizedClusterMatrices[0]);
|
||||
} else {
|
||||
transform = Transform(state.clusterMatrices[0]);
|
||||
}
|
||||
}
|
||||
// transform.preTranslate(_modelPosition);
|
||||
|
||||
transform.preTranslate(_transform.getTranslation());
|
||||
batch.setModelTransform(transform);
|
||||
}
|
||||
|
@ -507,8 +507,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
|
|||
assert(locations);
|
||||
|
||||
// Bind the model transform and the skinCLusterMatrices if needed
|
||||
bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE;
|
||||
_model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation());
|
||||
bindTransform(batch, locations);
|
||||
bindTransform(batch, locations, canCauterize);
|
||||
|
||||
//Bind the index buffer and vertex buffer and Blend shapes if needed
|
||||
bindMesh(batch);
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
void drawCall(gpu::Batch& batch) const;
|
||||
virtual void bindMesh(gpu::Batch& batch) const;
|
||||
virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const;
|
||||
virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const;
|
||||
virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool canCauterize = true) const;
|
||||
|
||||
// Payload resource cached values
|
||||
model::MeshPointer _drawMesh;
|
||||
|
@ -88,15 +88,17 @@ public:
|
|||
|
||||
// ModelMeshPartPayload functions to perform render
|
||||
void bindMesh(gpu::Batch& batch) const override;
|
||||
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const override;
|
||||
|
||||
void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool canCauterize) const override;
|
||||
|
||||
void initCache();
|
||||
|
||||
Model* _model;
|
||||
|
||||
int _meshIndex;
|
||||
int _shapeID;
|
||||
bool _isSkinned = false;
|
||||
bool _isBlendShaped = false;
|
||||
|
||||
bool _isSkinned{ false };
|
||||
bool _isBlendShaped{ false };
|
||||
};
|
||||
|
||||
#endif // hifi_MeshPartPayload_h
|
||||
|
|
|
@ -191,6 +191,9 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
setToneMappingToneCurve(renderContext->getTone().toneCurve);
|
||||
// TODO: Allow runtime manipulation of culling ShouldRenderFunctor
|
||||
|
||||
// TODO: For now, lighting is controlled through a singleton, so it is distinct
|
||||
DependencyManager::get<DeferredLightingEffect>()->setShadowMapStatus(renderContext->getShadowMapStatus());
|
||||
|
||||
renderContext->getArgs()->_context->syncCache();
|
||||
|
||||
for (auto job : _jobs) {
|
||||
|
|
|
@ -124,15 +124,12 @@ public:
|
|||
void setDrawHitEffect(bool draw) { enableJob(_drawHitEffectJobIndex, draw); }
|
||||
bool doDrawHitEffect() const { return getEnableJob(_drawHitEffectJobIndex); }
|
||||
|
||||
|
||||
void setOcclusionStatus(bool draw) { enableJob(_occlusionJobIndex, draw); }
|
||||
bool doOcclusionStatus() const { return getEnableJob(_occlusionJobIndex); }
|
||||
|
||||
|
||||
void setAntialiasingStatus(bool draw) { enableJob(_antialiasingJobIndex, draw); }
|
||||
bool doAntialiasingStatus() const { return getEnableJob(_antialiasingJobIndex); }
|
||||
|
||||
|
||||
void setToneMappingExposure(float exposure);
|
||||
float getToneMappingExposure() const;
|
||||
|
||||
|
|
|
@ -123,6 +123,11 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
|
|||
assert(sceneContext);
|
||||
RenderArgs* args = renderContext->getArgs();
|
||||
|
||||
// This feature is in a debugging stage - it must be turned on explicitly
|
||||
if (!renderContext->getShadowMapStatus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// sanity checks
|
||||
if (!sceneContext->_scene || !args) {
|
||||
return;
|
||||
|
@ -136,21 +141,26 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
|
|||
return;
|
||||
}
|
||||
|
||||
// Cache old render args
|
||||
ViewFrustum* viewFrustum = args->_viewFrustum;
|
||||
RenderArgs::RenderMode mode = args->_renderMode;
|
||||
|
||||
auto nearClip = viewFrustum->getNearClip();
|
||||
const int SHADOW_NEAR_DEPTH = -2;
|
||||
const int SHADOW_FAR_DEPTH = 20;
|
||||
globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip + SHADOW_NEAR_DEPTH, nearClip + SHADOW_FAR_DEPTH);
|
||||
|
||||
// Set the keylight frustum
|
||||
// Set the keylight render args
|
||||
args->_viewFrustum = globalLight->shadow.getFrustum().get();
|
||||
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
|
||||
|
||||
// TODO: Allow runtime manipulation of culling ShouldRenderFunctor
|
||||
|
||||
for (auto job : _jobs) {
|
||||
job.run(sceneContext, renderContext);
|
||||
}
|
||||
|
||||
// Reset the view frustum
|
||||
// Reset the render args
|
||||
args->_viewFrustum = viewFrustum;
|
||||
args->_renderMode = mode;
|
||||
};
|
||||
|
|
|
@ -60,44 +60,39 @@ float fetchShadow(vec3 shadowTexcoord) {
|
|||
return texture(shadowMap, shadowTexcoord);
|
||||
}
|
||||
|
||||
vec2 samples[8] = vec2[8](
|
||||
vec2(-2.0, -2.0),
|
||||
vec2(2.0, -2.0),
|
||||
vec2(2.0, 2.0),
|
||||
vec2(-2.0, 2.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(-1.0, 0.0),
|
||||
vec2(0.0, -1.0)
|
||||
vec2 PCFkernel[4] = vec2[4](
|
||||
vec2(-1.5, 0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-1.5, -1.5),
|
||||
vec2(0.5, -1.5)
|
||||
);
|
||||
|
||||
float evalShadowAttenuationSampling(vec4 shadowTexcoord) {
|
||||
float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) {
|
||||
float pcfRadius = 3.0;
|
||||
float shadowScale = getShadowScale();
|
||||
|
||||
float shadowAttenuation = (0.25 * (
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[0], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[1], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[2], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[3], 0.0))
|
||||
));
|
||||
// Offset for efficient PCF, see http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html
|
||||
vec2 offset = pcfRadius * step(fract(position.xy), vec2(0.5, 0.5));
|
||||
|
||||
// Check for early bailing
|
||||
if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) {
|
||||
shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * (
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[4], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[5], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[6], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[7], 0.0))
|
||||
));
|
||||
}
|
||||
float shadowAttenuation = (0.25 * (
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[0], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[1], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) +
|
||||
fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[3], 0.0))
|
||||
));
|
||||
|
||||
return shadowAttenuation;
|
||||
}
|
||||
|
||||
float evalShadowAttenuation(vec4 position) {
|
||||
vec4 shadowTexcoord = evalShadowTexcoord(position);
|
||||
if (shadowTexcoord.x < 0.0 || shadowTexcoord.x > 1.0 ||
|
||||
shadowTexcoord.y < 0.0 || shadowTexcoord.y > 1.0) {
|
||||
// If a point is not in the map, do not attenuate
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return evalShadowAttenuationSampling(shadowTexcoord);
|
||||
return evalShadowAttenuationPCF(position, shadowTexcoord);
|
||||
}
|
||||
|
||||
<@endif@>
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
layout(location = 0) out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
// stencil in solid color for debugging
|
||||
_fragColor = vec4(0.0, 0.0, 1.0, 1.0);
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
layout(location = 0) out vec4 _fragColor;
|
||||
|
||||
void main(void) {
|
||||
// stencil in solid color for debugging
|
||||
_fragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
// pass-through to set z-buffer
|
||||
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,10 @@ RenderContext::RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao,
|
|||
_drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect },
|
||||
_items{ items }, _tone{ tone }, _ambientOcclusion{ ao } {}
|
||||
|
||||
void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned) {
|
||||
void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) {
|
||||
_occlusionStatus = occlusion;
|
||||
_fxaaStatus = fxaa;
|
||||
_shadowMapStatus = shadowMap;
|
||||
|
||||
if (showOwned) {
|
||||
_drawStatus |= render::showNetworkStatusFlag;
|
||||
|
|
|
@ -100,7 +100,8 @@ public:
|
|||
bool getDrawHitEffect() { return _drawHitEffect; }
|
||||
bool getOcclusionStatus() { return _occlusionStatus; }
|
||||
bool getFxaaStatus() { return _fxaaStatus; }
|
||||
void setOptions(bool occlusion, bool fxaa, bool showOwned);
|
||||
bool getShadowMapStatus() { return _shadowMapStatus; }
|
||||
void setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap);
|
||||
|
||||
// Debugging
|
||||
int _deferredDebugMode;
|
||||
|
@ -114,6 +115,7 @@ protected:
|
|||
bool _drawHitEffect;
|
||||
bool _occlusionStatus { false };
|
||||
bool _fxaaStatus { false };
|
||||
bool _shadowMapStatus { false };
|
||||
|
||||
ItemsConfig _items;
|
||||
Tone _tone;
|
||||
|
|
|
@ -236,6 +236,9 @@ void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const Rend
|
|||
}
|
||||
|
||||
void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes) {
|
||||
outShapes.clear();
|
||||
outShapes.reserve(inShapes.size());
|
||||
|
||||
for (auto& pipeline : inShapes) {
|
||||
auto& inItems = pipeline.second;
|
||||
auto outItems = outShapes.find(pipeline.first);
|
||||
|
|
Loading…
Reference in a new issue