alpha over and opacity nodes are now functional
This commit is contained in:
@@ -131,8 +131,8 @@ private:
|
||||
intType gcd(intType &x, intType &y);
|
||||
};
|
||||
|
||||
#define RATIONAL_MIN rational(LONG_MIN, 1)
|
||||
#define RATIONAL_MAX rational(LONG_MAX, 1)
|
||||
#define RATIONAL_MIN rational(INT32_MIN, 1)
|
||||
#define RATIONAL_MAX rational(INT32_MAX, 1)
|
||||
|
||||
Q_DECLARE_METATYPE(rational)
|
||||
|
||||
|
||||
@@ -307,6 +307,9 @@ void Core::CreateNewSequence()
|
||||
// Connect track to timeline
|
||||
NodeParam::ConnectEdge(to->track_output(), tb->track_input());
|
||||
|
||||
// Connect timeline end point to renderer
|
||||
NodeParam::ConnectEdge(tb->length_output(), rp->length_input());
|
||||
|
||||
// FIXME: Test code
|
||||
AlphaOverBlend* blend = new AlphaOverBlend();
|
||||
new_sequence->AddNode(blend);
|
||||
|
||||
@@ -64,8 +64,13 @@ QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time)
|
||||
RenderTexturePtr base = base_input()->get_value(time).value<RenderTexturePtr>();
|
||||
RenderTexturePtr blend = blend_input()->get_value(time).value<RenderTexturePtr>();
|
||||
|
||||
// Set compositing strategy to alpha over
|
||||
renderer->context()->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
if (base == nullptr && blend == nullptr) {
|
||||
return 0;
|
||||
} else if (base == nullptr) {
|
||||
return QVariant::fromValue(blend);
|
||||
} else if (blend == nullptr) {
|
||||
return QVariant::fromValue(base);
|
||||
}
|
||||
|
||||
// Attach framebuffer to the backbuffer of base
|
||||
renderer->buffer()->Attach(base);
|
||||
@@ -74,13 +79,16 @@ QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time)
|
||||
// Bind blend
|
||||
blend->Bind();
|
||||
|
||||
// Set compositing strategy to alpha over
|
||||
renderer->context()->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Draw blend on base
|
||||
olive::gl::Blit(renderer->default_pipeline());
|
||||
|
||||
// Release all
|
||||
blend->Release();
|
||||
renderer->buffer()->Detach();
|
||||
renderer->buffer()->Release();
|
||||
renderer->buffer()->Detach();
|
||||
|
||||
// Return base texture which now has blend composited on top
|
||||
// NOTE: Blend texture will be implicitly deleted here (if it's not used anywhere else)
|
||||
|
||||
@@ -73,6 +73,10 @@ QVariant OpacityNode::Value(NodeOutput *output, const rational &time)
|
||||
if (output == texture_output_) {
|
||||
RenderTexturePtr input_tex = texture_input_->get_value(time).value<RenderTexturePtr>();
|
||||
|
||||
if (input_tex == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Attach texture's back buffer as frame buffer
|
||||
renderer->buffer()->AttachBackBuffer(input_tex);
|
||||
renderer->buffer()->Bind();
|
||||
@@ -82,17 +86,27 @@ QVariant OpacityNode::Value(NodeOutput *output, const rational &time)
|
||||
|
||||
// Set opacity to value
|
||||
ShaderPtr pipeline = renderer->default_pipeline();
|
||||
pipeline->bind();
|
||||
pipeline->setUniformValue("opacity", opacity_input_->get_value(time).toFloat()*0.01f);
|
||||
pipeline->release();
|
||||
|
||||
renderer->context()->functions()->glBlendFunc(GL_ONE, GL_ZERO);
|
||||
|
||||
// Blit
|
||||
olive::gl::Blit(renderer->default_pipeline());
|
||||
olive::gl::Blit(pipeline);
|
||||
|
||||
// Reset to full opacity
|
||||
pipeline->bind();
|
||||
pipeline->setUniformValue("opacity", 1.0f);
|
||||
pipeline->release();
|
||||
|
||||
input_tex->Release();
|
||||
renderer->buffer()->Release();
|
||||
renderer->buffer()->Detach();
|
||||
|
||||
input_tex->SwapFrontAndBack();
|
||||
|
||||
return QVariant::fromValue(input_tex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -57,6 +57,8 @@ void Node::AddParameter(NodeParam *param)
|
||||
|
||||
if (param->type() == NodeParam::kInput) {
|
||||
connect(param, SIGNAL(ValueChanged(rational, rational)), this, SLOT(InputChanged(rational, rational)));
|
||||
connect(param, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr)));
|
||||
connect(param, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(InputConnectionChanged(NodeEdgePtr)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,3 +362,10 @@ void Node::InputChanged(rational start, rational end)
|
||||
{
|
||||
InvalidateCache(start, end, static_cast<NodeInput*>(sender()));
|
||||
}
|
||||
|
||||
void Node::InputConnectionChanged(NodeEdgePtr edge)
|
||||
{
|
||||
Q_UNUSED(edge)
|
||||
|
||||
InvalidateCache(RATIONAL_MIN, RATIONAL_MAX, static_cast<NodeInput*>(sender()));
|
||||
}
|
||||
|
||||
@@ -288,6 +288,9 @@ private:
|
||||
|
||||
private slots:
|
||||
void InputChanged(rational start, rational end);
|
||||
|
||||
void InputConnectionChanged(NodeEdgePtr edge);
|
||||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -32,6 +32,10 @@ TimelineOutput::TimelineOutput() :
|
||||
track_input_->add_data_input(NodeParam::kTrack);
|
||||
AddParameter(track_input_);
|
||||
|
||||
length_output_ = new NodeOutput("length_out");
|
||||
length_output_->set_data_type(NodeParam::kRational);
|
||||
AddParameter(length_output_);
|
||||
|
||||
connect(this, SIGNAL(EdgeAdded(NodeEdgePtr)), this, SLOT(TrackConnectionAdded(NodeEdgePtr)));
|
||||
connect(this, SIGNAL(EdgeRemoved(NodeEdgePtr)), this, SLOT(TrackConnectionRemoved(NodeEdgePtr)));
|
||||
}
|
||||
@@ -96,10 +100,25 @@ NodeInput *TimelineOutput::track_input()
|
||||
return track_input_;
|
||||
}
|
||||
|
||||
NodeOutput *TimelineOutput::length_output()
|
||||
{
|
||||
return length_output_;
|
||||
}
|
||||
|
||||
QVariant TimelineOutput::Value(NodeOutput *output, const rational &time)
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(time)
|
||||
if (output == length_output_) {
|
||||
Q_UNUSED(time)
|
||||
|
||||
rational length;
|
||||
|
||||
// Retrieve each track's end point and return the longest of the tracks
|
||||
foreach (TrackOutput* track, track_cache_) {
|
||||
length = qMax(track->in(), length);
|
||||
}
|
||||
|
||||
return QVariant::fromValue(length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ public:
|
||||
|
||||
NodeInput* track_input();
|
||||
|
||||
NodeOutput* length_output();
|
||||
|
||||
protected:
|
||||
virtual QVariant Value(NodeOutput* output, const rational& time) override;
|
||||
|
||||
@@ -65,6 +67,8 @@ private:
|
||||
|
||||
NodeInput* track_input_;
|
||||
|
||||
NodeOutput* length_output_;
|
||||
|
||||
/**
|
||||
* @brief A cache of connected Tracks
|
||||
*/
|
||||
|
||||
@@ -226,6 +226,7 @@ QString NodeParam::GetDefaultDataTypeName(const DataType& type)
|
||||
case kBlock: return tr("Block");
|
||||
case kFootage: return tr("Footage");
|
||||
case kTrack: return tr("Track");
|
||||
case kRational: return tr("Rational");
|
||||
case kAny: return tr("Any");
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ public:
|
||||
kBlock,
|
||||
kFootage,
|
||||
kTrack,
|
||||
kRational,
|
||||
kAny
|
||||
};
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ RendererProcessor::RendererProcessor() :
|
||||
texture_input_->add_data_input(NodeInput::kTexture);
|
||||
AddParameter(texture_input_);
|
||||
|
||||
length_input_ = new NodeInput("length_in");
|
||||
length_input_->add_data_input(NodeInput::kRational);
|
||||
AddParameter(length_input_);
|
||||
|
||||
texture_output_ = new NodeOutput("tex_out");
|
||||
texture_output_->set_data_type(NodeInput::kTexture);
|
||||
AddParameter(texture_output_);
|
||||
@@ -126,18 +130,22 @@ void RendererProcessor::InvalidateCache(const rational &start_range, const ratio
|
||||
{
|
||||
Q_UNUSED(from)
|
||||
|
||||
// Adjust range to min/max values
|
||||
rational start_range_adj = qMax(rational(0), start_range);
|
||||
rational end_range_adj = qMin(length_input()->get_value(0).value<rational>(), end_range);
|
||||
|
||||
qDebug() << "[RendererProcessor] Cache invalidated between"
|
||||
<< start_range.toDouble()
|
||||
<< start_range_adj.toDouble()
|
||||
<< "and"
|
||||
<< end_range.toDouble();
|
||||
<< end_range_adj.toDouble();
|
||||
|
||||
// Snap start_range to timebase
|
||||
double start_range_dbl = start_range.toDouble();
|
||||
double start_range_dbl = start_range_adj.toDouble();
|
||||
double start_range_numf = start_range_dbl * static_cast<double>(timebase_.denominator());
|
||||
int64_t start_range_numround = qFloor(start_range_numf/static_cast<double>(timebase_.numerator())) * timebase_.numerator();
|
||||
rational true_start_range(start_range_numround, timebase_.denominator());
|
||||
|
||||
for (rational r=true_start_range;r<=end_range;r+=timebase_) {
|
||||
for (rational r=true_start_range;r<=end_range_adj;r+=timebase_) {
|
||||
if (!cache_queue_.contains(r)) {
|
||||
cache_queue_.append(r);
|
||||
}
|
||||
@@ -395,6 +403,11 @@ NodeInput *RendererProcessor::texture_input()
|
||||
return texture_input_;
|
||||
}
|
||||
|
||||
NodeInput *RendererProcessor::length_input()
|
||||
{
|
||||
return length_input_;
|
||||
}
|
||||
|
||||
NodeOutput *RendererProcessor::texture_output()
|
||||
{
|
||||
return texture_output_;
|
||||
|
||||
@@ -100,6 +100,8 @@ public:
|
||||
|
||||
NodeInput* texture_input();
|
||||
|
||||
NodeInput* length_input();
|
||||
|
||||
NodeOutput* texture_output();
|
||||
|
||||
protected:
|
||||
@@ -145,6 +147,8 @@ private:
|
||||
|
||||
NodeInput* texture_input_;
|
||||
|
||||
NodeInput* length_input_;
|
||||
|
||||
NodeOutput* texture_output_;
|
||||
|
||||
int width_;
|
||||
|
||||
@@ -95,7 +95,7 @@ void RenderFramebuffer::Attach(RenderTexturePtr texture)
|
||||
}
|
||||
|
||||
texture_ = texture;
|
||||
AttachInternal(texture_->texture());
|
||||
AttachInternal(texture_->texture(), false);
|
||||
}
|
||||
|
||||
void RenderFramebuffer::AttachBackBuffer(RenderTexturePtr texture)
|
||||
@@ -105,10 +105,7 @@ void RenderFramebuffer::AttachBackBuffer(RenderTexturePtr texture)
|
||||
}
|
||||
|
||||
texture_ = texture;
|
||||
AttachInternal(texture_->back_texture());
|
||||
|
||||
context_->functions()->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
context_->functions()->glClear(GL_COLOR_BUFFER_BIT);
|
||||
AttachInternal(texture_->back_texture(), true);
|
||||
}
|
||||
|
||||
void RenderFramebuffer::Detach()
|
||||
@@ -137,7 +134,7 @@ const GLuint &RenderFramebuffer::buffer() const
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
void RenderFramebuffer::AttachInternal(GLuint tex)
|
||||
void RenderFramebuffer::AttachInternal(GLuint tex, bool clear)
|
||||
{
|
||||
Detach();
|
||||
|
||||
@@ -150,6 +147,11 @@ void RenderFramebuffer::AttachInternal(GLuint tex)
|
||||
GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0
|
||||
);
|
||||
|
||||
if (clear) {
|
||||
context_->functions()->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
context_->functions()->glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
// release framebuffer
|
||||
f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public slots:
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
void AttachInternal(GLuint tex);
|
||||
void AttachInternal(GLuint tex, bool clear);
|
||||
|
||||
QOpenGLContext* context_;
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ bool RenderInstance::Start()
|
||||
|
||||
// Set viewport to the compositing dimensions
|
||||
ctx_->functions()->glViewport(0, 0, width_, height_);
|
||||
ctx_->functions()->glEnable(GL_BLEND);
|
||||
|
||||
// Set up default pipeline
|
||||
default_pipeline_ = olive::ShaderGenerator::DefaultPipeline();
|
||||
|
||||
@@ -52,6 +52,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
case NodeParam::kTexture:
|
||||
case NodeParam::kMatrix:
|
||||
case NodeParam::kTrack:
|
||||
case NodeParam::kRational:
|
||||
break;
|
||||
case NodeParam::kInt:
|
||||
{
|
||||
@@ -63,6 +64,7 @@ void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
case NodeParam::kFloat:
|
||||
{
|
||||
FloatSlider* slider = new FloatSlider();
|
||||
slider->SetValue(base_input->get_value(0).toDouble());
|
||||
widgets_.append(slider);
|
||||
connect(slider, SIGNAL(ValueChanged(double)), this, SLOT(WidgetCallback()));
|
||||
break;
|
||||
@@ -125,6 +127,7 @@ void NodeParamViewWidgetBridge::WidgetCallback()
|
||||
case NodeParam::kTexture:
|
||||
case NodeParam::kMatrix:
|
||||
case NodeParam::kTrack:
|
||||
case NodeParam::kRational:
|
||||
break;
|
||||
case NodeParam::kInt:
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user