proper alpha treatment
This commit is contained in:
@@ -176,7 +176,8 @@ SOURCES += \
|
||||
rendering/bitdepths.cpp \
|
||||
timeline/mediaimportdata.cpp \
|
||||
dialogs/autocutsilencedialog.cpp \
|
||||
ui/columnedgridlayout.cpp
|
||||
ui/columnedgridlayout.cpp \
|
||||
rendering/shadergenerators.cpp
|
||||
|
||||
HEADERS += \
|
||||
ui/mainwindow.h \
|
||||
@@ -306,7 +307,8 @@ HEADERS += \
|
||||
rendering/bitdepths.h \
|
||||
timeline/mediaimportdata.h \
|
||||
dialogs/autocutsilencedialog.h \
|
||||
ui/columnedgridlayout.h
|
||||
ui/columnedgridlayout.h \
|
||||
rendering/shadergenerators.h
|
||||
|
||||
FORMS +=
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QDebug>
|
||||
|
||||
// TODO take this from Config rather than having a constant
|
||||
const GLuint kPixelFormat = GL_RGBA16F;
|
||||
|
||||
FramebufferObject::FramebufferObject() :
|
||||
buffer_(0),
|
||||
texture_(0),
|
||||
@@ -61,12 +64,8 @@ void FramebufferObject::Create(QOpenGLContext *ctx, int width, int height)
|
||||
ctx->functions()->glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
|
||||
// allocate storage for texture
|
||||
/*ctx->functions()->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr
|
||||
);*/
|
||||
|
||||
ctx->functions()->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr
|
||||
GL_TEXTURE_2D, 0, kPixelFormat, width, height, 0, GL_RGBA, GL_FLOAT, nullptr
|
||||
);
|
||||
|
||||
// set texture filtering to bilinear
|
||||
|
||||
+10
-182
@@ -44,6 +44,7 @@ extern "C" {
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "qopenglshaderprogramptr.h"
|
||||
#include "shadergenerators.h"
|
||||
|
||||
GLfloat olive::rendering::blit_vertices[] = {
|
||||
-1.0f, -1.0f, 0.0f,
|
||||
@@ -75,14 +76,6 @@ GLfloat olive::rendering::flipped_blit_texcoords[] = {
|
||||
1.0, 0.0
|
||||
};
|
||||
|
||||
#ifndef NO_OCIO
|
||||
// copied from source code to OCIODisplay
|
||||
const int OCIO_LUT3D_EDGE_SIZE = 32;
|
||||
|
||||
// copied from source code to OCIODisplay, expanded from 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE
|
||||
const int OCIO_NUM_3D_ENTRIES = 98304;
|
||||
#endif
|
||||
|
||||
void olive::rendering::Blit(QOpenGLShaderProgram* pipeline, bool flipped, QMatrix4x4 matrix) {
|
||||
|
||||
QOpenGLVertexArrayObject m_vao;
|
||||
@@ -126,95 +119,6 @@ void olive::rendering::Blit(QOpenGLShaderProgram* pipeline, bool flipped, QMatri
|
||||
|
||||
}
|
||||
|
||||
QOpenGLShaderProgramPtr olive::rendering::GetPipeline(const QString& shader_code)
|
||||
{
|
||||
QOpenGLShaderProgramPtr program = std::make_shared<QOpenGLShaderProgram>();
|
||||
|
||||
// Generate vertex shader
|
||||
QString vert_shader = "#version 110\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump int;\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"uniform mat4 mvp_matrix;\n"
|
||||
"\n"
|
||||
"attribute vec4 a_position;\n"
|
||||
"attribute vec2 a_texcoord;\n"
|
||||
"\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = mvp_matrix * a_position;\n"
|
||||
" v_texcoord = a_texcoord;\n"
|
||||
"}\n";
|
||||
|
||||
// Generate fragment shader
|
||||
QString frag_shader = "#version 110\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump int;\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"uniform sampler2D texture;\n"
|
||||
"uniform float opacity;\n"
|
||||
"uniform bool color_only;\n"
|
||||
"uniform vec4 color_only_color;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"\n";
|
||||
|
||||
// Finish the function with the main function
|
||||
|
||||
// Check if additional code was passed to this function, add it here
|
||||
if (shader_code.isEmpty()) {
|
||||
|
||||
// If not, just add a pure main() function
|
||||
|
||||
frag_shader.append("\n"
|
||||
"void main() {\n"
|
||||
" if (color_only) {\n"
|
||||
" gl_FragColor = color_only_color;"
|
||||
" } else {\n"
|
||||
" vec4 color = texture2D(texture, v_texcoord)*opacity;\n"
|
||||
" gl_FragColor = color;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
} else {
|
||||
|
||||
// If additional code was passed, add it and reference it in main().
|
||||
//
|
||||
// The function in the additional code is expected to be `vec4 process(vec4 color)`. The texture coordinate can be
|
||||
// acquired through `v_texcoord`.
|
||||
|
||||
frag_shader.append(shader_code);
|
||||
|
||||
frag_shader.append("\n"
|
||||
"void main() {\n"
|
||||
" vec4 color = process(texture2D(texture, v_texcoord))*opacity;\n"
|
||||
" gl_FragColor = color;\n"
|
||||
"}\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Add shaders to program
|
||||
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vert_shader);
|
||||
program->addShaderFromSourceCode(QOpenGLShader::Fragment, frag_shader);
|
||||
program->link();
|
||||
|
||||
// Set opacity default to 100%
|
||||
program->bind();
|
||||
program->setUniformValue("opacity", 1.0f);
|
||||
program->release();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
void draw_clip(QOpenGLContext* ctx,
|
||||
QOpenGLShaderProgram* pipeline,
|
||||
GLuint fbo,
|
||||
@@ -560,7 +464,13 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) {
|
||||
OCIO::ConstProcessorRcPtr processor = config->getProcessor(input_cs.toUtf8(),
|
||||
OCIO::ROLE_SCENE_LINEAR);
|
||||
|
||||
c->ocio_shader = olive::rendering::SetupOCIO(params.ctx, c->ocio_lut_texture, processor);
|
||||
olive::shader::AlphaAssociateMode associate_mode = (c->media()->to_footage()->alpha_is_associated)
|
||||
? olive::shader::DisassociateAndReassociate : olive::shader::Associate;
|
||||
|
||||
c->ocio_shader = olive::shader::SetupOCIO(params.ctx,
|
||||
c->ocio_lut_texture,
|
||||
processor,
|
||||
associate_mode);
|
||||
} catch (OCIO::Exception& e) {
|
||||
qWarning() << e.what();
|
||||
}
|
||||
@@ -578,19 +488,6 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!c->media()->to_footage()->alpha_is_associated) {
|
||||
|
||||
// alpha is not premultiplied, we'll need to multiply it for the rest of the pipeline
|
||||
params.ctx->functions()->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ZERO);
|
||||
|
||||
textureID = draw_clip(params.ctx, params.pipeline, c->fbo.at(fbo_switcher), textureID, true);
|
||||
|
||||
params.ctx->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
fbo_switcher = !fbo_switcher;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,9 +593,8 @@ GLuint olive::rendering::compose_sequence(ComposeSequenceParams ¶ms) {
|
||||
params.ctx->functions()->glBindTexture(GL_TEXTURE_2D, textureID);
|
||||
|
||||
// set texture filter to bilinear
|
||||
//params.ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
//params.ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
params.ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
params.ctx->functions()->glGenerateMipmap(GL_TEXTURE_2D);
|
||||
params.ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
params.ctx->functions()->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
// draw clip on screen according to gl coordinates
|
||||
@@ -953,74 +849,6 @@ void close_active_clips(Sequence* s) {
|
||||
}
|
||||
|
||||
#ifndef NO_OCIO
|
||||
QOpenGLShaderProgramPtr olive::rendering::SetupOCIO(QOpenGLContext* ctx,
|
||||
GLuint& lut_texture,
|
||||
OCIO::ConstProcessorRcPtr processor)
|
||||
{
|
||||
|
||||
QOpenGLExtraFunctions* xf = ctx->extraFunctions();
|
||||
|
||||
// Create LUT texture
|
||||
xf->glGenTextures(1, &lut_texture);
|
||||
|
||||
// Bind LUT
|
||||
xf->glBindTexture(GL_TEXTURE_3D, lut_texture);
|
||||
|
||||
// Set texture parameters
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// Allocate storage for texture
|
||||
xf->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
|
||||
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
|
||||
0, GL_RGB,GL_FLOAT, nullptr);
|
||||
|
||||
//
|
||||
// SET UP GLSL SHADER
|
||||
//
|
||||
|
||||
OCIO::GpuShaderDesc shaderDesc;
|
||||
shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
|
||||
shaderDesc.setFunctionName("OCIODisplay");
|
||||
shaderDesc.setLut3DEdgeLen(OCIO_LUT3D_EDGE_SIZE);
|
||||
|
||||
//
|
||||
// COMPUTE 3D LUT
|
||||
//
|
||||
|
||||
GLfloat* ocio_lut_data = new GLfloat[OCIO_NUM_3D_ENTRIES];
|
||||
processor->getGpuLut3D(ocio_lut_data, shaderDesc);
|
||||
|
||||
// Upload LUT data to texture
|
||||
xf->glTexSubImage3D(GL_TEXTURE_3D, 0,
|
||||
0, 0, 0,
|
||||
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
|
||||
GL_RGB, GL_FLOAT, ocio_lut_data);
|
||||
|
||||
delete [] ocio_lut_data;
|
||||
|
||||
// Create OCIO shader code
|
||||
QString shader_text(processor->getGpuShaderText(shaderDesc));
|
||||
shader_text.append("\n"
|
||||
"uniform sampler3D tex2;\n"
|
||||
"\n"
|
||||
"vec4 process(vec4 col) {\n"
|
||||
" return OCIODisplay(col, tex2);\n"
|
||||
"}\n");
|
||||
|
||||
|
||||
// Get pipeline-based shader to inject OCIO shader into
|
||||
QOpenGLShaderProgramPtr shader = olive::rendering::GetPipeline(shader_text);
|
||||
|
||||
// Release LUT
|
||||
xf->glBindTexture(GL_TEXTURE_3D, 0);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint olive::rendering::OCIOBlit(QOpenGLShaderProgram *pipeline,
|
||||
GLuint lut,
|
||||
const FramebufferObject& fbo,
|
||||
|
||||
@@ -389,9 +389,8 @@ namespace olive {
|
||||
extern GLfloat blit_texcoords[];
|
||||
extern GLfloat flipped_blit_texcoords[];
|
||||
void Blit(QOpenGLShaderProgram* pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
|
||||
QOpenGLShaderProgramPtr GetPipeline(const QString &shader_code = QString());
|
||||
|
||||
#ifndef NO_OCIO
|
||||
QOpenGLShaderProgramPtr SetupOCIO(QOpenGLContext *ctx, GLuint &lut_texture, OCIO::ConstProcessorRcPtr processor);
|
||||
GLuint OCIOBlit(QOpenGLShaderProgram *pipeline,
|
||||
GLuint lut,
|
||||
const FramebufferObject& fbo,
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
#include "effects/effectloaders.h"
|
||||
#include "global/config.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "rendering/shadergenerators.h"
|
||||
|
||||
RenderThread::RenderThread() :
|
||||
gizmos(nullptr),
|
||||
@@ -117,7 +118,7 @@ void RenderThread::run() {
|
||||
olive::effects_loaded.unlock();
|
||||
blend_mode_program->link();
|
||||
|
||||
pipeline_program = olive::rendering::GetPipeline();
|
||||
pipeline_program = olive::shader::GetPipeline();
|
||||
}
|
||||
|
||||
#ifndef NO_OCIO
|
||||
@@ -193,7 +194,7 @@ void RenderThread::set_up_ocio()
|
||||
OCIO::ConstProcessorRcPtr processor = config->getProcessor(transform);
|
||||
|
||||
// Create a OCIO shader with this processor
|
||||
ocio_shader = olive::rendering::SetupOCIO(ctx, ocio_lut_texture, processor);
|
||||
ocio_shader = olive::shader::SetupOCIO(ctx, ocio_lut_texture, processor, olive::shader::NoAssociate);
|
||||
|
||||
} catch(OCIO::Exception & e) {
|
||||
qCritical() << e.what();
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "shadergenerators.h"
|
||||
|
||||
#include <QOpenGLExtraFunctions>
|
||||
|
||||
QOpenGLShaderProgramPtr olive::shader::GetPipeline(const QString& shader_code)
|
||||
{
|
||||
QOpenGLShaderProgramPtr program = std::make_shared<QOpenGLShaderProgram>();
|
||||
|
||||
// Generate vertex shader
|
||||
QString vert_shader = "#version 110\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump int;\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"uniform mat4 mvp_matrix;\n"
|
||||
"\n"
|
||||
"attribute vec4 a_position;\n"
|
||||
"attribute vec2 a_texcoord;\n"
|
||||
"\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = mvp_matrix * a_position;\n"
|
||||
" v_texcoord = a_texcoord;\n"
|
||||
"}\n";
|
||||
|
||||
// Generate fragment shader
|
||||
QString frag_shader = "#version 110\n"
|
||||
"\n"
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump int;\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"uniform sampler2D texture;\n"
|
||||
"uniform float opacity;\n"
|
||||
"uniform bool color_only;\n"
|
||||
"uniform vec4 color_only_color;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"\n";
|
||||
|
||||
// Finish the function with the main function
|
||||
|
||||
// Check if additional code was passed to this function, add it here
|
||||
if (shader_code.isEmpty()) {
|
||||
|
||||
// If not, just add a pure main() function
|
||||
|
||||
frag_shader.append("\n"
|
||||
"void main() {\n"
|
||||
" if (color_only) {\n"
|
||||
" gl_FragColor = color_only_color;"
|
||||
" } else {\n"
|
||||
" vec4 color = texture2D(texture, v_texcoord)*opacity;\n"
|
||||
" gl_FragColor = color;\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
|
||||
} else {
|
||||
|
||||
// If additional code was passed, add it and reference it in main().
|
||||
//
|
||||
// The function in the additional code is expected to be `vec4 process(vec4 color)`. The texture coordinate can be
|
||||
// acquired through `v_texcoord`.
|
||||
|
||||
frag_shader.append(shader_code);
|
||||
|
||||
frag_shader.append("\n"
|
||||
"void main() {\n"
|
||||
" vec4 color = process(texture2D(texture, v_texcoord))*opacity;\n"
|
||||
" gl_FragColor = color;\n"
|
||||
"}\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Add shaders to program
|
||||
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vert_shader);
|
||||
program->addShaderFromSourceCode(QOpenGLShader::Fragment, frag_shader);
|
||||
program->link();
|
||||
|
||||
// Set opacity default to 100%
|
||||
program->bind();
|
||||
program->setUniformValue("opacity", 1.0f);
|
||||
program->release();
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
QString olive::shader::GetAlphaDisassociateFunction(const QString &function_name)
|
||||
{
|
||||
return QString("vec4 %1(vec4 col) {\n"
|
||||
" if (col.a > 0.0) {\n"
|
||||
" return vec4(col.rgb / col.a, col.a);"
|
||||
" }\n"
|
||||
" return col;\n"
|
||||
"}\n").arg(function_name);
|
||||
}
|
||||
|
||||
QString olive::shader::GetAlphaReassociateFunction(const QString &function_name)
|
||||
{
|
||||
return QString("vec4 %1(vec4 col) {\n"
|
||||
" if (col.a > 0.0) {\n"
|
||||
" return vec4(col.rgb * col.a, col.a);"
|
||||
" }\n"
|
||||
" return col;\n"
|
||||
"}\n").arg(function_name);
|
||||
}
|
||||
|
||||
QString olive::shader::GetAlphaAssociateFunction(const QString &function_name)
|
||||
{
|
||||
return QString("vec4 %1(vec4 col) {\n"
|
||||
" return vec4(col.rgb * col.a, col.a);\n"
|
||||
"}\n").arg(function_name);
|
||||
}
|
||||
|
||||
#ifndef NO_OCIO
|
||||
|
||||
// copied from source code to OCIODisplay
|
||||
const int OCIO_LUT3D_EDGE_SIZE = 32;
|
||||
|
||||
// copied from source code to OCIODisplay, expanded from 3*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE*LUT3D_EDGE_SIZE
|
||||
const int OCIO_NUM_3D_ENTRIES = 98304;
|
||||
|
||||
QOpenGLShaderProgramPtr olive::shader::SetupOCIO(QOpenGLContext* ctx,
|
||||
GLuint& lut_texture,
|
||||
OCIO::ConstProcessorRcPtr processor,
|
||||
AlphaAssociateMode alpha_associate_mode)
|
||||
{
|
||||
|
||||
QOpenGLExtraFunctions* xf = ctx->extraFunctions();
|
||||
|
||||
// Create LUT texture
|
||||
xf->glGenTextures(1, &lut_texture);
|
||||
|
||||
// Bind LUT
|
||||
xf->glBindTexture(GL_TEXTURE_3D, lut_texture);
|
||||
|
||||
// Set texture parameters
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
xf->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
|
||||
// Allocate storage for texture
|
||||
xf->glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB,
|
||||
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
|
||||
0, GL_RGB,GL_FLOAT, nullptr);
|
||||
|
||||
//
|
||||
// SET UP GLSL SHADER
|
||||
//
|
||||
|
||||
OCIO::GpuShaderDesc shaderDesc;
|
||||
shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
|
||||
shaderDesc.setFunctionName("OCIODisplay");
|
||||
shaderDesc.setLut3DEdgeLen(OCIO_LUT3D_EDGE_SIZE);
|
||||
|
||||
//
|
||||
// COMPUTE 3D LUT
|
||||
//
|
||||
|
||||
GLfloat* ocio_lut_data = new GLfloat[OCIO_NUM_3D_ENTRIES];
|
||||
processor->getGpuLut3D(ocio_lut_data, shaderDesc);
|
||||
|
||||
// Upload LUT data to texture
|
||||
xf->glTexSubImage3D(GL_TEXTURE_3D, 0,
|
||||
0, 0, 0,
|
||||
OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE, OCIO_LUT3D_EDGE_SIZE,
|
||||
GL_RGB, GL_FLOAT, ocio_lut_data);
|
||||
|
||||
delete [] ocio_lut_data;
|
||||
|
||||
// Create OCIO shader code
|
||||
QString shader_text(processor->getGpuShaderText(shaderDesc));
|
||||
|
||||
QString ocio_call_func;
|
||||
|
||||
// Enforce alpha association
|
||||
switch (alpha_associate_mode) {
|
||||
case Associate:
|
||||
// If alpha is not already associated, we can just associate after OCIO
|
||||
|
||||
// Add associate function
|
||||
shader_text.append(GetAlphaAssociateFunction("assoc"));
|
||||
|
||||
// Make OCIO call pass through associate function
|
||||
ocio_call_func = "assoc(OCIODisplay(col, tex2));";
|
||||
break;
|
||||
case DisassociateAndReassociate:
|
||||
// If alpha is already associated, we'll need to disassociate and reassociate
|
||||
shader_text.append("\n");
|
||||
shader_text.append(GetAlphaDisassociateFunction("disassoc"));
|
||||
shader_text.append(GetAlphaReassociateFunction("reassoc"));
|
||||
|
||||
// Make OCIO call pass through disassociate and reassociate function
|
||||
ocio_call_func = "reassoc(OCIODisplay(disassoc(col), tex2));";
|
||||
break;
|
||||
default:
|
||||
// No association
|
||||
ocio_call_func = "OCIODisplay(col, tex2);";
|
||||
}
|
||||
|
||||
shader_text.append(QString("\n"
|
||||
"uniform sampler3D tex2;\n"
|
||||
"\n"
|
||||
"vec4 process(vec4 col) {\n"
|
||||
" return %1\n"
|
||||
"}\n").arg(ocio_call_func));
|
||||
|
||||
|
||||
// Get pipeline-based shader to inject OCIO shader into
|
||||
QOpenGLShaderProgramPtr shader = olive::shader::GetPipeline(shader_text);
|
||||
|
||||
// Release LUT
|
||||
xf->glBindTexture(GL_TEXTURE_3D, 0);
|
||||
|
||||
return shader;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef SHADERGENERATORS_H
|
||||
#define SHADERGENERATORS_H
|
||||
|
||||
#include "qopenglshaderprogramptr.h"
|
||||
#include "framebufferobject.h"
|
||||
|
||||
#ifndef NO_OCIO
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
#endif
|
||||
|
||||
namespace olive {
|
||||
namespace shader {
|
||||
|
||||
QOpenGLShaderProgramPtr GetPipeline(const QString &shader_code = QString());
|
||||
|
||||
#ifndef NO_OCIO
|
||||
enum AlphaAssociateMode {
|
||||
NoAssociate,
|
||||
Associate,
|
||||
DisassociateAndReassociate
|
||||
};
|
||||
|
||||
QOpenGLShaderProgramPtr SetupOCIO(QOpenGLContext *ctx,
|
||||
GLuint &lut_texture,
|
||||
OCIO::ConstProcessorRcPtr processor,
|
||||
AlphaAssociateMode alpha_associate_mode);
|
||||
#endif
|
||||
|
||||
QString GetAlphaDisassociateFunction(const QString& function_name);
|
||||
QString GetAlphaReassociateFunction(const QString& function_name);
|
||||
QString GetAlphaAssociateFunction(const QString& function_name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHADERGENERATORS_H
|
||||
+42
-29
@@ -474,7 +474,7 @@ void Clip::Open() {
|
||||
}
|
||||
|
||||
// reset variable used to optimize uploading frame data
|
||||
texture_frame = -1;
|
||||
texture_timestamp = -1;
|
||||
|
||||
if (UsesCacher()) {
|
||||
// cacher will unlock open_lock
|
||||
@@ -558,47 +558,60 @@ bool Clip::Retrieve()
|
||||
|
||||
if (frame != nullptr && cacher.queue()->contains(frame)) {
|
||||
|
||||
bool allocate_data = false;
|
||||
//if (frame->pts != texture_timestamp) {
|
||||
|
||||
bool allocate_data = false;
|
||||
|
||||
// check if the opengl texture exists yet, create it if not
|
||||
if (texture == 0) {
|
||||
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
|
||||
|
||||
// create texture object
|
||||
f->glGenTextures(1, &texture);
|
||||
// check if the opengl texture exists yet, create it if not
|
||||
if (texture == 0) {
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
// create texture object
|
||||
f->glGenTextures(1, &texture);
|
||||
|
||||
// set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// queue an allocation ahead
|
||||
allocate_data = true;
|
||||
// set texture filtering to bilinear
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
}
|
||||
// queue an allocation ahead
|
||||
allocate_data = true;
|
||||
|
||||
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
|
||||
} else {
|
||||
|
||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[0]/kRGBAComponentCount);
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
int video_width = cacher.media_width();
|
||||
int video_height = cacher.media_height();
|
||||
}
|
||||
|
||||
if (allocate_data) {
|
||||
// the raw frame size may differ from the one we're using (e.g. a lower resolution proxy), so we make sure
|
||||
// the texture is using the correct dimensions, but then treat it as if it's the original resolution in the
|
||||
// composition
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, video_width, video_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame->data[0]
|
||||
);
|
||||
} else {
|
||||
f->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width, video_height, GL_RGBA, GL_UNSIGNED_BYTE, frame->data[0]);
|
||||
}
|
||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[0]/kRGBAComponentCount);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
int video_width = cacher.media_width();
|
||||
int video_height = cacher.media_height();
|
||||
|
||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
if (allocate_data) {
|
||||
|
||||
// the raw frame size may differ from the one we're using (e.g. a lower resolution proxy), so we make sure
|
||||
// the texture is using the correct dimensions, but then treat it as if it's the original resolution in the
|
||||
// composition
|
||||
f->glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA8, video_width, video_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame->data[0]
|
||||
);
|
||||
|
||||
} else {
|
||||
|
||||
f->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, video_width, video_height, GL_RGBA, GL_UNSIGNED_BYTE, frame->data[0]);
|
||||
|
||||
}
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
texture_timestamp = frame->pts;
|
||||
|
||||
//}
|
||||
|
||||
ret = true;
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -155,7 +155,7 @@ public:
|
||||
// video playback variables
|
||||
QVector<FramebufferObject> fbo;
|
||||
GLuint texture;
|
||||
long texture_frame;
|
||||
int64_t texture_timestamp;
|
||||
|
||||
#ifndef NO_OCIO
|
||||
QOpenGLShaderProgramPtr ocio_shader;
|
||||
|
||||
+2
-1
@@ -57,6 +57,7 @@ extern "C" {
|
||||
#include "ui/timelinewidget.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "rendering/renderthread.h"
|
||||
#include "rendering/shadergenerators.h"
|
||||
#include "ui/viewerwindow.h"
|
||||
#include "ui/menu.h"
|
||||
#include "mainwindow.h"
|
||||
@@ -217,7 +218,7 @@ void ViewerWidget::initializeGL() {
|
||||
|
||||
connect(context(), SIGNAL(aboutToBeDestroyed()), this, SLOT(context_destroy()), Qt::DirectConnection);
|
||||
|
||||
pipeline_ = olive::rendering::GetPipeline();
|
||||
pipeline_ = olive::shader::GetPipeline();
|
||||
|
||||
vao_.create();
|
||||
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@
|
||||
#include <QDebug>
|
||||
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "rendering/shadergenerators.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
ViewerWindow::ViewerWindow(QWidget *parent) :
|
||||
@@ -109,7 +110,7 @@ void ViewerWindow::mouseMoveEvent(QMouseEvent *) {
|
||||
|
||||
void ViewerWindow::initializeGL()
|
||||
{
|
||||
pipeline_ = olive::rendering::GetPipeline();
|
||||
pipeline_ = olive::shader::GetPipeline();
|
||||
}
|
||||
|
||||
void ViewerWindow::paintGL() {
|
||||
|
||||
Reference in New Issue
Block a user