gles transition almost complete

This commit is contained in:
itsmattkc
2019-03-17 23:49:06 +11:00
parent 05ac0314d7
commit 862996e8a3
12 changed files with 257 additions and 189 deletions
+2 -2
View File
@@ -81,7 +81,7 @@ void FramebufferObject::BindBuffer() const
if (ctx_ == nullptr) {
return;
}
ctx_->functions()->glBindFramebuffer(GL_TEXTURE_2D, buffer_);
ctx_->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buffer_);
}
void FramebufferObject::ReleaseBuffer() const
@@ -89,7 +89,7 @@ void FramebufferObject::ReleaseBuffer() const
if (ctx_ == nullptr) {
return;
}
ctx_->functions()->glBindFramebuffer(GL_TEXTURE_2D, 0);
ctx_->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void FramebufferObject::BindTexture() const
+118 -32
View File
@@ -26,6 +26,7 @@ extern "C" {
#include <QApplication>
#include <QDesktopWidget>
#include <QOpenGLExtraFunctions>
#include <QDebug>
#ifndef NO_OCIO
@@ -67,12 +68,23 @@ GLfloat olive::rendering::blit_texcoords[] = {
1.0, 1.0
};
void olive::rendering::Blit(QOpenGLShaderProgram* pipeline) {
GLfloat olive::rendering::flipped_blit_texcoords[] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
void olive::rendering::Blit(QOpenGLShaderProgram* pipeline, bool flipped, QMatrix4x4 matrix) {
QOpenGLFunctions* func = QOpenGLContext::currentContext()->functions();
pipeline->bind();
pipeline->setUniformValue("mvp_matrix", QMatrix4x4());
pipeline->setUniformValue("mvp_matrix", matrix);
pipeline->setUniformValue("texture", 0);
GLuint vertex_location = pipeline->attributeLocation("a_position");
@@ -81,21 +93,90 @@ void olive::rendering::Blit(QOpenGLShaderProgram* pipeline) {
GLuint tex_location = pipeline->attributeLocation("a_texcoord");
func->glEnableVertexAttribArray(tex_location);
func->glVertexAttribPointer(tex_location, 2, GL_FLOAT, GL_FALSE, 0, blit_texcoords);
func->glVertexAttribPointer(tex_location, 2, GL_FLOAT, GL_FALSE, 0, flipped ? flipped_blit_texcoords : blit_texcoords);
func->glDrawArrays(GL_TRIANGLES, 0, 6);
pipeline->release();
}
QOpenGLShaderProgramPtr olive::rendering::GetPipeline()
QOpenGLShaderProgramPtr olive::rendering::GetPipeline(const QString& shader_code)
{
QOpenGLShaderProgramPtr program = std::make_shared<QOpenGLShaderProgram>();
program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/internalshaders/pipeline.vert");
program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/internalshaders/pipeline.frag");
// Generate vertex shader
QString vert_shader = "#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 = "#ifdef GL_ES\n"
"precision mediump int;\n"
"precision mediump float;\n"
"#endif\n"
"\n"
"uniform sampler2D texture;\n"
"uniform float opacity;\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"
" vec4 color = texture2D(texture, v_texcoord)*opacity;\n"
" gl_FragColor = color;\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;
}
@@ -158,10 +239,10 @@ void process_effect(QOpenGLContext* ctx,
bool can_process_shaders = ((e->Flags() & Effect::ShaderFlag) && olive::CurrentRuntimeConfig.shaders_are_enabled);
if (can_process_shaders || (e->Flags() & Effect::SuperimposeFlag)) {
e->startEffect();
if (can_process_shaders && e->is_glsl_linked()) {
if (can_process_shaders && e->is_shader_linked()) {
for (int i=0;i<e->getIterations();i++) {
e->process_shader(timecode, coords, i);
composite_texture = draw_clip(ctx, pipeline, c->fbo[fbo_switcher], composite_texture, true);
composite_texture = draw_clip(ctx, pipeline, c->fbo.at(fbo_switcher), composite_texture, true);
fbo_switcher = !fbo_switcher;
}
}
@@ -179,11 +260,11 @@ void process_effect(QOpenGLContext* ctx,
} else {
// if the source texture is not already a framebuffer texture,
// we'll need to make it one before drawing a superimpose effect on it
if (composite_texture != c->fbo[0].texture() && composite_texture != c->fbo[1].texture()) {
draw_clip(ctx, pipeline, c->fbo[!fbo_switcher], composite_texture, true);
if (composite_texture != c->fbo.at(0).texture() && composite_texture != c->fbo.at(1).texture()) {
draw_clip(ctx, pipeline, c->fbo.at(!fbo_switcher), composite_texture, true);
}
composite_texture = draw_clip(ctx, pipeline, c->fbo[!fbo_switcher], superimpose_texture, false);
composite_texture = draw_clip(ctx, pipeline, c->fbo.at(!fbo_switcher), superimpose_texture, false);
}
}
e->endEffect();
@@ -205,9 +286,9 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
}
if (params.video && !params.nests.last()->fbo.isEmpty()) {
params.nests.last()->fbo[0].BindBuffer();
glClear(GL_COLOR_BUFFER_BIT);
final_fbo = params.nests.last()->fbo[0].buffer();
params.nests.last()->fbo.at(0).BindBuffer();
params.ctx->functions()->glClear(GL_COLOR_BUFFER_BIT);
final_fbo = params.nests.last()->fbo.at(0).buffer();
}
}
@@ -308,14 +389,11 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
if (params.video) {
// set default coordinates based on the sequence, with 0 in the direct center
//glPushMatrix();
//glLoadIdentity();
params.ctx->functions()->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
int half_width = s->width/2;
int half_height = s->height/2;
//glOrtho(-half_width, half_width, -half_height, half_height, -1, 10);
projection.ortho(-half_width, half_width, -half_height, half_height, -1, 1);
}
@@ -406,7 +484,7 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
// 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[fbo_switcher], textureID, true);
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);
@@ -418,15 +496,23 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
// convert to linear colorspace
if (olive::CurrentConfig.enable_color_management && params.ocio_shader != nullptr)
{
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE2);
params.ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, params.ocio_lut_texture);
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE0);
params.ocio_shader->bind();
params.ocio_shader->setUniformValue("tex1", 0);
params.ocio_shader->setUniformValue("tex2", 2);
textureID = draw_clip(params.ctx, params.pipeline, c->fbo[fbo_switcher], textureID, true);
textureID = draw_clip(params.ctx, params.ocio_shader, c->fbo.at(fbo_switcher), textureID, true);
params.ocio_shader->release();
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE2);
params.ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, 0);
params.ctx->extraFunctions()->glActiveTexture(GL_TEXTURE0);
fbo_switcher = !fbo_switcher;
}
@@ -459,7 +545,6 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
Effect* e = c->effects.at(j).get();
process_effect(params.ctx, params.pipeline, c, e, timecode, coords, textureID, fbo_switcher, params.texture_failed, kTransitionNone);
}
// if the clip has an opening transition, process that now
@@ -482,27 +567,29 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
// Check whether the parent clip is auto-scaled
// TODO redo this
/*
if (c->autoscaled()
&& (video_width != s->width
&& video_height != s->height)) {
float width_multiplier = float(s->width) / float(video_width);
float height_multiplier = float(s->height) / float(video_height);
float scale_multiplier = qMin(width_multiplier, height_multiplier);
glScalef(scale_multiplier, scale_multiplier, 1);
coords.matrix.scale(scale_multiplier, scale_multiplier);
}
*/
// Configure effect gizmos if they exist
if (params.gizmos != nullptr) {
params.gizmos->gizmo_draw(timecode, coords); // set correct gizmo coords
params.gizmos->gizmo_world_to_screen(); // convert gizmo coords to screen coords
// set correct gizmo coords at this matrix
params.gizmos->gizmo_draw(timecode, coords);
// convert gizmo coords to screen coords
params.gizmos->gizmo_world_to_screen(coords.matrix, projection);
}
if (textureID > 0) {
// set viewport to sequence size
params.ctx->functions()->glViewport(0, 0, s->width, s->height);
@@ -542,8 +629,9 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
// draw clip on screen according to gl coordinates
params.pipeline->bind();
params.pipeline->setUniformValue("mvp_matrix", projection);
params.pipeline->setUniformValue("mvp_matrix", projection * coords.matrix);
params.pipeline->setUniformValue("texture", 0);
params.pipeline->setUniformValue("opacity", coords.opacity);
GLfloat vertices[] = {
coords.vertex_top_left.x(), coords.vertex_top_left.y(), 0.0f,
@@ -576,6 +664,8 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
params.ctx->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
params.pipeline->setUniformValue("opacity", 1.0f);
params.pipeline->release();
// release final clip texture
@@ -700,10 +790,6 @@ GLuint compose_sequence(ComposeSequenceParams &params) {
params.viewer->play_wake();
}
if (params.video) {
glPopMatrix();
}
if (!params.nests.isEmpty() && !params.nests.last()->fbo.isEmpty()) {
// returns nested clip's texture
return params.nests.last()->fbo[0].texture();
+3 -2
View File
@@ -414,8 +414,9 @@ namespace olive {
namespace rendering {
extern GLfloat blit_vertices[];
extern GLfloat blit_texcoords[];
void Blit(QOpenGLShaderProgram* pipeline);
QOpenGLShaderProgramPtr GetPipeline();
extern GLfloat flipped_blit_texcoords[];
void Blit(QOpenGLShaderProgram* pipeline, bool flipped = false, QMatrix4x4 matrix = QMatrix4x4());
QOpenGLShaderProgramPtr GetPipeline(const QString &shader_code = QString());
}
}
+43 -48
View File
@@ -149,47 +149,26 @@ const GLuint &RenderThread::get_texture()
return front_buffer_switcher ? front_buffer_2.texture() : front_buffer_1.texture();
}
const char * g_fragShaderText = ""
"\n"
"uniform sampler2D tex1;\n"
"uniform sampler3D tex2;\n"
"\n"
"void main()\n"
"{\n"
" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n"
" gl_FragColor = OCIODisplay(col, tex2);\n"
"}\n";
#ifndef NO_OCIO
void RenderThread::set_up_ocio()
{
//
// SETUP LUT TEXTURE
//
// Create LUT texture
ctx->functions()->glGenTextures(1, &ocio_lut_texture);
ctx->extraFunctions()->glGenTextures(1, &ocio_lut_texture);
// Bind texture to GL_TEXTURE_3D and GL_TEXTURE2
ctx->functions()->glActiveTexture(GL_TEXTURE2);
ctx->functions()->glBindTexture(GL_TEXTURE_3D, ocio_lut_texture);
// Bind LUT
ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, ocio_lut_texture);
// Set texture parameters
ctx->functions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ctx->functions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ctx->functions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
ctx->functions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
ctx->functions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
ctx->extraFunctions()->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// Allocate storage for texture
ctx->extraFunctions()->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, ocio_lut_data);
//
// SET UP OCIO DISPLAY
//
0, GL_RGB,GL_FLOAT, nullptr);
OCIO::ConstConfigRcPtr config;
@@ -208,30 +187,32 @@ void RenderThread::set_up_ocio()
const char* display = config->getDefaultDisplay();
OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
transform->setInputColorSpaceName(OCIO::ROLE_SCENE_LINEAR);
transform->setDisplay(display);
transform->setView(config->getDefaultView(display));
//
// GET OCIO PROCESSOR
//
OCIO::ConstProcessorRcPtr processor;
OCIO::GpuShaderDesc shaderDesc;
// Get processor for this configuration
try {
processor = OCIO::GetCurrentConfig()->getProcessor(transform);
processor = config->getProcessor(transform);
} catch(OCIO::Exception & e) {
qCritical() << e.what();
ctx->functions()->glActiveTexture(GL_TEXTURE0);
return;
}
//
// SET UP GLSL SHADER
//
OCIO::GpuShaderDesc shaderDesc;
shaderDesc.setLanguage(OCIO::GPU_LANGUAGE_GLSL_1_0);
shaderDesc.setFunctionName("OCIODisplay");
shaderDesc.setLut3DEdgeLen(OCIO_LUT3D_EDGE_SIZE);
@@ -242,22 +223,31 @@ void RenderThread::set_up_ocio()
processor->getGpuLut3D(ocio_lut_data, shaderDesc);
ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, ocio_lut_texture);
// Upload LUT data to texture
ctx->extraFunctions()->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);
GL_RGB, GL_FLOAT, ocio_lut_data);
QString shader_text = processor->getGpuShaderText(shaderDesc);
shader_text.append("\n");
shader_text.append(g_fragShaderText);
ocio_shader = std::make_shared<QOpenGLShaderProgram>();
ocio_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, shader_text);
ocio_shader->link();
// 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
ocio_shader = olive::rendering::GetPipeline(shader_text);
// Release LUT
ctx->extraFunctions()->glBindTexture(GL_TEXTURE_3D, 0);
// Reset active texture to 0 for the rest of the pipeline
ctx->functions()->glActiveTexture(GL_TEXTURE0);
}
void RenderThread::destroy_ocio()
@@ -284,6 +274,7 @@ void RenderThread::paint() {
params.pipeline = pipeline_program.get();
#ifndef NO_OCIO
params.ocio_shader = ocio_shader.get();
params.ocio_lut_texture = ocio_lut_texture;
#endif
params.backend_buffer1 = back_buffer_1.buffer();
params.backend_buffer2 = back_buffer_2.buffer();
@@ -299,6 +290,8 @@ void RenderThread::paint() {
QMutex& active_mutex = front_buffer_switcher ? front_mutex1 : front_mutex2;
active_mutex.lock();
ctx->functions()->glEnable(GL_BLEND);
// bind framebuffer for drawing
ctx->functions()->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, params.main_buffer);
@@ -310,6 +303,8 @@ void RenderThread::paint() {
// flush changes
ctx->functions()->glFinish();
ctx->functions()->glDisable(GL_BLEND);
texture_failed = params.texture_failed;
active_mutex.unlock();
@@ -321,7 +316,7 @@ void RenderThread::paint() {
} else {
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, params.main_buffer);
QImage img(tex_width, tex_height, QImage::Format_RGBA8888);
glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
ctx->functions()->glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
img.save(save_fn);
ctx->functions()->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
save_fn = "";