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;
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("yMap"), 1));
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>();
state->setCullMode(gpu::State::CULL_BACK);
@ -823,9 +824,9 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
}
// Apply fade effect
auto fadeEffect = DependencyManager::get<FadeEffect>();
if (fadeEffect->bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime, isFading())) {
fadeEffect->bindPerBatch(batch, 3);
if (args->_enableFade) {
FadeRenderJob::bindPerBatch(batch, render::ShapePipeline::Slot::MAP::FADE_MASK, render::ShapePipeline::Slot::BUFFER::FADE_PARAMETERS);
FadeRenderJob::bindPerItem(batch, pipeline.get(), glm::vec3(0, 0, 0), _fadeStartTime);
}
int voxelVolumeSizeLocation = pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
@ -882,6 +883,13 @@ namespace render {
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 Item::Bound payloadGetBound(const PolyVoxPayload::Pointer& payload);
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,
int x, int y, int z);
#endif // hifi_RenderablePolyVoxEntityItem_h

View file

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

View file

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

View file

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

View file

@ -18,9 +18,26 @@
<@func declareFadeFragment()@>
uniform vec3 fadeOffset;
uniform float fadePercent;
uniform float fadeInvScale;
struct FadeParameters
{
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;
vec2 hash2D(vec3 position) {
@ -31,9 +48,9 @@ float noise3D(vec3 position) {
return textureLod(fadeMaskMap, hash2D(position), 0).r;
}
float evalFadeMask(vec3 position) {
float evalFadeNoiseGradient(vec3 position) {
// Do tri-linear interpolation
vec3 noisePosition = position * fadeInvScale + fadeOffset;
vec3 noisePosition = position * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.xyz + fadeNoiseOffset;
vec3 noisePositionFloored = floor(noisePosition);
vec3 noisePositionFraction = fract(noisePosition);
float noiseLowXLowYLowZ = noise3D(noisePositionFloored);
@ -49,14 +66,59 @@ float evalFadeMask(vec3 position) {
vec4 maskXY = mix(maskLowZ, maskHighZ, noisePositionFraction.z);
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) {
if (evalFadeMask(position) > fadePercent) {
float evalFadeBaseGradient(vec3 position) {
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;
}
}
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@>
<@endif@>

View file

@ -4,73 +4,223 @@
#include <PathUtils.h>
#include <NumericalConstants.h>
#include <Interpolate.h>
#include <render/ShapePipeline.h>
#include <gpu/Context.h>
FadeEffect::FadeEffect() :
_invScale{ 1.f },
_duration{ 3.f },
_debugFadePercent{ 0.f },
_isDebugEnabled{ false }
void FadeSwitchJob::configure(const Config& config) {
_isEditEnabled = config.editFade;
}
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";
_fadeMaskMap = DependencyManager::get<TextureCache>()->getImageTexture(texturePath, image::TextureUsage::STRICT_TEXTURE);
}
render::ShapeKey::Builder FadeEffect::getKeyBuilder(render::ShapeKey::Builder builder) const {
if (_isDebugEnabled) {
// Force fade for everyone
builder.withFade();
}
return builder;
void FadeConfigureJob::configure(const Config& config) {
assert(_parameters);
for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) {
auto& configuration = _configurations[i];
_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 {
batch.setResourceTexture(fadeMaskMapLocation, _fadeMaskMap);
void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, Output& output) {
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 {
auto program = pipeline->getProgram();
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
bindPerBatch(batch, maskMapLocation);
}
const FadeRenderJob* FadeRenderJob::_currentInstance{ nullptr };
gpu::TexturePointer FadeRenderJob::_currentFadeMaskMap;
const gpu::BufferView* FadeRenderJob::_currentFadeBuffer{ nullptr };
float FadeEffect::computeFadePercent(quint64 startTime) const {
float FadeRenderJob::computeFadePercent(quint64 startTime) {
assert(_currentInstance);
float fadeAlpha = 1.0f;
const double INV_FADE_PERIOD = 1.0 / (double)(_duration * USECS_PER_SECOND);
double fraction = (double)(usecTimestampNow() - startTime) * INV_FADE_PERIOD;
const double INV_FADE_PERIOD = 1.0 / (double)(_currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN] * USECS_PER_SECOND);
double fraction = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) * INV_FADE_PERIOD;
fraction = std::max(fraction, 0.0);
if (fraction < 1.0) {
fadeAlpha = Interpolate::easeInOutQuad(fraction);
}
return fadeAlpha;
}
bool FadeEffect::bindPerItem(gpu::Batch& batch, RenderArgs* args, glm::vec3 offset, quint64 startTime, bool isFading) const {
return bindPerItem(batch, args->_pipeline->pipeline.get(), offset, startTime, isFading);
void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const Input& inputs) {
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 {
if (isFading || _isDebugEnabled) {
auto& uniforms = pipeline->getProgram()->getUniforms();
auto fadeScaleLocation = uniforms.findLocation("fadeInvScale");
auto fadeOffsetLocation = uniforms.findLocation("fadeOffset");
auto fadePercentLocation = uniforms.findLocation("fadePercent");
void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) {
assert(_currentFadeMaskMap);
assert(_currentFadeBuffer!=nullptr);
bindPerBatch(batch, _currentFadeMaskMap, fadeMaskMapLocation, _currentFadeBuffer, fadeBufferLocation);
}
if (fadeScaleLocation >= 0 || fadeOffsetLocation >= 0 || fadePercentLocation>=0) {
float percent;
void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, int fadeMaskMapLocation, const gpu::BufferView* buffer, int fadeBufferLocation) {
batch.setResourceTexture(fadeMaskMapLocation, texture);
batch.setUniformBuffer(fadeBufferLocation, *buffer);
}
// A bit ugly to have the test at every bind...
if (!_isDebugEnabled) {
percent = computeFadePercent(startTime);
}
else {
percent = _debugFadePercent;
}
batch._glUniform1f(fadeScaleLocation, _invScale);
batch._glUniform1f(fadePercentLocation, percent);
batch._glUniform3f(fadeOffsetLocation, offset.x, offset.y, offset.z);
void FadeRenderJob::bindPerBatch(gpu::Batch& batch, gpu::TexturePointer texture, const gpu::BufferView* buffer, const gpu::PipelinePointer& pipeline) {
auto program = pipeline->getProgram();
auto maskMapLocation = program->getTextures().findLocation("fadeMaskMap");
auto bufferLocation = program->getUniformBuffers().findLocation("fadeParametersBuffer");
bindPerBatch(batch, texture, maskMapLocation, buffer, bufferLocation);
}
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;
}

View file

@ -11,47 +11,304 @@
#ifndef hifi_FadeEffect_h
#define hifi_FadeEffect_h
#include <DependencyManager.h>
#include <gpu/Pipeline.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:
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; }
float getDuration() const { return 1.f / _duration; }
class FadeJobConfig : public render::Job::Config {
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; }
bool isDebugEnabled() const { return _isDebugEnabled; }
public:
void setDebugFadePercent(float value) { assert(value >= 0.f && value <= 1.f); _debugFadePercent = value; }
float getDebugFadePercent() const { return _debugFadePercent; }
enum EventCategory {
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 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;
void setEditedCategory(int value) { assert(value < EVENT_CATEGORY_COUNT); editedCategory = std::min<int>(EVENT_CATEGORY_COUNT, value); }
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:
gpu::TexturePointer _fadeMaskMap;
float _invScale;
float _duration;
float _debugFadePercent;
bool _isDebugEnabled;
FadeCommonParameters::Pointer _parameters;
bool _isEditEnabled{ false };
void distribute(const render::RenderContextPointer& renderContext, const render::Varying& input,
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

View file

@ -523,12 +523,10 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool
}
render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) {
isFading = isFading || DependencyManager::get<FadeEffect>()->isDebugEnabled();
return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;
}
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
isFading = isFading || DependencyManager::get<FadeEffect>()->isDebugEnabled();
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) {
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) :
@ -525,6 +530,10 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline:
batch.setModelTransform(_transform);
}
bool ModelMeshPartPayload::mustFade() const {
return _fadeState != STATE_COMPLETE;
}
void ModelMeshPartPayload::render(RenderArgs* args) {
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
@ -572,11 +581,16 @@ void ModelMeshPartPayload::render(RenderArgs* args) {
// apply material properties
bindMaterial(batch, locations, args->_enableTexturing);
// Apply fade effect
if (!DependencyManager::get<FadeEffect>()->bindPerItem(batch, args, _transform.getTranslation(), _fadeStartTime, _fadeState != STATE_COMPLETE)) {
if (args->_enableFade) {
// 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.
_fadeState = STATE_COMPLETE;
}
}*/
args->_details._materialSwitches++;

View file

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

View file

@ -50,20 +50,15 @@ extern void initDeferredPipelines(render::ShapePlumber& plumber);
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) {
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
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 lightingFramebuffer = prepareDeferredOutputs.getN<PrepareDeferred::Outputs>(1);
DependencyManager::set<FadeEffect>();
// draw a stencil mask in hidden regions of the framebuffer.
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();
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);
@ -159,6 +156,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying();
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
{
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();
RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder = DependencyManager::get<FadeEffect>()->getKeyBuilder();
gpu::doInBatch(args->_context, [&](gpu::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());
// From the lighting model define a global shapKey ORED with individiual keys
ShapeKey::Builder keyBuilder = defaultKeyBuilder;
ShapeKey::Builder keyBuilder;
if (lightingModel->isWireframeEnabled()) {
keyBuilder.withWireframe();
}
// Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
ShapeKey globalKey = keyBuilder.build();
args->_globalShapeKey = globalKey._flags.to_ulong();
@ -313,7 +310,6 @@ void DrawStateSortDeferred::run(const RenderContextPointer& renderContext, const
const auto& lightingModel = inputs.get1();
RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder = DependencyManager::get<FadeEffect>()->getKeyBuilder();
gpu::doInBatch(args->_context, [&](gpu::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());
// From the lighting model define a global shapeKey ORED with individiual keys
ShapeKey::Builder keyBuilder = defaultKeyBuilder;
ShapeKey::Builder keyBuilder;
if (lightingModel->isWireframeEnabled()) {
keyBuilder.withWireframe();
}
// Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
ShapeKey globalKey = keyBuilder.build();
args->_globalShapeKey = globalKey._flags.to_ulong();

View file

@ -53,7 +53,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
const auto& fbo = shadow->framebuffer;
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) {
args->_batch = &batch;
@ -75,7 +75,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext,
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
// Prepare fade effect
DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
// TODO: support fade on shadows DependencyManager::get<FadeEffect>()->bindPerBatch(batch);
std::vector<ShapeKey> skinnedShapeKeys{};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -29,7 +29,9 @@ in vec4 _worldFadePosition;
layout(location = 0) out vec4 _fragColor0;
void main(void) {
applyFade(_worldFadePosition.xyz);
vec3 fadeEmissive;
applyFade(_worldFadePosition.xyz, fadeEmissive);
vec4 texel = texture(originalTexture, _texCoord0.st);
float colorAlpha = _color.a;
@ -37,5 +39,5 @@ void main(void) {
texel = colorToLinearRGBA(texel);
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;
void main(void) {
applyFade(_worldFadePosition.xyz);
applyFadeClip(_worldFadePosition.xyz);
// pass-through to set z-buffer
_fragColor = vec4(1.0, 1.0, 1.0, 0.0);

View file

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

View file

@ -316,7 +316,7 @@ public:
virtual const ItemKey getKey() const = 0;
virtual const Bound getBound() const = 0;
virtual int getLayer() const = 0;
virtual bool mustFade() const = 0;
virtual void render(RenderArgs* args) = 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
int getLayer() const { return _payload->getLayer(); }
bool mustFade() const { return _payload->mustFade(); }
// Render call for the item
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> 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> bool payloadMustFade(const std::shared_ptr<T>& payloadData) { return false; }
// Shape type interface
// 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 Item::Bound getBound() const override { return payloadGetBound<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); }

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 background = filteredNonspatialBuckets[BACKGROUND_BUCKET];
output = Varying(Output{{
opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection }});
output = Output{opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background, spatialSelection};
}

View file

@ -31,7 +31,7 @@ public:
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>;
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("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
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);
@ -89,7 +90,8 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer");
locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap");
locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap");
locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer");
ShapeKey key{filter._flags};
auto gpuPipeline = gpu::Pipeline::create(program, state);
auto shapePipeline = std::make_shared<Pipeline>(gpuPipeline, locations, batchSetter);

View file

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

View file

@ -281,6 +281,11 @@ public:
(*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',
source: qml,
width: 500,
height: 80
height: 900
});
window.setPosition(50, 50);
window.closed.connect(function() { Script.stop(); });

View file

@ -12,47 +12,228 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import "configSlider"
Row {
property var taskConfig: Render.getConfig("RenderDeferredTask");
spacing: 4
Column {
Column {
property var config: Render.getConfig("RenderDeferredTask");
spacing: 8
Row {
spacing: 8
CheckBox {
text: "Manual Fade"
checked: taskConfig["debugFade"]
onCheckedChanged: { taskConfig["debugFade"] = checked }
text: "Edit Fade"
checked: config["editFade"]
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 {
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 {
label: "Duration"
integral: false
config: taskConfig
property: "fadeDuration"
config: config
property: "duration"
max: 10.0
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
}
}
}
}
}
}
}