Fade effect working again for basic enter domain but with various Fade jobs

This commit is contained in:
Olivier Prat 2017-06-29 08:54:23 +02:00
parent b76a8a6f9b
commit 8a12d0c106
40 changed files with 900 additions and 187 deletions

View file

@ -740,10 +740,11 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS));
slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("xMap"), 0));
slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("yMap"), 1));
slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("zMap"), 2));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), 3)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK));
auto state = std::make_shared<gpu::State>(); auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK); state->setCullMode(gpu::State::CULL_BACK);
@ -823,9 +824,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
} }
// Apply fade effect // Apply fade effect
auto fadeEffect = DependencyManager::get<FadeEffect>(); if (args->_enableFade) {
if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) { FadeRenderJob::bindPerBatch(batch, render::ShapePipeline::Slot::MAP::FADE_MASK, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS);
fadeEffect->bindPerBatch(batch, 3); FadeRenderJob::bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime);
} }
int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize"); int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
@ -882,6 +883,13 @@ namespace render {
payload->_owner->getRenderableInterface()->render(args); payload->_owner->getRenderableInterface()->render(args);
} }
} }
template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload) {
if (payload && payload->_owner) {
return payload->_owner->mustFade();
}
return false;
}
} }

View file

@ -38,6 +38,7 @@ namespace render {
template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload); template <> const ItemKey payloadGetKey(const PolyVoxPayload::Pointer& payload);
template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload); template <> const Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload);
template <> void payloadRender(const PolyVoxPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const PolyVoxPayload::Pointer& payload, RenderArgs* args);
template <> bool payloadMustFade(const PolyVoxPayload::Pointer& payload);
} }
@ -205,4 +206,5 @@ private:
bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, bool inUserBounds(const PolyVox::SimpleVolume<uint8_t>* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle,
int x, int y, int z); int x, int y, int z);
#endif // hifi_RenderablePolyVoxEntityItem_h #endif // hifi_RenderablePolyVoxEntityItem_h

View file

@ -126,7 +126,6 @@ void RenderableShapeEntityItem::render(RenderArgs* args) {
color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; color.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
// FIXME, support instanced multi-shape rendering using multidraw indirect // FIXME, support instanced multi-shape rendering using multidraw indirect
auto geometryCache = DependencyManager::get<GeometryCache>(); auto geometryCache = DependencyManager::get<GeometryCache>();
auto fadeEffect = DependencyManager::get<FadeEffect>();
auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
assert(pipeline != nullptr); assert(pipeline != nullptr);

View file

@ -30,7 +30,8 @@ uniform vec3 voxelVolumeSize;
<$declareFadeFragment()$> <$declareFadeFragment()$>
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 emissive;
applyFade(_worldFadePosition.xyz, emissive);
vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz));
worldNormal = normalize(worldNormal); worldNormal = normalize(worldNormal);
@ -54,7 +55,7 @@ void main(void) {
vec3(diffuse), vec3(diffuse),
DEFAULT_ROUGHNESS, DEFAULT_ROUGHNESS,
DEFAULT_METALLIC, DEFAULT_METALLIC,
DEFAULT_EMISSIVE, DEFAULT_EMISSIVE+emissive,
DEFAULT_OCCLUSION, DEFAULT_OCCLUSION,
DEFAULT_SCATTERING); DEFAULT_SCATTERING);
} }

View file

@ -459,6 +459,7 @@ public:
bool isFading() const { return _isFading; } bool isFading() const { return _isFading; }
float getFadingRatio() const { return (isFading() ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); } float getFadingRatio() const { return (isFading() ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f); }
bool mustFade() const { return _isFading; }
virtual void emitScriptEvent(const QVariant& message) {} virtual void emitScriptEvent(const QVariant& message) {}

View file

@ -18,9 +18,26 @@
<@func declareFadeFragment()@> <@func declareFadeFragment()@>
uniform vec3 fadeOffset; struct FadeParameters
uniform float fadePercent; {
uniform float fadeInvScale; vec4 _baseInvSizeAndLevel;
vec4 _noiseInvSizeAndLevel;
vec3 _innerEdgeColor;
vec3 _outerEdgeColor;
vec2 _edgeWidthInvWidth;
int _invertBase;
float _padding;
};
#define EVENT_CATEGORY_COUNT 5
uniform fadeParametersBuffer {
FadeParameters fadeParameters[EVENT_CATEGORY_COUNT];
};
uniform int fadeCategory;
uniform vec3 fadeNoiseOffset;
uniform vec3 fadeBaseOffset;
uniform float fadeThreshold;
uniform sampler2D fadeMaskMap; uniform sampler2D fadeMaskMap;
vec2 hash2D(vec3 position) { vec2 hash2D(vec3 position) {
@ -31,9 +48,9 @@ float noise3D(vec3 position) {
return textureLod(fadeMaskMap, hash2D(position), 0).r; return textureLod(fadeMaskMap, hash2D(position), 0).r;
} }
float evalFadeMask(vec3 position) { float evalFadeNoiseGradient(vec3 position) {
// Do tri-linear interpolation // Do tri-linear interpolation
vec3 noisePosition = position * fadeInvScale + fadeOffset; vec3 noisePosition = position * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.xyz + fadeNoiseOffset;
vec3 noisePositionFloored = floor(noisePosition); vec3 noisePositionFloored = floor(noisePosition);
vec3 noisePositionFraction = fract(noisePosition); vec3 noisePositionFraction = fract(noisePosition);
float noiseLowXLowYLowZ = noise3D(noisePositionFloored); float noiseLowXLowYLowZ = noise3D(noisePositionFloored);
@ -49,14 +66,59 @@ float evalFadeMask(vec3 position) {
vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z); vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);
vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x); vec2 maskY = mix(maskXY.xy, maskXY.zw, noisePositionFraction.x);
return mix(maskY.x, maskY.y, noisePositionFraction.y); return mix(maskY.x, maskY.y, noisePositionFraction.y) * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w;
} }
void applyFade(vec3 position) { float evalFadeBaseGradient(vec3 position) {
if (evalFadeMask(position) > fadePercent) { float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz);
if (fadeParameters[fadeCategory]._invertBase!=0) {
gradient = 1.0 - gradient;
}
gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w;
return gradient;
}
float evalFadeGradient(vec3 position) {
float baseGradient = evalFadeBaseGradient(position);
float noiseGradient = evalFadeNoiseGradient(position);
float gradient = (noiseGradient-0.5*fadeParameters[fadeCategory]._baseInvSizeAndLevel.w);
// This is to be sure the noise is zero at the start of the gradient
gradient *= (1-baseGradient*baseGradient);
gradient += baseGradient;
return gradient;
}
float evalFadeAlpha(vec3 position) {
/* float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x;
float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold);
return evalFadeGradient(position)-cutoff;*/
return evalFadeNoiseGradient(position)-fadeThreshold;
}
void applyFadeClip(vec3 position) {
if (evalFadeAlpha(position) < 0) {
discard; discard;
} }
} }
void applyFade(vec3 position, out vec3 emissive) {
float alpha = evalFadeAlpha(position);
if (alpha < 0) {
discard;
}
/*
float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y;
float edgeAlpha = 1.0-clamp(edgeMask, 0, 1);
edgeMask = step(edgeMask, 1.f);
edgeAlpha *= edgeAlpha; // Square to have a nice ease out
emissive = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha);
emissive *= edgeMask;
*/
emissive = vec3(0,0,0);
}
<@endfunc@> <@endfunc@>
<@endif@> <@endif@>

View file

@ -4,73 +4,223 @@
#include <PathUtils.h> #include <PathUtils.h>
#include <NumericalConstants.h> #include <NumericalConstants.h>
#include <Interpolate.h> #include <Interpolate.h>
#include <render/ShapePipeline.h> #include <gpu/Context.h>
FadeEffect::FadeEffect() : void FadeSwitchJob::configure(const Config& config) {
_invScale{ 1.f }, _isEditEnabled = config.editFade;
_duration{ 3.f }, }
_debugFadePercent{ 0.f },
_isDebugEnabled{ false } void FadeSwitchJob::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) {
auto& normalOutputs = output.edit0();
auto& fadeOutputs = output.edit1();
// Only shapes are affected by fade at this time.
normalOutputs[RenderFetchCullSortTask::LIGHT] = input[RenderFetchCullSortTask::LIGHT];
normalOutputs[RenderFetchCullSortTask::META] = input[RenderFetchCullSortTask::META];
normalOutputs[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
normalOutputs[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE] = input[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
normalOutputs[RenderFetchCullSortTask::BACKGROUND] = input[RenderFetchCullSortTask::BACKGROUND];
normalOutputs[RenderFetchCullSortTask::SPATIAL_SELECTION] = input[RenderFetchCullSortTask::SPATIAL_SELECTION];
// Now, distribute items that need to be faded accross both outputs
distribute(renderContext, input[RenderFetchCullSortTask::OPAQUE_SHAPE], normalOutputs[RenderFetchCullSortTask::OPAQUE_SHAPE], fadeOutputs[OPAQUE_SHAPE]);
distribute(renderContext, input[RenderFetchCullSortTask::TRANSPARENT_SHAPE], normalOutputs[RenderFetchCullSortTask::TRANSPARENT_SHAPE], fadeOutputs[TRANSPARENT_SHAPE]);
}
void FadeSwitchJob::distribute(const render::RenderContextPointer& renderContext, const render::Varying& input,
render::Varying& normalOutput, render::Varying& fadeOutput) const {
auto& scene = renderContext->_scene;
assert(_parameters);
const double fadeDuration = double(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]) * USECS_PER_SECOND;
const auto& inputItems = input.get<render::ItemBounds>();
// Clear previous values
normalOutput.template edit<render::ItemBounds>().clear();
fadeOutput.template edit<render::ItemBounds>().clear();
for (const auto& itemBound : inputItems) {
auto& item = scene->getItem(itemBound.id);
if (!item.mustFade()) {
// No need to fade
normalOutput.template edit<render::ItemBounds>().emplace_back(itemBound);
}
else {
fadeOutput.template edit<render::ItemBounds>().emplace_back(itemBound);
}
}
/* if (!_isEditEnabled) {
}*/
}
FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) :
_parameters{ commonParams }
{ {
auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png"; auto texturePath = PathUtils::resourcesPath() + "images/fadeMask.png";
_fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE); _fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
} }
render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder builder) const { void FadeConfigureJob::configure(const Config& config) {
if (_isDebugEnabled) { assert(_parameters);
// Force fade for everyone for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) {
builder.withFade(); auto& configuration = _configurations[i];
}
return builder; _parameters->_durations[i] = config.duration[i];
configuration._baseInvSizeAndLevel.x = 1.f / config.baseSize[i].x;
configuration._baseInvSizeAndLevel.y = 1.f / config.baseSize[i].y;
configuration._baseInvSizeAndLevel.z = 1.f / config.baseSize[i].z;
configuration._baseInvSizeAndLevel.w = config.baseLevel[i];
configuration._noiseInvSizeAndLevel.x = 1.f / config.noiseSize[i].x;
configuration._noiseInvSizeAndLevel.y = 1.f / config.noiseSize[i].y;
configuration._noiseInvSizeAndLevel.z = 1.f / config.noiseSize[i].z;
configuration._noiseInvSizeAndLevel.w = config.noiseLevel[i];
configuration._invertBase = config.baseInverted[i];
configuration._edgeWidthInvWidth.x = config.edgeWidth[i];
configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x;
configuration._innerEdgeColor.r = config.edgeInnerColor[i].r * config.edgeInnerColor[i].a;
configuration._innerEdgeColor.g = config.edgeInnerColor[i].g * config.edgeInnerColor[i].a;
configuration._innerEdgeColor.b = config.edgeInnerColor[i].b * config.edgeInnerColor[i].a;
configuration._outerEdgeColor.r = config.edgeOuterColor[i].r * config.edgeOuterColor[i].a;
configuration._outerEdgeColor.g = config.edgeOuterColor[i].g * config.edgeOuterColor[i].a;
configuration._outerEdgeColor.b = config.edgeOuterColor[i].b * config.edgeOuterColor[i].a;
}
_isBufferDirty = true;
} }
void FadeEffect::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation) const { void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, Output& output) {
batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap); if (_isBufferDirty) {
auto& configurations = output.edit1().edit();
std::copy(_configurations, _configurations + FadeJobConfig::EVENT_CATEGORY_COUNT, configurations.parameters);
_isBufferDirty = false;
}
output.edit0() = _fadeMaskMap;
} }
void FadeEffect::bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const { const FadeRenderJob* FadeRenderJob::_currentInstance{ nullptr };
auto program = pipeline->getProgram(); gpu::TexturePointer FadeRenderJob::_currentFadeMaskMap;
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap"); const gpu::BufferView* FadeRenderJob::_currentFadeBuffer{ nullptr };
bindPerBatch(batch, maskMapLocation);
}
float FadeEffect::computeFadePercent(quint64 startTime) const { float FadeRenderJob::computeFadePercent(quint64 startTime) {
assert(_currentInstance);
float fadeAlpha = 1.0f; float fadeAlpha = 1.0f;
const double INV_FADE_PERIOD = 1.0 / (double)(_duration * USECS_PER_SECOND); const double INV_FADE_PERIOD = 1.0 / (double)(_currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] * USECS_PER_SECOND);
double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD; double fraction = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) * INV_FADE_PERIOD;
fraction = std::max(fraction, 0.0);
if (fraction < 1.0) { if (fraction < 1.0) {
fadeAlpha = Interpolate::easeInOutQuad(fraction); fadeAlpha = Interpolate::easeInOutQuad(fraction);
} }
return fadeAlpha; return fadeAlpha;
} }
bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const { void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) {
return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading); assert(renderContext->args);
assert(renderContext->args->hasViewFrustum());
const auto& inItems = inputs.get0();
if (!inItems.empty()) {
const auto& lightingModel = inputs.get1();
const auto& configuration = inputs.get2();
const auto& fadeMaskMap = configuration.get0();
const auto& fadeParamBuffer = configuration.get1();
// Very, very ugly hack to keep track of the current fade render job
RenderArgs* args = renderContext->args;
render::ShapeKey::Builder defaultKeyBuilder;
defaultKeyBuilder.withFade();
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch;
_currentInstance = this;
_currentFadeMaskMap = fadeMaskMap;
_currentFadeBuffer = &fadeParamBuffer;
// Setup camera, projection and viewport for all items
batch.setViewportTransform(args->_viewport);
batch.setStateScissorRect(args->_viewport);
glm::mat4 projMat;
Transform viewMat;
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
// Setup lighting model for all items;
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
// From the lighting model define a global shapKey ORED with individiual keys
render::ShapeKey::Builder keyBuilder = defaultKeyBuilder;
if (lightingModel->isWireframeEnabled()) {
keyBuilder.withWireframe();
}
// Prepare fade effect
bindPerBatch(batch, fadeMaskMap, render::ShapePipeline::Slot::MAP::FADE_MASK, &fadeParamBuffer, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS);
render::ShapeKey globalKey = keyBuilder.build();
args->_globalShapeKey = globalKey._flags.to_ulong();
args->_enableFade = true;
renderShapes(renderContext, _shapePlumber, inItems, -1, globalKey);
args->_enableFade = false;
args->_batch = nullptr;
args->_globalShapeKey = 0;
// Very, very ugly hack to keep track of the current fade render job
_currentInstance = nullptr;
_currentFadeMaskMap.reset();
_currentFadeBuffer = nullptr;
});
}
} }
bool FadeEffect::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const { void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) {
if (isFading || _isDebugEnabled) { assert(_currentFadeMaskMap);
auto& uniforms = pipeline->getProgram()->getUniforms(); assert(_currentFadeBuffer!=nullptr);
auto fadeScaleLocation = uniforms.findLocation("fadeInvScale"); bindPerBatch(batch, _currentFadeMaskMap, fadeMaskMapLocation, _currentFadeBuffer, fadeBufferLocation);
auto fadeOffsetLocation = uniforms.findLocation("fadeOffset"); }
auto fadePercentLocation = uniforms.findLocation("fadePercent");
if (fadeScaleLocation >= 0 || fadeOffsetLocation >= 0 || fadePercentLocation>=0) { void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) {
float percent; batch.setResourceTexture(fadeMaskMapLocation, texture);
batch.setUniformBuffer(fadeBufferLocation, *buffer);
}
// A bit ugly to have the test at every bind... void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) {
if (!_isDebugEnabled) { auto program = pipeline->getProgram();
percent = computeFadePercent(startTime); auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
} auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
else { bindPerBatch(batch, texture, maskMapLocation, buffer, bufferLocation);
percent = _debugFadePercent; }
}
batch._glUniform1f(fadeScaleLocation, _invScale);
batch._glUniform1f(fadePercentLocation, percent);
batch._glUniform3f(fadeOffsetLocation, offset.x, offset.y, offset.z);
return percent < 1.f; bool FadeRenderJob::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime) {
} return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime);
}
bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime) {
auto& uniforms = pipeline->getProgram()->getUniforms();
auto fadeNoiseOffsetLocation = uniforms.findLocation("fadeNoiseOffset");
auto fadeBaseOffsetLocation = uniforms.findLocation("fadeBaseOffset");
auto fadeThresholdLocation = uniforms.findLocation("fadeThreshold");
auto fadeCategoryLocation = uniforms.findLocation("fadeCategory");
if (fadeNoiseOffsetLocation >= 0 || fadeBaseOffsetLocation>=0 || fadeThresholdLocation >= 0 || fadeCategoryLocation>=0) {
float percent;
percent = computeFadePercent(startTime);
batch._glUniform1i(fadeCategoryLocation, FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN);
batch._glUniform1f(fadeThresholdLocation, 1.f-percent);
// This is really temporary
batch._glUniform3f(fadeNoiseOffsetLocation, offset.x, offset.y, offset.z);
// This is really temporary
batch._glUniform3f(fadeBaseOffsetLocation, offset.x, offset.y, offset.z);
return percent < 1.f;
} }
return false; return false;
} }

View file

@ -11,47 +11,304 @@
#ifndef hifi_FadeEffect_h #ifndef hifi_FadeEffect_h
#define hifi_FadeEffect_h #define hifi_FadeEffect_h
#include <DependencyManager.h>
#include <gpu/Pipeline.h> #include <gpu/Pipeline.h>
#include <render/ShapePipeline.h> #include <render/ShapePipeline.h>
#include <render/RenderFetchCullSortTask.h>
#include "LightingModel.h"
class FadeSwitchJobConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool editFade MEMBER editFade NOTIFY dirty)
// Centralizes fade effect data and functions
class FadeEffect : public Dependency {
SINGLETON_DEPENDENCY
public: public:
FadeEffect(); bool editFade{ false };
const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; } signals:
void dirty();
void setScale(float value) { assert(value > 0.f); _invScale = 1.f / value; } };
float getScale() const { return 1.f / _invScale; }
void setDuration(float seconds) { assert(seconds > 0.f); _duration = seconds; } class FadeJobConfig : public render::Job::Config {
float getDuration() const { return 1.f / _duration; } Q_OBJECT
Q_PROPERTY(int editedCategory MEMBER editedCategory WRITE setEditedCategory NOTIFY dirty)
Q_PROPERTY(float duration READ getDuration WRITE setDuration NOTIFY dirty)
Q_PROPERTY(float baseSizeX READ getBaseSizeX WRITE setBaseSizeX NOTIFY dirty)
Q_PROPERTY(float baseSizeY READ getBaseSizeY WRITE setBaseSizeY NOTIFY dirty)
Q_PROPERTY(float baseSizeZ READ getBaseSizeZ WRITE setBaseSizeZ NOTIFY dirty)
Q_PROPERTY(float baseLevel READ getBaseLevel WRITE setBaseLevel NOTIFY dirty)
Q_PROPERTY(bool baseInverted READ isBaseInverted WRITE setBaseInverted NOTIFY dirty)
Q_PROPERTY(float noiseSizeX READ getNoiseSizeX WRITE setNoiseSizeX NOTIFY dirty)
Q_PROPERTY(float noiseSizeY READ getNoiseSizeY WRITE setNoiseSizeY NOTIFY dirty)
Q_PROPERTY(float noiseSizeZ READ getNoiseSizeZ WRITE setNoiseSizeZ NOTIFY dirty)
Q_PROPERTY(float noiseLevel READ getNoiseLevel WRITE setNoiseLevel NOTIFY dirty)
Q_PROPERTY(float edgeWidth READ getEdgeWidth WRITE setEdgeWidth NOTIFY dirty)
Q_PROPERTY(float edgeInnerColorR READ getEdgeInnerColorR WRITE setEdgeInnerColorR NOTIFY dirty)
Q_PROPERTY(float edgeInnerColorG READ getEdgeInnerColorG WRITE setEdgeInnerColorG NOTIFY dirty)
Q_PROPERTY(float edgeInnerColorB READ getEdgeInnerColorB WRITE setEdgeInnerColorB NOTIFY dirty)
Q_PROPERTY(float edgeInnerIntensity READ getEdgeInnerIntensity WRITE setEdgeInnerIntensity NOTIFY dirty)
Q_PROPERTY(float edgeOuterColorR READ getEdgeOuterColorR WRITE setEdgeOuterColorR NOTIFY dirty)
Q_PROPERTY(float edgeOuterColorG READ getEdgeOuterColorG WRITE setEdgeOuterColorG NOTIFY dirty)
Q_PROPERTY(float edgeOuterColorB READ getEdgeOuterColorB WRITE setEdgeOuterColorB NOTIFY dirty)
Q_PROPERTY(float edgeOuterIntensity READ getEdgeOuterIntensity WRITE setEdgeOuterIntensity NOTIFY dirty)
void setDebugEnabled(bool isEnabled) { _isDebugEnabled = isEnabled; } public:
bool isDebugEnabled() const { return _isDebugEnabled; }
void setDebugFadePercent(float value) { assert(value >= 0.f && value <= 1.f); _debugFadePercent = value; } enum EventCategory {
float getDebugFadePercent() const { return _debugFadePercent; } ELEMENT_ENTER_LEAVE_DOMAIN = 0,
BUBBLE_ISECT_OWNER,
BUBBLE_ISECT_TRESPASSER,
USER_ENTER_LEAVE_DOMAIN,
AVATAR_CHANGE,
render::ShapeKey::Builder getKeyBuilder(render::ShapeKey::Builder builder = render::ShapeKey::Builder()) const; // Don't forget to modify Fade.slh to reflect the change in number of categories
EVENT_CATEGORY_COUNT
};
void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation = render::ShapePipeline::Slot::MAP::FADE_MASK) const; void setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min<int>(EVENT_CATEGORY_COUNT, value); }
void bindPerBatch(gpu::Batch& batch, const gpu::PipelinePointer& pipeline) const;
bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const;
bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime, bool isFading) const;
float computeFadePercent(quint64 startTime) const; void setDuration(float value) { duration[editedCategory] = value; }
float getDuration() const { return duration[editedCategory]; }
void setBaseSizeX(float value) { baseSize[editedCategory].x = value; }
float getBaseSizeX() const { return baseSize[editedCategory].x; }
void setBaseSizeY(float value) { baseSize[editedCategory].y = value; }
float getBaseSizeY() const { return baseSize[editedCategory].y; }
void setBaseSizeZ(float value) { baseSize[editedCategory].z = value; }
float getBaseSizeZ() const { return baseSize[editedCategory].z; }
void setBaseLevel(float value) { baseLevel[editedCategory] = value; }
float getBaseLevel() const { return baseLevel[editedCategory]; }
void setBaseInverted(bool value) { baseInverted[editedCategory] = value; }
bool isBaseInverted() const { return baseInverted[editedCategory]; }
void setNoiseSizeX(float value) { noiseSize[editedCategory].x = value; }
float getNoiseSizeX() const { return noiseSize[editedCategory].x; }
void setNoiseSizeY(float value) { noiseSize[editedCategory].y = value; }
float getNoiseSizeY() const { return noiseSize[editedCategory].y; }
void setNoiseSizeZ(float value) { noiseSize[editedCategory].z = value; }
float getNoiseSizeZ() const { return noiseSize[editedCategory].z; }
void setNoiseLevel(float value) { noiseLevel[editedCategory] = value; }
float getNoiseLevel() const { return noiseLevel[editedCategory]; }
void setEdgeWidth(float value) { edgeWidth[editedCategory] = value; }
float getEdgeWidth() const { return edgeWidth[editedCategory]; }
void setEdgeInnerColorR(float value) { edgeInnerColor[editedCategory].r = value; }
float getEdgeInnerColorR() const { return edgeInnerColor[editedCategory].r; }
void setEdgeInnerColorG(float value) { edgeInnerColor[editedCategory].g = value; }
float getEdgeInnerColorG() const { return edgeInnerColor[editedCategory].g; }
void setEdgeInnerColorB(float value) { edgeInnerColor[editedCategory].b = value; }
float getEdgeInnerColorB() const { return edgeInnerColor[editedCategory].b; }
void setEdgeInnerIntensity(float value) { edgeInnerColor[editedCategory].a = value; }
float getEdgeInnerIntensity() const { return edgeInnerColor[editedCategory].a; }
void setEdgeOuterColorR(float value) { edgeOuterColor[editedCategory].r = value; }
float getEdgeOuterColorR() const { return edgeOuterColor[editedCategory].r; }
void setEdgeOuterColorG(float value) { edgeOuterColor[editedCategory].g = value; }
float getEdgeOuterColorG() const { return edgeOuterColor[editedCategory].g; }
void setEdgeOuterColorB(float value) { edgeOuterColor[editedCategory].b = value; }
float getEdgeOuterColorB() const { return edgeOuterColor[editedCategory].b; }
void setEdgeOuterIntensity(float value) { edgeOuterColor[editedCategory].a = value; }
float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; }
int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN };
glm::vec3 baseSize[EVENT_CATEGORY_COUNT]{
{ 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER
{ 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER
{ 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE
};
float baseLevel[EVENT_CATEGORY_COUNT]{
1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN
1.0f, // BUBBLE_ISECT_OWNER
1.0f, // BUBBLE_ISECT_TRESPASSER
1.0f, // USER_ENTER_LEAVE_DOMAIN
1.0f, // AVATAR_CHANGE
};
bool baseInverted[EVENT_CATEGORY_COUNT]{
false, // ELEMENT_ENTER_LEAVE_DOMAIN
false, // BUBBLE_ISECT_OWNER
false, // BUBBLE_ISECT_TRESPASSER
false, // USER_ENTER_LEAVE_DOMAIN
false, // AVATAR_CHANGE
};
glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{
{ 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER
{ 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER
{ 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE
};
float noiseLevel[EVENT_CATEGORY_COUNT]{
1.0f, // ELEMENT_ENTER_LEAVE_DOMAIN
1.0f, // BUBBLE_ISECT_OWNER
1.0f, // BUBBLE_ISECT_TRESPASSER
1.0f, // USER_ENTER_LEAVE_DOMAIN
1.0f, // AVATAR_CHANGE
};
float duration[EVENT_CATEGORY_COUNT]{
5.0f, // ELEMENT_ENTER_LEAVE_DOMAIN
0.0f, // BUBBLE_ISECT_OWNER
0.0f, // BUBBLE_ISECT_TRESPASSER
3.0f, // USER_ENTER_LEAVE_DOMAIN
3.0f, // AVATAR_CHANGE
};
float edgeWidth[EVENT_CATEGORY_COUNT]{
0.1f, // ELEMENT_ENTER_LEAVE_DOMAIN
0.1f, // BUBBLE_ISECT_OWNER
0.1f, // BUBBLE_ISECT_TRESPASSER
0.1f, // USER_ENTER_LEAVE_DOMAIN
0.1f, // AVATAR_CHANGE
};
glm::vec4 edgeInnerColor[EVENT_CATEGORY_COUNT]{
{ 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER
{ 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER
{ 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE
};
glm::vec4 edgeOuterColor[EVENT_CATEGORY_COUNT]{
{ 1.0f, 1.0f, 1.0f, 1.0f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_OWNER
{ 1.0f, 1.0f, 1.0f, 1.0f }, // BUBBLE_ISECT_TRESPASSER
{ 1.0f, 1.0f, 1.0f, 1.0f }, // USER_ENTER_LEAVE_DOMAIN
{ 1.0f, 1.0f, 1.0f, 1.0f }, // AVATAR_CHANGE
};
signals:
void dirty();
};
struct FadeCommonParameters
{
using Pointer = std::shared_ptr<FadeCommonParameters>;
float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]{
30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN
0.0f, // BUBBLE_ISECT_OWNER
0.0f, // BUBBLE_ISECT_TRESPASSER
3.0f, // USER_ENTER_LEAVE_DOMAIN
3.0f, // AVATAR_CHANGE
};
};
class FadeSwitchJob {
public:
enum FadeBuckets {
OPAQUE_SHAPE = 0,
TRANSPARENT_SHAPE,
NUM_BUCKETS
};
using FadeOutput = render::VaryingArray<render::ItemBounds, FadeBuckets::NUM_BUCKETS>;
using Input = RenderFetchCullSortTask::Output;
using Output = render::VaryingSet2<RenderFetchCullSortTask::Output, FadeOutput>;
using Config = FadeSwitchJobConfig;
using JobModel = render::Job::ModelIO<FadeSwitchJob, Input, Output, Config>;
FadeSwitchJob(FadeCommonParameters::Pointer commonParams) : _parameters{ commonParams } {}
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output);
private: private:
gpu::TexturePointer _fadeMaskMap; FadeCommonParameters::Pointer _parameters;
float _invScale; bool _isEditEnabled{ false };
float _duration;
float _debugFadePercent; void distribute(const render::RenderContextPointer& renderContext, const render::Varying& input,
bool _isDebugEnabled; render::Varying& normalOutput, render::Varying& fadeOutput) const;
};
struct FadeParameters
{
glm::vec4 _baseInvSizeAndLevel;
glm::vec4 _noiseInvSizeAndLevel;
glm::vec3 _innerEdgeColor;
glm::vec3 _outerEdgeColor;
glm::vec2 _edgeWidthInvWidth;
glm::int32 _invertBase;
glm::float32 _padding;
};
struct FadeConfiguration
{
FadeParameters parameters[FadeJobConfig::EVENT_CATEGORY_COUNT];
};
class FadeConfigureJob {
public:
using UniformBuffer = gpu::StructBuffer<FadeConfiguration>;
using Output = render::VaryingSet2<gpu::TexturePointer, UniformBuffer>;
using Config = FadeJobConfig;
using JobModel = render::Job::ModelO<FadeConfigureJob, Output, Config>;
FadeConfigureJob(FadeCommonParameters::Pointer commonParams);
const gpu::TexturePointer getFadeMaskMap() const { return _fadeMaskMap; }
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, Output& output);
private:
FadeCommonParameters::Pointer _parameters;
bool _isBufferDirty{ true };
gpu::TexturePointer _fadeMaskMap;
FadeParameters _configurations[FadeJobConfig::EVENT_CATEGORY_COUNT];
};
class FadeRenderJob {
public:
using Input = render::VaryingSet3<render::ItemBounds, LightingModelPointer, FadeConfigureJob::Output>;
using JobModel = render::Job::ModelI<FadeRenderJob, Input>;
FadeRenderJob(FadeCommonParameters::Pointer commonParams, render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber }, _parameters{ commonParams } {}
void run(const render::RenderContextPointer& renderContext, const Input& inputs);
static void bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation);
static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation);
static void bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline);
static bool bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime);
static bool bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline, glm::vec3 offset, quint64 startTime);
static float computeFadePercent(quint64 startTime);
private:
static const FadeRenderJob* _currentInstance;
static gpu::TexturePointer _currentFadeMaskMap;
static const gpu::BufferView* _currentFadeBuffer;
render::ShapePlumberPointer _shapePlumber;
FadeCommonParameters::Pointer _parameters;
}; };
#endif // hifi_FadeEffect_h #endif // hifi_FadeEffect_h

View file

@ -523,12 +523,10 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
} }
render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) {
isFading = isFading || DependencyManager::get<FadeEffect>()->isDebugEnabled();
return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;
} }
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
isFading = isFading || DependencyManager::get<FadeEffect>()->isDebugEnabled();
return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline;
} }

View file

@ -319,6 +319,11 @@ template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer&
template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) {
return payload->render(args); return payload->render(args);
} }
template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload) {
return payload->mustFade();
}
} }
ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) :
@ -525,6 +530,10 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
batch.setModelTransform(_transform); batch.setModelTransform(_transform);
} }
bool ModelMeshPartPayload::mustFade() const {
return _fadeState != STATE_COMPLETE;
}
void ModelMeshPartPayload::render(RenderArgs* args) { void ModelMeshPartPayload::render(RenderArgs* args) {
PerformanceTimer perfTimer("ModelMeshPartPayload::render"); PerformanceTimer perfTimer("ModelMeshPartPayload::render");
@ -572,11 +581,16 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
// apply material properties // apply material properties
bindMaterial(batch, locations, args->_enableTexturing); bindMaterial(batch, locations, args->_enableTexturing);
// Apply fade effect if (args->_enableFade) {
if (!DependencyManager::get<FadeEffect>()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState != STATE_COMPLETE)) { // Apply fade effect
if (!FadeRenderJob::bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime)) {
_fadeState = STATE_COMPLETE;
}
}
/* else {
// TODO : very ugly way to update the fade state. Need to improve this with global fade manager. // TODO : very ugly way to update the fade state. Need to improve this with global fade manager.
_fadeState = STATE_COMPLETE; _fadeState = STATE_COMPLETE;
} }*/
args->_details._materialSwitches++; args->_details._materialSwitches++;

View file

@ -97,6 +97,7 @@ public:
int getLayer() const; int getLayer() const;
render::ShapeKey getShapeKey() const override; // shape interface render::ShapeKey getShapeKey() const override; // shape interface
void render(RenderArgs* args) override; void render(RenderArgs* args) override;
bool mustFade() const;
// ModelMeshPartPayload functions to perform render // ModelMeshPartPayload functions to perform render
void bindMesh(gpu::Batch& batch) override; void bindMesh(gpu::Batch& batch) override;
@ -135,6 +136,7 @@ namespace render {
template <> int payloadGetLayer(const ModelMeshPartPayload::Pointer& payload); template <> int payloadGetLayer(const ModelMeshPartPayload::Pointer& payload);
template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload);
template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args);
template <> bool payloadMustFade(const ModelMeshPartPayload::Pointer& payload);
} }
#endif // hifi_MeshPartPayload_h #endif // hifi_MeshPartPayload_h

View file

@ -50,20 +50,15 @@ extern void initDeferredPipelines(render::ShapePlumber& plumber);
void RenderDeferredTask::configure(const Config& config) void RenderDeferredTask::configure(const Config& config)
{ {
const float SCALE_MIN = 0.01f;
const float SCALE_MAX = 5.f;
auto fadeEffect = DependencyManager::get<FadeEffect>();
float scale = SCALE_MIN + (SCALE_MAX - SCALE_MIN)*config.fadeScale*config.fadeScale*config.fadeScale;
fadeEffect->setScale(scale);
fadeEffect->setDuration(config.fadeDuration);
fadeEffect->setDebugEnabled(config.debugFade);
fadeEffect->setDebugFadePercent(config.debugFadePercent);
} }
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
auto items = input.get<Input>(); auto commonFadeParameters = std::make_shared<FadeCommonParameters>();
const auto fadeSwitchOutputs = task.addJob<FadeSwitchJob>("FadeSwitch", input, commonFadeParameters).get<FadeSwitchJob::Output>();
const auto fadeConfigureOutputs = task.addJob<FadeConfigureJob>("FadeConfigure", commonFadeParameters).get<FadeConfigureJob::Output>();
const auto& items = fadeSwitchOutputs.get0();
const auto& fadeItems = fadeSwitchOutputs.get1();
// Prepare the ShapePipelines // Prepare the ShapePipelines
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>(); ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
@ -97,8 +92,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0); const auto deferredFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(0);
const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1); const auto lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
DependencyManager::set<FadeEffect>();
// draw a stencil mask in hidden regions of the framebuffer. // draw a stencil mask in hidden regions of the framebuffer.
task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer); task.addJob<PrepareStencil>("PrepareStencil", primaryFramebuffer);
@ -106,6 +99,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying(); const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel).hasVarying();
task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber); task.addJob<DrawStateSortDeferred>("DrawOpaqueDeferred", opaqueInputs, shapePlumber);
const auto fadeOpaques = fadeItems[FadeSwitchJob::OPAQUE_SHAPE];
const auto fadeOpaqueInputs = FadeRenderJob::Input(fadeOpaques, lightingModel, fadeConfigureOutputs).hasVarying();
task.addJob<FadeRenderJob>("DrawFadeOpaque", fadeOpaqueInputs, commonFadeParameters, shapePlumber);
task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer); task.addJob<EndGPURangeTimer>("OpaqueRangeTimer", opaqueRangeTimer);
@ -159,6 +156,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying();
task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber); task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
const auto fadeTransparents = fadeItems[FadeSwitchJob::TRANSPARENT_SHAPE];
const auto fadeTransparentInputs = FadeRenderJob::Input(fadeTransparents, lightingModel, fadeConfigureOutputs).hasVarying();
task.addJob<FadeRenderJob>("DrawFadeTransparent", fadeTransparentInputs, commonFadeParameters, shapePlumber);
// LIght Cluster Grid Debuging job // LIght Cluster Grid Debuging job
{ {
const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying(); const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).hasVarying();
@ -262,7 +263,6 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
const auto& lightingModel = inputs.get1(); const auto& lightingModel = inputs.get1();
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder = DependencyManager::get<FadeEffect>()->getKeyBuilder();
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch; args->_batch = &batch;
@ -283,14 +283,11 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
// From the lighting model define a global shapKey ORED with individiual keys // From the lighting model define a global shapKey ORED with individiual keys
ShapeKey::Builder keyBuilder = defaultKeyBuilder; ShapeKey::Builder keyBuilder;
if (lightingModel->isWireframeEnabled()) { if (lightingModel->isWireframeEnabled()) {
keyBuilder.withWireframe(); keyBuilder.withWireframe();
} }
// Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
ShapeKey globalKey = keyBuilder.build(); ShapeKey globalKey = keyBuilder.build();
args->_globalShapeKey = globalKey._flags.to_ulong(); args->_globalShapeKey = globalKey._flags.to_ulong();
@ -313,7 +310,6 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
const auto& lightingModel = inputs.get1(); const auto& lightingModel = inputs.get1();
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder = DependencyManager::get<FadeEffect>()->getKeyBuilder();
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch; args->_batch = &batch;
@ -334,14 +330,11 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
// From the lighting model define a global shapeKey ORED with individiual keys // From the lighting model define a global shapeKey ORED with individiual keys
ShapeKey::Builder keyBuilder = defaultKeyBuilder; ShapeKey::Builder keyBuilder;
if (lightingModel->isWireframeEnabled()) { if (lightingModel->isWireframeEnabled()) {
keyBuilder.withWireframe(); keyBuilder.withWireframe();
} }
// Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
ShapeKey globalKey = keyBuilder.build(); ShapeKey globalKey = keyBuilder.build();
args->_globalShapeKey = globalKey._flags.to_ulong(); args->_globalShapeKey = globalKey._flags.to_ulong();

View file

@ -53,7 +53,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
const auto& fbo = shadow->framebuffer; const auto& fbo = shadow->framebuffer;
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder = DependencyManager::get<FadeEffect>()->getKeyBuilder(); ShapeKey::Builder defaultKeyBuilder;// TODO: support fade on shadows = DependencyManager::get<FadeEffect>()->getKeyBuilder();
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch; args->_batch = &batch;
@ -75,7 +75,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
// Prepare fade effect // Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch); // TODO: support fade on shadows DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
std::vector<ShapeKey> skinnedShapeKeys{}; std::vector<ShapeKey> skinnedShapeKeys{};

View file

@ -30,7 +30,9 @@ in vec2 _texCoord1;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -50,6 +52,7 @@ void main(void) {
vec3 emissive = getMaterialEmissive(mat); vec3 emissive = getMaterialEmissive(mat);
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
emissive += fadeEmissive;
float scattering = getMaterialScattering(mat); float scattering = getMaterialScattering(mat);

View file

@ -31,7 +31,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -46,5 +48,5 @@ void main(void) {
getMaterialRoughness(mat) * roughness, getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat), getMaterialMetallic(mat),
getMaterialFresnel(mat), getMaterialFresnel(mat),
lightmapVal); lightmapVal+fadeEmissive);
} }

View file

@ -32,7 +32,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -49,5 +51,5 @@ void main(void) {
getMaterialRoughness(mat), getMaterialRoughness(mat),
getMaterialMetallic(mat), getMaterialMetallic(mat),
getMaterialFresnel(mat), getMaterialFresnel(mat),
lightmapVal); lightmapVal+fadeEmissive);
} }

View file

@ -32,7 +32,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -49,5 +51,5 @@ void main(void) {
getMaterialRoughness(mat) * roughness, getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat) * metallicTex, getMaterialMetallic(mat) * metallicTex,
/*specular, // no use of */ getMaterialFresnel(mat), /*specular, // no use of */ getMaterialFresnel(mat),
lightmapVal); lightmapVal+fadeEmissive);
} }

View file

@ -31,7 +31,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -45,5 +47,5 @@ void main(void) {
getMaterialRoughness(mat) * roughness, getMaterialRoughness(mat) * roughness,
getMaterialMetallic(mat) * metallicTex, getMaterialMetallic(mat) * metallicTex,
/*metallicTex, // no use of */getMaterialFresnel(mat), /*metallicTex, // no use of */getMaterialFresnel(mat),
lightmapVal); lightmapVal+fadeEmissive);
} }

View file

@ -31,7 +31,9 @@ in vec3 _tangent;
in vec3 _color; in vec3 _color;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);

View file

@ -31,7 +31,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -66,7 +68,7 @@ void main(void) {
albedo, albedo,
roughness, roughness,
metallic, metallic,
emissive, emissive+fadeEmissive,
occlusionTex, occlusionTex,
scattering); scattering);
} }

View file

@ -20,7 +20,7 @@ layout(location = 0) out vec4 _fragColor;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); applyFadeClip(_worldFadePosition.xyz);
// pass-through to set z-buffer // pass-through to set z-buffer
_fragColor = vec4(1.0, 1.0, 1.0, 0.0); _fragColor = vec4(1.0, 1.0, 1.0, 0.0);

View file

@ -30,7 +30,9 @@ in vec3 _color;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -62,7 +64,7 @@ void main(void) {
albedo, albedo,
roughness, roughness,
metallic, metallic,
emissive, emissive+fadeEmissive,
occlusionTex, occlusionTex,
scattering); scattering);
} }

View file

@ -38,7 +38,9 @@ in vec4 _worldFadePosition;
out vec4 _fragColor; out vec4 _fragColor;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -81,7 +83,7 @@ void main(void) {
albedo, albedo,
fresnel, fresnel,
metallic, metallic,
emissive, emissive+fadeEmissive,
roughness, opacity), roughness, opacity),
opacity); opacity);
} }

View file

@ -29,7 +29,9 @@ in vec4 _worldFadePosition;
out vec4 _fragColor; out vec4 _fragColor;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -41,6 +43,6 @@ void main(void) {
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color; albedo *= _color;
albedo += fadeEmissive;
_fragColor = vec4(albedo * isUnlitEnabled(), opacity); _fragColor = vec4(albedo * isUnlitEnabled(), opacity);
} }

View file

@ -29,7 +29,9 @@ in float _alpha;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material mat = getMaterial(); Material mat = getMaterial();
int matKey = getMaterialKey(mat); int matKey = getMaterialKey(mat);
@ -42,7 +44,7 @@ void main(void) {
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;
albedo *= _color; albedo *= _color;
albedo += fadeEmissive;
packDeferredFragmentUnlit( packDeferredFragmentUnlit(
normalize(_normal), normalize(_normal),
opacity, opacity,

View file

@ -33,7 +33,9 @@ in vec4 _worldFadePosition;
#line 2030 #line 2030
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
Material material = getMaterial(); Material material = getMaterial();
vec3 normal = normalize(_normal.xyz); vec3 normal = normalize(_normal.xyz);
@ -61,14 +63,14 @@ void main(void) {
packDeferredFragmentTranslucent( packDeferredFragmentTranslucent(
normal, normal,
_color.a, _color.a,
specular, specular+fadeEmissive,
DEFAULT_FRESNEL, DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS); DEFAULT_ROUGHNESS);
} else { } else {
packDeferredFragmentTranslucent( packDeferredFragmentTranslucent(
normal, normal,
_color.a, _color.a,
diffuse, diffuse+fadeEmissive,
DEFAULT_FRESNEL, DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS); DEFAULT_ROUGHNESS);
} }
@ -77,7 +79,7 @@ void main(void) {
packDeferredFragmentLightmap( packDeferredFragmentLightmap(
normal, normal,
1.0, 1.0,
diffuse, diffuse+fadeEmissive,
max(0, 1.0 - shininess / 128.0), max(0, 1.0 - shininess / 128.0),
DEFAULT_METALLIC, DEFAULT_METALLIC,
specular, specular,
@ -89,7 +91,7 @@ void main(void) {
diffuse, diffuse,
max(0, 1.0 - shininess / 128.0), max(0, 1.0 - shininess / 128.0),
length(specular), length(specular),
DEFAULT_EMISSIVE, DEFAULT_EMISSIVE+fadeEmissive,
DEFAULT_OCCLUSION, DEFAULT_OCCLUSION,
DEFAULT_SCATTERING); DEFAULT_SCATTERING);
} }

View file

@ -29,7 +29,9 @@ in vec2 _texCoord0;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0); vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a; float colorAlpha = _color.a;
@ -43,7 +45,7 @@ void main(void) {
packDeferredFragmentTranslucent( packDeferredFragmentTranslucent(
normalize(_normal), normalize(_normal),
colorAlpha * texel.a, colorAlpha * texel.a,
_color.rgb * texel.rgb, _color.rgb * texel.rgb + fadeEmissive,
DEFAULT_FRESNEL, DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS); DEFAULT_ROUGHNESS);
} else { } else {
@ -53,7 +55,7 @@ void main(void) {
_color.rgb * texel.rgb, _color.rgb * texel.rgb,
DEFAULT_ROUGHNESS, DEFAULT_ROUGHNESS,
DEFAULT_METALLIC, DEFAULT_METALLIC,
DEFAULT_EMISSIVE, DEFAULT_EMISSIVE + fadeEmissive,
DEFAULT_OCCLUSION, DEFAULT_OCCLUSION,
DEFAULT_SCATTERING); DEFAULT_SCATTERING);
} }

View file

@ -28,7 +28,9 @@ in vec2 _texCoord0;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st); vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a; float colorAlpha = _color.a;
@ -42,13 +44,13 @@ void main(void) {
packDeferredFragmentTranslucent( packDeferredFragmentTranslucent(
normalize(_normal), normalize(_normal),
colorAlpha * texel.a, colorAlpha * texel.a,
_color.rgb * texel.rgb, _color.rgb * texel.rgb+fadeEmissive,
DEFAULT_FRESNEL, DEFAULT_FRESNEL,
DEFAULT_ROUGHNESS); DEFAULT_ROUGHNESS);
} else { } else {
packDeferredFragmentUnlit( packDeferredFragmentUnlit(
normalize(_normal), normalize(_normal),
1.0, 1.0,
_color.rgb * texel.rgb); _color.rgb * texel.rgb+fadeEmissive);
} }
} }

View file

@ -35,7 +35,9 @@ in vec2 _texCoord0;
in vec4 _worldFadePosition; in vec4 _worldFadePosition;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st); vec4 texel = texture(originalTexture, _texCoord0.st);
float opacity = _color.a; float opacity = _color.a;
@ -59,8 +61,8 @@ void main(void) {
fragNormal, fragNormal,
albedo, albedo,
DEFAULT_FRESNEL, DEFAULT_FRESNEL,
0.0, 0.0f,
vec3(0.0f), fadeEmissive,
DEFAULT_ROUGHNESS, DEFAULT_ROUGHNESS,
opacity), opacity),
opacity); opacity);

View file

@ -29,7 +29,9 @@ in vec4 _worldFadePosition;
layout(location = 0) out vec4 _fragColor0; layout(location = 0) out vec4 _fragColor0;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st); vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a; float colorAlpha = _color.a;
@ -37,5 +39,5 @@ void main(void) {
texel = colorToLinearRGBA(texel); texel = colorToLinearRGBA(texel);
colorAlpha = -_color.a; colorAlpha = -_color.a;
} }
_fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); _fragColor0 = vec4(_color.rgb * texel.rgb+fadeEmissive, colorAlpha * texel.a);
} }

View file

@ -20,7 +20,7 @@ in vec4 _worldFadePosition;
layout(location = 0) out vec4 _fragColor; layout(location = 0) out vec4 _fragColor;
void main(void) { void main(void) {
applyFade(_worldFadePosition.xyz); applyFadeClip(_worldFadePosition.xyz);
// pass-through to set z-buffer // pass-through to set z-buffer
_fragColor = vec4(1.0, 1.0, 1.0, 0.0); _fragColor = vec4(1.0, 1.0, 1.0, 0.0);

View file

@ -115,6 +115,7 @@ namespace render {
uint32_t _globalShapeKey { 0 }; uint32_t _globalShapeKey { 0 };
bool _enableTexturing { true }; bool _enableTexturing { true };
bool _enableFade{ false };
RenderDetails _details; RenderDetails _details;
render::ScenePointer _scene; render::ScenePointer _scene;

View file

@ -316,7 +316,7 @@ public:
virtual const ItemKey getKey() const = 0; virtual const ItemKey getKey() const = 0;
virtual const Bound getBound() const = 0; virtual const Bound getBound() const = 0;
virtual int getLayer() const = 0; virtual int getLayer() const = 0;
virtual bool mustFade() const = 0;
virtual void render(RenderArgs* args) = 0; virtual void render(RenderArgs* args) = 0;
virtual const ShapeKey getShapeKey() const = 0; virtual const ShapeKey getShapeKey() const = 0;
@ -364,6 +364,8 @@ public:
// Get the layer where the item belongs. 0 by default meaning NOT LAYERED // Get the layer where the item belongs. 0 by default meaning NOT LAYERED
int getLayer() const { return _payload->getLayer(); } int getLayer() const { return _payload->getLayer(); }
bool mustFade() const { return _payload->mustFade(); }
// Render call for the item // Render call for the item
void render(RenderArgs* args) const { _payload->render(args); } void render(RenderArgs* args) const { _payload->render(args); }
@ -409,6 +411,7 @@ template <class T> const ItemKey payloadGetKey(const std::shared_ptr<T>& payload
template <class T> const Item::Bound payloadGetBound(const std::shared_ptr<T>& payloadData) { return Item::Bound(); } template <class T> const Item::Bound payloadGetBound(const std::shared_ptr<T>& payloadData) { return Item::Bound(); }
template <class T> int payloadGetLayer(const std::shared_ptr<T>& payloadData) { return 0; } template <class T> int payloadGetLayer(const std::shared_ptr<T>& payloadData) { return 0; }
template <class T> void payloadRender(const std::shared_ptr<T>& payloadData, RenderArgs* args) { } template <class T> void payloadRender(const std::shared_ptr<T>& payloadData, RenderArgs* args) { }
template <class T> bool payloadMustFade(const std::shared_ptr<T>& payloadData) { return false; }
// Shape type interface // Shape type interface
// This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape. // This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape.
@ -435,7 +438,7 @@ public:
virtual const ItemKey getKey() const override { return payloadGetKey<T>(_data); } virtual const ItemKey getKey() const override { return payloadGetKey<T>(_data); }
virtual const Item::Bound getBound() const override { return payloadGetBound<T>(_data); } virtual const Item::Bound getBound() const override { return payloadGetBound<T>(_data); }
virtual int getLayer() const override { return payloadGetLayer<T>(_data); } virtual int getLayer() const override { return payloadGetLayer<T>(_data); }
virtual bool mustFade() const override { return payloadMustFade<T>(_data); }
virtual void render(RenderArgs* args) override { payloadRender<T>(_data, args); } virtual void render(RenderArgs* args) override { payloadRender<T>(_data, args); }

View file

@ -65,6 +65,5 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
const auto overlayTransparents = task.addJob<DepthSortItems>("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto overlayTransparents = task.addJob<DepthSortItems>("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false));
const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET];
output = Varying(Output{{ output = Output{opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection};
opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection }});
} }

View file

@ -31,7 +31,7 @@ public:
NUM_BUCKETS NUM_BUCKETS
}; };
using Output = std::array<render::Varying, Buckets::NUM_BUCKETS>; using Output = render::VaryingArray<render::ItemBounds, Buckets::NUM_BUCKETS>;
using JobModel = render::Task::ModelO<RenderFetchCullSortTask, Output>; using JobModel = render::Task::ModelO<RenderFetchCullSortTask, Output>;
RenderFetchCullSortTask() {} RenderFetchCullSortTask() {}

View file

@ -70,6 +70,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), Slot::MAP::FADE_MASK));
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
@ -89,7 +90,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer");
locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap");
locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap");
locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer");
ShapeKey key{filter._flags}; ShapeKey key{filter._flags};
auto gpuPipeline = gpu::Pipeline::create(program, state); auto gpuPipeline = gpu::Pipeline::create(program, state);
auto shapePipeline = std::make_shared<Pipeline>(gpuPipeline, locations, batchSetter); auto shapePipeline = std::make_shared<Pipeline>(gpuPipeline, locations, batchSetter);

View file

@ -215,6 +215,7 @@ public:
LIGHTING_MODEL, LIGHTING_MODEL,
LIGHT, LIGHT,
LIGHT_AMBIENT_BUFFER, LIGHT_AMBIENT_BUFFER,
FADE_PARAMETERS,
}; };
enum MAP { enum MAP {
@ -246,6 +247,7 @@ public:
int lightAmbientBufferUnit; int lightAmbientBufferUnit;
int lightAmbientMapUnit; int lightAmbientMapUnit;
int fadeMaskTextureUnit; int fadeMaskTextureUnit;
int fadeParameterBufferUnit;
}; };
using LocationsPointer = std::shared_ptr<Locations>; using LocationsPointer = std::shared_ptr<Locations>;

View file

@ -281,6 +281,11 @@ public:
(*this)[i] = Varying(T()); (*this)[i] = Varying(T());
} }
} }
VaryingArray(std::initializer_list<Varying> list) {
assert(list.size() == NUM);
std::copy(list.begin(), list.end(), begin());
}
}; };
} }

View file

@ -15,7 +15,7 @@ var window = new OverlayWindow({
title: 'Fade', title: 'Fade',
source: qml, source: qml,
width: 500, width: 500,
height: 80 height: 900
}); });
window.setPosition(50, 50); window.setPosition(50, 50);
window.closed.connect(function() { Script.stop(); }); window.closed.connect(function() { Script.stop(); });

View file

@ -12,47 +12,228 @@ import QtQuick 2.5
import QtQuick.Controls 1.4 import QtQuick.Controls 1.4
import "configSlider" import "configSlider"
Row { Column {
property var taskConfig: Render.getConfig("RenderDeferredTask"); property var config: Render.getConfig("RenderDeferredTask");
spacing: 4 spacing: 8
Column { Row {
spacing: 8 spacing: 8
CheckBox { CheckBox {
text: "Manual Fade" text: "Edit Fade"
checked: taskConfig["debugFade"] checked: config["editFade"]
onCheckedChanged: { taskConfig["debugFade"] = checked } onCheckedChanged: { config["editFade"] = checked }
}
ComboBox {
width: 400
model: ["Elements enter/leave domain", "Bubble isect. - Owner POV", "Bubble isect. - Trespasser POV", "Another user leaves/arrives", "Changing an avatar"]
onCurrentIndexChanged: { config["editedCategory"] = currentIndex }
} }
} }
Column { Column {
spacing: 8 spacing: 8
ConfigSlider {
label: "Percent"
integral: false
config: taskConfig
property: "debugFadePercent"
max: 1.0
min: 0.0
width: 250
}
ConfigSlider {
label: "Scale"
integral: false
config: taskConfig
property: "fadeScale"
max: 1.0
min: 0.0
width: 250
}
ConfigSlider { ConfigSlider {
label: "Duration" label: "Duration"
integral: false integral: false
config: taskConfig config: config
property: "fadeDuration" property: "duration"
max: 10.0 max: 10.0
min: 0.1 min: 0.1
width: 250 width: 400
}
GroupBox {
title: "Base Gradient"
width: 500
Column {
spacing: 8
ConfigSlider {
label: "Size X"
integral: false
config: config
property: "baseSizeX"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Size Y"
integral: false
config: config
property: "baseSizeY"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Size Z"
integral: false
config: config
property: "baseSizeZ"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Level"
integral: false
config: config
property: "baseLevel"
max: 1.0
min: 0.0
width: 400
}
CheckBox {
text: "Invert"
checked: config["baseInverted"]
onCheckedChanged: { config["baseInverted"] = checked }
}
}
}
GroupBox {
title: "Noise Gradient"
width: 500
Column {
spacing: 8
ConfigSlider {
label: "Size X"
integral: false
config: config
property: "noiseSizeX"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Size Y"
integral: false
config: config
property: "noiseSizeY"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Size Z"
integral: false
config: config
property: "noiseSizeZ"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Level"
integral: false
config: config
property: "noiseLevel"
max: 1.0
min: 0.0
width: 400
}
}
}
GroupBox {
title: "Edge"
width: 500
Column {
spacing: 8
ConfigSlider {
label: "Width"
integral: false
config: config
property: "edgeWidth"
max: 1.0
min: 0.0
width: 400
}
GroupBox {
title: "Inner color"
Column {
spacing: 8
ConfigSlider {
label: "Color R"
integral: false
config: config
property: "edgeInnerColorR"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color G"
integral: false
config: config
property: "edgeInnerColorG"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color B"
integral: false
config: config
property: "edgeInnerColorB"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color intensity"
integral: false
config: config
property: "edgeInnerIntensity"
max: 5.0
min: 0.0
width: 400
}
}
}
GroupBox {
title: "Outer color"
Column {
spacing: 8
ConfigSlider {
label: "Color R"
integral: false
config: config
property: "edgeOuterColorR"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color G"
integral: false
config: config
property: "edgeOuterColorG"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color B"
integral: false
config: config
property: "edgeOuterColorB"
max: 1.0
min: 0.0
width: 400
}
ConfigSlider {
label: "Color intensity"
integral: false
config: config
property: "edgeOuterIntensity"
max: 5.0
min: 0.0
width: 400
}
}
}
}
} }
} }
} }