gles transition almost complete
This commit is contained in:
+7
-15
@@ -735,12 +735,12 @@ void Effect::open() {
|
||||
} else {
|
||||
shader_program_ = std::make_shared<QOpenGLShaderProgram>();
|
||||
validate_meta_path();
|
||||
bool glsl_compiled = true;
|
||||
bool shader_compiled = true;
|
||||
if (!shader_vert_path_.isEmpty()) {
|
||||
if (shader_program_->addShaderFromSourceFile(QOpenGLShader::Vertex, meta->path + "/" + shader_vert_path_)) {
|
||||
qInfo() << "Vertex shader added successfully";
|
||||
} else {
|
||||
glsl_compiled = false;
|
||||
shader_compiled = false;
|
||||
qWarning() << "Vertex shader could not be added";
|
||||
}
|
||||
}
|
||||
@@ -748,11 +748,11 @@ void Effect::open() {
|
||||
if (shader_program_->addShaderFromSourceFile(QOpenGLShader::Fragment, meta->path + "/" + shader_frag_path_)) {
|
||||
qInfo() << "Fragment shader added successfully";
|
||||
} else {
|
||||
glsl_compiled = false;
|
||||
shader_compiled = false;
|
||||
qWarning() << "Fragment shader could not be added";
|
||||
}
|
||||
}
|
||||
if (glsl_compiled) {
|
||||
if (shader_compiled) {
|
||||
if (shader_program_->link()) {
|
||||
qInfo() << "Shader program linked successfully";
|
||||
} else {
|
||||
@@ -775,7 +775,7 @@ void Effect::close() {
|
||||
isOpen = false;
|
||||
}
|
||||
|
||||
bool Effect::is_glsl_linked() {
|
||||
bool Effect::is_shader_linked() {
|
||||
return shader_program_ != nullptr && shader_program_->isLinked();
|
||||
}
|
||||
|
||||
@@ -983,20 +983,12 @@ void Effect::gizmo_move(EffectGizmo* gizmo, int x_movement, int y_movement, doub
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::gizmo_world_to_screen() {
|
||||
GLfloat view_val[16];
|
||||
GLfloat projection_val[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, view_val);
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, projection_val);
|
||||
|
||||
QMatrix4x4 view_matrix(view_val);
|
||||
QMatrix4x4 projection_matrix(projection_val);
|
||||
|
||||
void Effect::gizmo_world_to_screen(const QMatrix4x4& matrix, const QMatrix4x4& projection) {
|
||||
for (int i=0;i<gizmos.size();i++) {
|
||||
EffectGizmo* g = gizmos.at(i);
|
||||
|
||||
for (int j=0;j<g->get_point_count();j++) {
|
||||
QVector4D screen_pos = QVector4D(g->world_pos[j].x(), g->world_pos[j].y(), 0, 1.0) * (view_matrix * projection_matrix);
|
||||
QVector4D screen_pos = QVector4D(g->world_pos[j].x(), g->world_pos[j].y(), 0, 1.0) * (matrix * projection);
|
||||
|
||||
int adjusted_sx1 = qRound(((screen_pos.x()*0.5f)+0.5f)*parent_clip->sequence->width);
|
||||
int adjusted_sy1 = qRound((1.0f-((screen_pos.y()*0.5f)+0.5f))*parent_clip->sequence->height);
|
||||
|
||||
+2
-2
@@ -172,7 +172,7 @@ public:
|
||||
bool is_open();
|
||||
void open();
|
||||
void close();
|
||||
bool is_glsl_linked();
|
||||
bool is_shader_linked();
|
||||
virtual void startEffect();
|
||||
virtual void endEffect();
|
||||
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
|
||||
virtual void gizmo_draw(double timecode, GLTextureCoords& coords);
|
||||
void gizmo_move(EffectGizmo* sender, int x_movement, int y_movement, double timecode, bool done);
|
||||
void gizmo_world_to_screen();
|
||||
void gizmo_world_to_screen(const QMatrix4x4 &matrix, const QMatrix4x4 &projection);
|
||||
bool are_gizmos_enabled();
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -4,8 +4,10 @@ precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform sampler2D texture;
|
||||
uniform float opacity;
|
||||
varying vec2 v_texcoord;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(texture, v_texcoord);
|
||||
vec4 color = texture2D(texture, v_texcoord)*opacity;
|
||||
gl_FragColor = color;
|
||||
}
|
||||
@@ -78,10 +78,7 @@ void ShakeEffect::process_coords(double timecode, GLTextureCoords& coords, int)
|
||||
yoff *= multiplier;
|
||||
rotoff *= rotmult;
|
||||
|
||||
coords.vertex_top_left += QVector3D(xoff, yoff, 0.0);
|
||||
coords.vertex_top_right += QVector3D(xoff, yoff, 0.0);
|
||||
coords.vertex_bottom_left += QVector3D(xoff, yoff, 0.0);
|
||||
coords.vertex_bottom_right += QVector3D(xoff, yoff, 0.0);
|
||||
coords.matrix.translate(xoff, yoff, 0.0);
|
||||
|
||||
glRotatef(rotoff, 0, 0, 1);
|
||||
coords.matrix.rotate(QQuaternion::fromEulerAngles(0.0f, 0.0f, rotoff));
|
||||
}
|
||||
|
||||
@@ -190,9 +190,9 @@ void TransformEffect::toggle_uniform_scale(bool enabled) {
|
||||
|
||||
void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, int) {
|
||||
// position
|
||||
glTranslated(position_x->GetDoubleAt(timecode)-(parent_clip->sequence->width/2),
|
||||
position_y->GetDoubleAt(timecode)-(parent_clip->sequence->height/2),
|
||||
0);
|
||||
coords.matrix.translate(position_x->GetDoubleAt(timecode)-(parent_clip->sequence->width/2),
|
||||
position_y->GetDoubleAt(timecode)-(parent_clip->sequence->height/2),
|
||||
0);
|
||||
|
||||
// anchor point
|
||||
int anchor_x_offset = qRound(anchor_x_box->GetDoubleAt(timecode));
|
||||
@@ -204,12 +204,12 @@ void TransformEffect::process_coords(double timecode, GLTextureCoords& coords, i
|
||||
coords.vertex_bottom_right -= QVector3D(anchor_x_offset, anchor_y_offset, 0.0f);
|
||||
|
||||
// rotation
|
||||
glRotated(rotation->GetDoubleAt(timecode), 0, 0, 1);
|
||||
coords.matrix.rotate(QQuaternion::fromEulerAngles(0, 0, rotation->GetDoubleAt(timecode)));
|
||||
|
||||
// scale
|
||||
double sx = scale_x->GetDoubleAt(timecode)*0.01;
|
||||
double sy = (uniform_scale_field->GetBoolAt(timecode)) ? sx : scale_y->GetDoubleAt(timecode)*0.01;
|
||||
glScaled(sx, sy, 1);
|
||||
coords.matrix.scale(sx, sy);
|
||||
|
||||
// blend mode
|
||||
coords.blendmode = blend_mode_box->GetValueAt(timecode).toInt();
|
||||
|
||||
@@ -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
@@ -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 ¶ms) {
|
||||
}
|
||||
|
||||
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 ¶ms) {
|
||||
|
||||
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 ¶ms) {
|
||||
// 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 ¶ms) {
|
||||
// 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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
|
||||
|
||||
// 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 ¶ms) {
|
||||
// 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 ¶ms) {
|
||||
|
||||
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 ¶ms) {
|
||||
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();
|
||||
|
||||
@@ -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
@@ -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 = "";
|
||||
|
||||
+6
-6
@@ -567,20 +567,20 @@ void ViewerWidget::paintGL() {
|
||||
// draw texture from render thread
|
||||
|
||||
|
||||
// TODO fix zooming
|
||||
double zoom_factor = container->zoom/(double(width())/double(viewer->seq->width));
|
||||
double zoom_size = (zoom_factor*2.0) - 2.0;
|
||||
double zoom_left = -zoom_size*x_scroll - 1.0;
|
||||
double zoom_right = zoom_size*(1.0-x_scroll) + 1.0;
|
||||
double zoom_bottom = -zoom_size*(1.0-y_scroll) - 1.0;
|
||||
double zoom_top = zoom_size*(y_scroll) + 1.0;
|
||||
|
||||
QMatrix4x4 matrix;
|
||||
if (zoom_factor > 1.0) {
|
||||
matrix.translate((-(x_scroll-0.5))*zoom_size, (y_scroll-0.5)*zoom_size);
|
||||
matrix.scale(zoom_factor);
|
||||
}
|
||||
|
||||
f->glViewport(0, 0, width(), height());
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
olive::rendering::Blit(pipeline_.get());
|
||||
olive::rendering::Blit(pipeline_.get(), true, matrix);
|
||||
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
+47
-53
@@ -28,27 +28,26 @@
|
||||
#include <QShortcut>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
|
||||
ViewerWindow::ViewerWindow(QWidget *parent) :
|
||||
QOpenGLWidget(parent, Qt::Window),
|
||||
texture(0),
|
||||
mutex(nullptr),
|
||||
show_fullscreen_msg(false)
|
||||
texture_(0),
|
||||
mutex_(nullptr),
|
||||
show_fullscreen_msg_(false)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
|
||||
fullscreen_msg_timer.setInterval(2000);
|
||||
connect(&fullscreen_msg_timer, SIGNAL(timeout()), this, SLOT(fullscreen_msg_timeout()));
|
||||
fullscreen_msg_timer_.setInterval(2000);
|
||||
connect(&fullscreen_msg_timer_, SIGNAL(timeout()), this, SLOT(fullscreen_msg_timeout()));
|
||||
}
|
||||
|
||||
void ViewerWindow::set_texture(GLuint t, double iar, QMutex* imutex) {
|
||||
texture = t;
|
||||
ar = iar;
|
||||
mutex = imutex;
|
||||
texture_ = t;
|
||||
ar_ = iar;
|
||||
mutex_ = imutex;
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -59,71 +58,66 @@ void ViewerWindow::keyPressEvent(QKeyEvent *e) {
|
||||
}
|
||||
|
||||
void ViewerWindow::mousePressEvent(QMouseEvent *e) {
|
||||
if (show_fullscreen_msg && fullscreen_msg_rect.contains(e->pos())) {
|
||||
if (show_fullscreen_msg_ && fullscreen_msg_rect_.contains(e->pos())) {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWindow::mouseMoveEvent(QMouseEvent *) {
|
||||
fullscreen_msg_timer.start();
|
||||
if (!show_fullscreen_msg) {
|
||||
show_fullscreen_msg = true;
|
||||
fullscreen_msg_timer_.start();
|
||||
if (!show_fullscreen_msg_) {
|
||||
show_fullscreen_msg_ = true;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWindow::initializeGL()
|
||||
{
|
||||
pipeline_ = olive::rendering::GetPipeline();
|
||||
}
|
||||
|
||||
void ViewerWindow::paintGL() {
|
||||
if (texture > 0) {
|
||||
if (mutex != nullptr) mutex->lock();
|
||||
if (texture_ > 0) {
|
||||
if (mutex_ != nullptr) mutex_->lock();
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
QOpenGLFunctions* f = context()->functions();
|
||||
//QOpenGLExtraFunctions* xf = context()->extraFunctions();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
makeCurrent();
|
||||
|
||||
glLoadIdentity();
|
||||
glOrtho(0, 1, 0, 1, -1, 1);
|
||||
// clear to solid black
|
||||
f->glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
f->glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
double top = 0;
|
||||
double left = 0;
|
||||
double right = 1;
|
||||
double bottom = 1;
|
||||
// draw texture from render thread
|
||||
|
||||
double widget_ar = double(width()) / double(height());
|
||||
|
||||
if (widget_ar > ar) {
|
||||
double width = 1.0 * ar / widget_ar;
|
||||
left = (1.0 - width)*0.5;
|
||||
right = left + width;
|
||||
QMatrix4x4 matrix;
|
||||
|
||||
double widget_ar = (double(width()) / double(height()));
|
||||
if (widget_ar > ar_) {
|
||||
matrix.scale(ar_ / widget_ar, 1.0);
|
||||
} else {
|
||||
double height = 1.0 / ar * widget_ar;
|
||||
top = (1.0 - height)*0.5;
|
||||
bottom = top + height;
|
||||
matrix.scale(1.0f, widget_ar / ar_);
|
||||
}
|
||||
|
||||
glVertex2d(left, top);
|
||||
glTexCoord2d(0, 0);
|
||||
glVertex2d(left, bottom);
|
||||
glTexCoord2d(1, 0);
|
||||
glVertex2d(right, bottom);
|
||||
glTexCoord2d(1, 1);
|
||||
glVertex2d(right, top);
|
||||
glTexCoord2d(0, 1);
|
||||
|
||||
glEnd();
|
||||
f->glViewport(0, 0, width(), height());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
f->glBindTexture(GL_TEXTURE_2D, texture_);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
olive::rendering::Blit(pipeline_.get(), true, matrix);
|
||||
|
||||
if (mutex != nullptr) mutex->unlock();
|
||||
f->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
|
||||
|
||||
if (mutex_ != nullptr) mutex_->unlock();
|
||||
}
|
||||
|
||||
if (show_fullscreen_msg) {
|
||||
if (show_fullscreen_msg_) {
|
||||
QPainter p(this);
|
||||
|
||||
QFont f = p.font();
|
||||
@@ -143,21 +137,21 @@ void ViewerWindow::paintGL() {
|
||||
|
||||
int rect_padding = 8;
|
||||
|
||||
fullscreen_msg_rect = QRect(text_x-rect_padding,
|
||||
fullscreen_msg_rect_ = QRect(text_x-rect_padding,
|
||||
fm.height()-rect_padding,
|
||||
text_width+rect_padding+rect_padding,
|
||||
fm.height()+rect_padding+rect_padding);
|
||||
|
||||
p.drawRect(fullscreen_msg_rect);
|
||||
p.drawRect(fullscreen_msg_rect_);
|
||||
|
||||
p.drawText(text_x, text_y, fs_str);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWindow::fullscreen_msg_timeout() {
|
||||
fullscreen_msg_timer.stop();
|
||||
if (show_fullscreen_msg) {
|
||||
show_fullscreen_msg = false;
|
||||
fullscreen_msg_timer_.stop();
|
||||
if (show_fullscreen_msg_) {
|
||||
show_fullscreen_msg_ = false;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
+19
-18
@@ -23,33 +23,34 @@
|
||||
|
||||
#include <QOpenGLWidget>
|
||||
#include <QTimer>
|
||||
#include <QMutex>
|
||||
|
||||
class QMutex;
|
||||
class QMenu;
|
||||
class QShortcut;
|
||||
#include "rendering/qopenglshaderprogramptr.h"
|
||||
|
||||
class ViewerWindow : public QOpenGLWidget {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWindow(QWidget *parent);
|
||||
void set_texture(GLuint t, double iar, QMutex *imutex);
|
||||
ViewerWindow(QWidget *parent);
|
||||
void set_texture(GLuint t, double iar, QMutex *imutex);
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent*) override;
|
||||
virtual void mousePressEvent(QMouseEvent*) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent*) override;
|
||||
virtual void keyPressEvent(QKeyEvent*) override;
|
||||
virtual void mousePressEvent(QMouseEvent*) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent*) override;
|
||||
|
||||
virtual void paintGL() override;
|
||||
virtual void initializeGL() override;
|
||||
virtual void paintGL() override;
|
||||
private:
|
||||
GLuint texture;
|
||||
double ar;
|
||||
QMutex* mutex;
|
||||
GLuint texture_;
|
||||
double ar_;
|
||||
QMutex* mutex_;
|
||||
QOpenGLShaderProgramPtr pipeline_;
|
||||
|
||||
// exit full screen message
|
||||
QTimer fullscreen_msg_timer;
|
||||
bool show_fullscreen_msg;
|
||||
QRect fullscreen_msg_rect;
|
||||
// exit full screen message
|
||||
QTimer fullscreen_msg_timer_;
|
||||
bool show_fullscreen_msg_;
|
||||
QRect fullscreen_msg_rect_;
|
||||
private slots:
|
||||
void fullscreen_msg_timeout();
|
||||
void fullscreen_msg_timeout();
|
||||
};
|
||||
|
||||
#endif // VIEWERWINDOW_H
|
||||
|
||||
Reference in New Issue
Block a user