Working avater enter/leaves + manual threshold

This commit is contained in:
Olivier Prat 2017-07-03 12:40:58 +02:00
parent 87833abd31
commit af7957491b
5 changed files with 85 additions and 47 deletions

View file

@ -66,14 +66,14 @@ float evalFadeNoiseGradient(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) * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w;
float noise = mix(maskY.x, maskY.y, noisePositionFraction.y);
noise -= 0.5; // Center on value 0
return noise * fadeParameters[fadeCategory]._noiseInvSizeAndLevel.w;
}
float evalFadeBaseGradient(vec3 position) {
float gradient = length((position - fadeBaseOffset) * fadeParameters[fadeCategory]._baseInvSizeAndLevel.xyz);
if (fadeParameters[fadeCategory]._invertBase!=0) {
gradient = 1.0 - gradient;
}
gradient = mod(gradient, 1.0)-0.5; // Center on value 0.5
gradient *= fadeParameters[fadeCategory]._baseInvSizeAndLevel.w;
return gradient;
}
@ -81,17 +81,15 @@ float evalFadeBaseGradient(vec3 position) {
float evalFadeGradient(vec3 position) {
float baseGradient = evalFadeBaseGradient(position);
float noiseGradient = evalFadeNoiseGradient(position);
float gradient = (noiseGradient-0.5*fadeParameters[fadeCategory]._baseInvSizeAndLevel.w);
float gradient = noiseGradient+baseGradient+0.5;
// 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);
//float edgeWidth = fadeParameters[fadeCategory]._edgeWidthInvWidth.x;
//float cutoff = mix(-edgeWidth, 1.0+edgeWidth, fadeThreshold);
float cutoff = fadeThreshold;
return evalFadeGradient(position)-cutoff;
}
@ -104,6 +102,10 @@ void applyFadeClip(vec3 position) {
void applyFade(vec3 position, out vec3 emissive) {
float alpha = evalFadeAlpha(position);
if (fadeParameters[fadeCategory]._invertBase!=0) {
alpha = -alpha;
}
if (alpha < 0) {
discard;
}
@ -111,12 +113,12 @@ void applyFade(vec3 position, out vec3 emissive) {
float edgeMask = alpha * fadeParameters[fadeCategory]._edgeWidthInvWidth.y;
float edgeAlpha = 1.0-clamp(edgeMask, 0, 1);
//edgeMask = step(edgeMask, 1.f);
edgeMask = edgeMask > 1.f ? 0.f : 1.f;
edgeMask = step(edgeMask, 1.f);
edgeAlpha *= edgeAlpha; // Square to have a nice ease out
vec4 color = mix(fadeParameters[fadeCategory]._innerEdgeColor, fadeParameters[fadeCategory]._outerEdgeColor, edgeAlpha);
emissive = color.rgb * edgeMask * color.a;
}
<@endfunc@>
<@endif@>

View file

@ -250,6 +250,9 @@ FadeConfigureJob::FadeConfigureJob(FadeCommonParameters::Pointer commonParams) :
void FadeConfigureJob::configure(const Config& config) {
assert(_parameters);
_parameters->_editedCategory = config.editedCategory;
_parameters->_isManualThresholdEnabled = config.manualFade;
_parameters->_manualThreshold = config.manualThreshold;
for (auto i = 0; i < FadeJobConfig::EVENT_CATEGORY_COUNT; i++) {
auto& configuration = _configurations[i];
@ -267,6 +270,7 @@ void FadeConfigureJob::configure(const Config& config) {
configuration._edgeWidthInvWidth.y = 1.f / configuration._edgeWidthInvWidth.x;
configuration._innerEdgeColor = config.edgeInnerColor[i];
configuration._outerEdgeColor = config.edgeOuterColor[i];
_parameters->_thresholdScale[i] = 1.f + 2.f*(configuration._edgeWidthInvWidth.x + std::max(0.f, (config.noiseLevel[i] + config.baseLevel[i])*0.5f-0.5f));
}
_isBufferDirty = true;
}
@ -276,7 +280,7 @@ void FadeConfigureJob::run(const render::RenderContextPointer& renderContext, co
auto& configurations = output.edit1().edit();
std::copy(_configurations, _configurations + FadeJobConfig::EVENT_CATEGORY_COUNT, configurations.parameters);
if (_parameters->_editedCategory == FadeJobConfig::USER_ENTER_LEAVE_DOMAIN) {
configurations.parameters[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._baseInvSizeAndLevel.y = 2.f / input.getDimensions().y;
configurations.parameters[FadeJobConfig::USER_ENTER_LEAVE_DOMAIN]._baseInvSizeAndLevel.y = 1.0f / input.getDimensions().y;
}
_isBufferDirty = false;
}
@ -314,10 +318,10 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const
// Update interactive edit effect
if (_parameters->_isEditEnabled) {
updateFadeEdit(inItems.front());
updateFadeEdit(renderContext, inItems.front());
}
else {
_editStartTime = 0;
_editPreviousTime = 0;
}
// Setup camera, projection and viewport for all items
@ -362,9 +366,10 @@ void FadeRenderJob::run(const render::RenderContextPointer& renderContext, const
}
}
float FadeRenderJob::computeElementEnterThreshold(double time) const {
float FadeRenderJob::computeElementEnterThreshold(double time, const double period) const {
assert(period > 0.0);
float fadeAlpha = 1.0f;
const double INV_FADE_PERIOD = 1.0 / (double)(_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]);
const double INV_FADE_PERIOD = 1.0 / period;
double fraction = time * INV_FADE_PERIOD;
fraction = std::max(fraction, 0.0);
if (fraction < 1.0) {
@ -376,31 +381,35 @@ float FadeRenderJob::computeElementEnterThreshold(double time) const {
float FadeRenderJob::computeFadePercent(quint64 startTime) {
const double time = (double)(int64_t(usecTimestampNow()) - int64_t(startTime)) / (double)(USECS_PER_SECOND);
assert(_currentInstance);
return _currentInstance->computeElementEnterThreshold(time);
return _currentInstance->computeElementEnterThreshold(time, _currentInstance->_parameters->_durations[FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN]);
}
void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) {
if (_editStartTime == 0) {
_editStartTime = usecTimestampNow();
void FadeRenderJob::updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds) {
if (_editPreviousTime == 0) {
_editPreviousTime = usecTimestampNow();
_editTime = 0.0;
}
const double time = (int64_t(usecTimestampNow()) - int64_t(_editStartTime)) / double(USECS_PER_SECOND);
uint64_t now = usecTimestampNow();
const double deltaTime = (int64_t(now) - int64_t(_editPreviousTime)) / double(USECS_PER_SECOND);
const float eventDuration = _parameters->_durations[_parameters->_editedCategory];
const double waitTime = 0.5; // Wait between fade in and out
double cycleTime = fmod(_editTime, (eventDuration + waitTime) * 2.0);
_editTime += deltaTime;
_editPreviousTime = now;
switch (_parameters->_editedCategory) {
case FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN:
{
const double waitTime = 0.5; // Wait between fade in and out
double cycleTime = fmod(time, (eventDuration+waitTime) * 2.0);
if (cycleTime < eventDuration) {
_editThreshold = 1.f-computeElementEnterThreshold(cycleTime);
_editThreshold = 1.f-computeElementEnterThreshold(cycleTime, eventDuration);
}
else if (cycleTime < (eventDuration + waitTime)) {
_editThreshold = 0.f;
}
else if (cycleTime < (2 * eventDuration + waitTime)) {
_editThreshold = computeElementEnterThreshold(cycleTime- (eventDuration + waitTime));
_editThreshold = computeElementEnterThreshold(cycleTime- (eventDuration + waitTime), eventDuration);
}
else {
_editThreshold = 1.f;
@ -416,28 +425,21 @@ void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) {
case FadeJobConfig::USER_ENTER_LEAVE_DOMAIN:
{
const double waitTime = 0.5; // Wait between fade in and out
double cycleTime = fmod(time, (eventDuration + waitTime) * 2.0);
_editNoiseOffset.x = time*0.5;
_editNoiseOffset.x = _editTime*0.5;
_editNoiseOffset.y = 0.f;
_editNoiseOffset.z = time*0.75;
_editNoiseOffset.z = _editTime*0.75;
_editBaseOffset.x = 0.f;
_editBaseOffset.y = -itemBounds.bound.getDimensions().y;
_editBaseOffset.z = 0.f;
{
}
_editBaseOffset = itemBounds.bound.calcCenter();
_editBaseOffset.y -= itemBounds.bound.getDimensions().y/2.f;
if (cycleTime < eventDuration) {
_editThreshold = 1.f - computeElementEnterThreshold(cycleTime);
_editThreshold = 1.f - computeElementEnterThreshold(cycleTime, eventDuration);
}
else if (cycleTime < (eventDuration + waitTime)) {
_editThreshold = 0.f;
}
else if (cycleTime < (2 * eventDuration + waitTime)) {
_editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime));
_editThreshold = computeElementEnterThreshold(cycleTime - (eventDuration + waitTime), eventDuration);
}
else {
_editThreshold = 1.f;
@ -451,6 +453,10 @@ void FadeRenderJob::updateFadeEdit(const render::ItemBound& itemBounds) {
default:
assert(false);
}
if (_parameters->_isManualThresholdEnabled) {
_editThreshold = _parameters->_manualThreshold;
}
}
void FadeRenderJob::bindPerBatch(gpu::Batch& batch, int fadeMaskMapLocation, int fadeBufferLocation) {
@ -496,9 +502,12 @@ bool FadeRenderJob::bindPerItem(gpu::Batch& batch, const gpu::Pipeline* pipeline
eventCategory = _currentInstance->_parameters->_editedCategory;
threshold = _currentInstance->_editThreshold;
noiseOffset += _currentInstance->_editNoiseOffset;
baseOffset += _currentInstance->_editBaseOffset;
// This works supposing offset is the world position of the object that is fading.
baseOffset = _currentInstance->_editBaseOffset - offset;
}
threshold = (threshold-0.5f)*_currentInstance->_parameters->_thresholdScale[eventCategory] + 0.5f;
batch._glUniform1i(fadeCategoryLocation, eventCategory);
batch._glUniform1f(fadeThresholdLocation, threshold);
// This is really temporary

View file

@ -52,6 +52,8 @@ class FadeJobConfig : public render::Job::Config {
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)
Q_PROPERTY(bool manualFade MEMBER manualFade NOTIFY dirty)
Q_PROPERTY(float manualThreshold MEMBER manualThreshold NOTIFY dirty)
public:
@ -124,10 +126,12 @@ public:
void setEdgeOuterIntensity(float value);
float getEdgeOuterIntensity() const { return edgeOuterColor[editedCategory].a; }
bool manualFade{ false };
float manualThreshold{ 0.f };
int editedCategory{ ELEMENT_ENTER_LEAVE_DOMAIN };
glm::vec3 noiseSize[EVENT_CATEGORY_COUNT]{
{ 1.f, 1.f, 1.f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 0.75f, 0.75f, 0.75f }, // ELEMENT_ENTER_LEAVE_DOMAIN
{ 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_OWNER
{ 0.4f, 0.4f, 0.4f }, // BUBBLE_ISECT_TRESPASSER
{ 10.f, 0.01f, 10.0f }, // USER_ENTER_LEAVE_DOMAIN
@ -201,6 +205,9 @@ struct FadeCommonParameters
using Pointer = std::shared_ptr<FadeCommonParameters>;
bool _isEditEnabled{ false };
bool _isManualThresholdEnabled{ false };
float _manualThreshold{ 0.f };
float _thresholdScale[FadeJobConfig::EVENT_CATEGORY_COUNT];
int _editedCategory{ FadeJobConfig::ELEMENT_ENTER_LEAVE_DOMAIN };
float _durations[FadeJobConfig::EVENT_CATEGORY_COUNT]{
30.0f, // ELEMENT_ENTER_LEAVE_DOMAIN
@ -312,15 +319,16 @@ private:
render::ShapePlumberPointer _shapePlumber;
FadeCommonParameters::Pointer _parameters;
float computeElementEnterThreshold(double time) const;
float computeElementEnterThreshold(double time, const double period) const;
// Everything needed for interactive edition
uint64_t _editStartTime{ 0 };
uint64_t _editPreviousTime{ 0 };
double _editTime{ 0.0 };
float _editThreshold{ 0.f };
glm::vec3 _editNoiseOffset{ 0.f, 0.f, 0.f };
glm::vec3 _editBaseOffset{ 0.f, 0.f, 0.f };
void updateFadeEdit(const render::ItemBound& itemBounds);
void updateFadeEdit(const render::RenderContextPointer& renderContext, const render::ItemBound& itemBounds);
};
#endif // hifi_FadeEffect_h

View file

@ -66,7 +66,7 @@ void main(void) {
albedo,
roughness,
getMaterialMetallic(mat),
emissive,
emissive+fadeEmissive,
occlusionTex,
scattering);
}

View file

@ -46,6 +46,25 @@ Column {
}
}
}
Row {
CheckBox {
text: "Manual"
checked: root.config["manualFade"]
onCheckedChanged: {
root.config["manualFade"] = checked;
}
}
ConfigSlider {
label: "Threshold"
integral: false
config: root.config
property: "manualThreshold"
max: 1.0
min: 0.0
width: 400
}
}
Component {
id: paramWidgets