void GLWidgetRendererPrivate::updateShaderIfNeeded() { const VideoFormat& fmt(video_frame.format()); if (fmt != video_format) { qDebug("pixel format changed: %s => %s", qPrintable(video_format.name()), qPrintable(fmt.name())); } VideoMaterialType *newType = materialType(fmt); if (material_type == newType) return; material_type = newType; // http://forum.doom9.org/archive/index.php/t-160211.html ColorTransform::ColorSpace cs = ColorTransform::RGB; if (fmt.isRGB()) { if (fmt.isPlanar()) cs = ColorTransform::GBR; } else { if (video_frame.width() >= 1280 || video_frame.height() > 576) //values from mpv cs = ColorTransform::BT709; else cs = ColorTransform::BT601; } if (!prepareShaderProgram(fmt, cs)) { qWarning("shader program create error..."); return; } else { qDebug("shader program created!!!"); } }
void BasicUsageScene::init() { vao_.create(); vao_.bind(); prepareShaderProgram(); prepareVertexBuffers(); }
void GLWidget::initializeGL() { // get context opengl-version qDebug() << "Widget OpenGl: " << format().majorVersion() << "." << format().minorVersion(); qDebug() << "Context valid: " << context()->isValid(); qDebug() << "Really used OpenGl: " << context()->format().majorVersion() << "." << context()->format().minorVersion(); qDebug() << "OpenGl information: VENDOR: " << (const char*)glGetString(GL_VENDOR); qDebug() << " RENDERDER: " << (const char*)glGetString(GL_RENDERER); qDebug() << " VERSION: " << (const char*)glGetString(GL_VERSION); qDebug() << " GLSL VERSION: " << (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); QGLFormat glFormat = QGLWidget::format(); if ( !glFormat.sampleBuffers() ) qWarning() << "Could not enable sample buffers"; // Set the clear color to black glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // Prepare a complete shader program... if ( !prepareShaderProgram( ":/simple.vert", ":/simple.frag" ) ) return; // we need a VAO in core! GLuint VAO; PglGenVertexArrays glGenVertexArrays = (PglGenVertexArrays) context()->getProcAddress("glGenVertexArrays"); PglBindVertexArray glBindVertexArray = (PglBindVertexArray) context()->getProcAddress("glBindVertexArray"); glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); // We need us some vertex data. Start simple with a triangle ;-) float points[] = { -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f }; m_vertexBuffer.create(); m_vertexBuffer.setUsagePattern( QOpenGLBuffer::StaticDraw ); if ( !m_vertexBuffer.bind() ) { qWarning() << "Could not bind vertex buffer to the context"; return; } m_vertexBuffer.allocate( points, 3 * 4 * sizeof( float ) ); // Bind the shader program so that we can associate variables from // our application to the shaders if ( !m_shader.bind() ) { qWarning() << "Could not bind shader program to context"; return; } // Enable the "vertex" attribute to bind it to our currently bound // vertex buffer. m_shader.setAttributeBuffer( "vertex", GL_FLOAT, 0, 4 ); m_shader.enableAttributeArray( "vertex" ); }
void GLWidgetRendererPrivate::updateTexturesIfNeeded() { const VideoFormat &fmt = video_frame.format(); bool update_textures = false; if (fmt != video_format) { update_textures = true; qDebug("pixel format changed: %s => %s", qPrintable(video_format.name()), qPrintable(fmt.name())); // http://forum.doom9.org/archive/index.php/t-160211.html ColorTransform::ColorSpace cs = ColorTransform::BT601; if (video_frame.width() >= 1280 || video_frame.height() > 576) //values from mpv cs = ColorTransform::BT709; if (!prepareShaderProgram(fmt, cs)) { qWarning("shader program create error..."); return; } else { qDebug("shader program created!!!"); } } // effective size may change even if plane size not changed if (update_textures || video_frame.bytesPerLine(0) != plane0Size.width() || video_frame.height() != plane0Size.height() || (plane1_linesize > 0 && video_frame.bytesPerLine(1) != plane1_linesize)) { // no need to check hieght if plane 0 sizes are equal? update_textures = true; //qDebug("---------------------update texture: %dx%d, %s", video_frame.width(), video_frame.height(), video_frame.format().name().toUtf8().constData()); const int nb_planes = fmt.planeCount(); texture_size.resize(nb_planes); texture_upload_size.resize(nb_planes); effective_tex_width.resize(nb_planes); for (int i = 0; i < nb_planes; ++i) { qDebug("plane linesize %d: padded = %d, effective = %d", i, video_frame.bytesPerLine(i), video_frame.effectiveBytesPerLine(i)); qDebug("plane width %d: effective = %d", video_frame.planeWidth(i), video_frame.effectivePlaneWidth(i)); qDebug("planeHeight %d = %d", i, video_frame.planeHeight(i)); // we have to consider size of opengl format. set bytesPerLine here and change to width later texture_size[i] = QSize(video_frame.bytesPerLine(i), video_frame.planeHeight(i)); texture_upload_size[i] = texture_size[i]; effective_tex_width[i] = video_frame.effectiveBytesPerLine(i); //store bytes here, modify as width later // TODO: ratio count the GL_UNPACK_ALIGN? //effective_tex_width_ratio = qMin((qreal)1.0, (qreal)video_frame.effectiveBytesPerLine(i)/(qreal)video_frame.bytesPerLine(i)); } plane1_linesize = 0; if (nb_planes > 1) { texture_size[0].setWidth(texture_size[1].width() * effective_tex_width[0]/effective_tex_width[1]); // height? how about odd? plane1_linesize = video_frame.bytesPerLine(1); } effective_tex_width_ratio = (qreal)video_frame.effectiveBytesPerLine(nb_planes-1)/(qreal)video_frame.bytesPerLine(nb_planes-1); qDebug("effective_tex_width_ratio=%f", effective_tex_width_ratio); plane0Size.setWidth(video_frame.bytesPerLine(0)); plane0Size.setHeight(video_frame.height()); } if (update_textures) { initTextures(fmt); } }
void GLES2Lesson::render() { clearBuffers(); prepareShaderProgram(); setPerspective(); resetTransformMatrices(); drawGeometry(vboCubeVertexDataIndex, vboCubeVertexIndicesIndex, 36, cubeTransformMatrix ); }
void GLWidget::initializeGL() { QGLFormat glFormat = QGLWidget::format(); if ( !glFormat.sampleBuffers() ) qWarning() << "Could not enable sample buffers"; // Set the clear color to black glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // Prepare a complete shader program… if ( !prepareShaderProgram( ":/simple.vert", ":/simple.frag" ) ) return; // We need us some vertex data. Start simple with a triangle ;-) float points[] = {-0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, 1.0f}; m_vertexBuffer.create(); m_vertexBuffer.setUsagePattern( QGLBuffer::StaticDraw ); if ( !m_vertexBuffer.bind() ) { qWarning() << "Could not bind vertex buffer to the context"; return; } m_vertexBuffer.allocate( points, 3 * 4 * sizeof( float ) ); // Bind the shader program so that we can associate variables from // our application to the shaders if ( !m_shader.bind() ) { qWarning() << "Could not bind shader program to context"; return; } // Enable the "vertex" attribute to bind it to our currently bound // vertex buffer. m_shader.setAttributeBuffer( "vertex", GL_FLOAT, 0, 4 ); m_shader.enableAttributeArray( "vertex" ); /*glfuncs = m_context->versionFunctions(); if (!glfuncs) { qDebug()<<"Не поддерживается версия OpenGL этой программой."; exit(1); //Хъюстон, у нас проблема номер раз } glfuncs->initializeOpenGLFunctions(); uint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao);//*/ qDebug() << QString((const char*)glGetString(GL_VERSION)) << "\n" << QString((const char*)glGetString(GL_VENDOR))<< "\n" << QString((const char*)glGetString(GL_RENDERER));//<< "\n" << glGetString(GL_EXTENTIONS); }
ncGraphics::ncGraphics() : ibo_(QOpenGLBuffer::IndexBuffer) , vbo_(QOpenGLBuffer::VertexBuffer) { indexes_ = new GLushort[VERTEX_BUFFER_SIZE*6/4]; vertArray_ = new ncVertex[VERTEX_BUFFER_SIZE]; GLushort* iptr = indexes_; GLushort n = 0; for (int i=0; i<VERTEX_BUFFER_SIZE/4; ++i) { *iptr++ = n; *iptr++ = n+1; *iptr++ = n+2; *iptr++ = n+2; *iptr++ = n+3; *iptr++ = n; n+=4; } vao_.create(); ibo_.create(); ibo_.bind(); ibo_.setUsagePattern(QOpenGLBuffer::StaticDraw); ibo_.allocate(indexes_, sizeof(GLushort)*VERTEX_BUFFER_SIZE*6/4); ibo_.release(); vbo_.create(); vbo_.bind(); vbo_.setUsagePattern(QOpenGLBuffer::DynamicDraw); vbo_.allocate(sizeof(ncVertex)*VERTEX_BUFFER_SIZE); vbo_.release(); program_ = new QOpenGLShaderProgram(); if (!prepareShaderProgram(":/vertex.glsl", ":/fragment.glsl")) { return; } numPrim_ = 0; curPrimType_ = PRIM_QUADS; curBlendMode_ = NC_BLEND_DEFAULT; curTexture_ = 0; program_->bind(); program_->setUniformValue("texIsInvalid", true); program_->release(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
void GLES2Lesson::render() { clearBuffers(); prepareShaderProgram(); setPerspective(); resetTransformMatrices(); for (auto &star : mStars) { glUniform4fv(fragmentTintPosition, 1, &star->mColor[0]); drawGeometry(vboCubeVertexDataIndex, vboCubeVertexIndicesIndex, 4, star->mTransform ); } }
void TextRenderer::renderImmediate(int fbWidth, int fbHeight, float x, float y, const std::string &text, FontType fontType, HAlign hAlign, VAlign vAlign) { if (pixelDensity != targetPixelDensity) { loadFontAtlas(targetPixelDensity); } ASSERT(atlas, "Font atlas not loaded"); if (!atlas) { return; } ASSERT(atlas->fontRangeMap.count(fontType) != 0, "Invalid font type"); if (atlas->fontRangeMap.count(fontType) == 0) { return; } FontRange &fontRange = atlas->fontRangeMap.at(fontType); float width = 0.0f, height = fontRange.fontSize; processText(text, fontRange, atlas->bitmapSize, &width, &height, [](const stbtt_aligned_quad &q){}); float xOffset = 0.0f; if (hAlign == HAlign::Center) { xOffset = -width / 2.0f; } else if (hAlign == HAlign::Right) { xOffset = -width; } float yOffset = 0.0f; if (vAlign == VAlign::Center) { yOffset = height * 0.25f; // Approximate (offset from baseline) } else if (vAlign == VAlign::Top) { yOffset = height; } prepareShaderProgram(*gameObject, fbWidth, fbHeight); glDisable(GL_DEPTH_TEST); float absX = fbWidth * x; float absY = fbHeight * y; processText(text, fontRange, atlas->bitmapSize, &absX, &absY, [&](const stbtt_aligned_quad &q) { renderQuad(*gameObject, *mesh, q, xOffset, yOffset); }); glEnable(GL_DEPTH_TEST); }
void GLES2Lesson::render() { clearBuffers(); prepareShaderProgram(); setPerspective(); resetTransformMatrices(); if (enableBlending) { enableAlphaBlending(); } else { disableAlfaBlending(); } drawGeometry(vboCubeVertexDataIndex, vboCubeVertexIndicesIndex, 36, cubeTransformMatrix ); }
void GLES2Lesson::render() { clearBuffers(); prepareShaderProgram(); setPerspective(); drawGeometry( triangleVertices, triangleColours, triangleIndices, 3, triangleTransformMatrix ); drawGeometry( squareVertices, squareColours, squareIndices, 4, squareTransformMatrix ); }
SPtr<Texture> TextRenderer::renderToTexture(const std::string &text, Resolution *resolution, FontType fontType) { if (pixelDensity != targetPixelDensity) { loadFontAtlas(targetPixelDensity); } ASSERT(atlas, "Font atlas not loaded"); if (!atlas) { return nullptr; } ASSERT(atlas->fontRangeMap.count(fontType) != 0, "Invalid font type"); if (atlas->fontRangeMap.count(fontType) == 0) { return nullptr; } FontRange &fontRange = atlas->fontRangeMap.at(fontType); float width = 0.0f, height = fontRange.fontSize; processText(text, fontRange, atlas->bitmapSize, &width, &height, [](const stbtt_aligned_quad &q){}); prepareShaderProgram(*gameObject, width, height); framebuffer->init(glm::ceil(width), glm::ceil(height)); framebuffer->use(); glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); float x = 0.0f, y = 0.0f; processText(text, fontRange, atlas->bitmapSize, &x, &y, [&](const stbtt_aligned_quad &q) { renderQuad(*gameObject, *mesh, q, 0.0f, height * 0.75f); }); glEnable(GL_DEPTH_TEST); framebuffer->disable(); if (resolution) { resolution->width = width; resolution->height = height; } return framebuffer->getTexture(); }
void GLWidgetRendererPrivate::upload(const QRect &roi) { const VideoFormat &fmt = video_frame.format(); bool update_textures = false; if (fmt != video_format) { update_textures = true; qDebug("pixel format changed: %s => %s", qPrintable(video_format.name()), qPrintable(fmt.name())); if (!prepareShaderProgram(fmt)) { qWarning("shader program create error..."); return; } else { qDebug("shader program created!!!"); } } // effective size may change even if plane size not changed if (update_textures || video_frame.size() != plane0Size) { // update_textures = true; //qDebug("---------------------update texture: %dx%d, %s", video_frame.width(), video_frame.height(), video_frame.format().name().toUtf8().constData()); texture_size.resize(fmt.planeCount()); effective_tex_width.resize(fmt.planeCount()); for (int i = 0; i < fmt.planeCount(); ++i) { qDebug("plane linesize %d: padded = %d, effective = %d", i, video_frame.bytesPerLine(i), video_frame.effectiveBytesPerLine(i)); qDebug("plane width %d: effective = %d", video_frame.planeWidth(i), video_frame.effectivePlaneWidth(i)); qDebug("planeHeight %d = %d", i, video_frame.planeHeight(i)); // we have to consider size of opengl format. set bytesPerLine here and change to width later texture_size[i] = QSize(video_frame.bytesPerLine(i), video_frame.planeHeight(i)); effective_tex_width[i] = video_frame.effectiveBytesPerLine(i); //store bytes here, modify as width later // TODO: ratio count the GL_UNPACK_ALIGN? effective_tex_width_ratio = qMin((qreal)1.0, (qreal)video_frame.effectiveBytesPerLine(i)/(qreal)video_frame.bytesPerLine(i)); } qDebug("effective_tex_width_ratio=%f", effective_tex_width_ratio); plane0Size = video_frame.size(); } if (update_textures) { initTextures(fmt); } for (int i = 0; i < video_frame.planeCount(); ++i) { uploadPlane(i, internal_format[i], data_format[i], roi); } }
void Scene::initialize() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Récupération des fonctions d'OpenGL 3.1 m_funcs = m_context->versionFunctions<QOpenGLFunctions_3_1>(); if ( ! m_funcs ) { qFatal("Requires OpenGL >= 3.1"); exit(1); } m_funcs->initializeOpenGLFunctions(); // Charge, compile et link le Vertex et Fragment Shader prepareShaderProgram(); // Initialisation des buffers prepareVertexBuffers(); prepareIndexBuffer(); }
void GlWidget::initializeGL() { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); qglClearColor(QColor(Qt::lightGray)); if (!prepareShaderProgram( ":/vertex_shader.vert", ":/fragment_shader.frag")) { return; } vertices << QVector3D(-0.5f, -0.5f, 0.5f) << QVector3D( 0.5f, -0.5f, 0.5f) << QVector3D( 0.5f, 0.5f, 0.5f) // Front << QVector3D( 0.5f, 0.5f, 0.5f) << QVector3D(-0.5f, 0.5f, 0.5f) << QVector3D(-0.5f, -0.5f, 0.5f) << QVector3D( 0.5f, -0.5f, -0.5f) << QVector3D(-0.5f, -0.5f, -0.5f) << QVector3D(-0.5f, 0.5f, -0.5f) // Back << QVector3D(-0.5f, 0.5f, -0.5f) << QVector3D( 0.5f, 0.5f, -0.5f) << QVector3D( 0.5f, -0.5f, -0.5f) << QVector3D(-0.5f, -0.5f, -0.5f) << QVector3D(-0.5f, -0.5f, 0.5f) << QVector3D(-0.5f, 0.5f, 0.5f) // Left << QVector3D(-0.5f, 0.5f, 0.5f) << QVector3D(-0.5f, 0.5f, -0.5f) << QVector3D(-0.5f, -0.5f, -0.5f) << QVector3D( 0.5f, -0.5f, 0.5f) << QVector3D( 0.5f, -0.5f, -0.5f) << QVector3D( 0.5f, 0.5f, -0.5f) // Right << QVector3D( 0.5f, 0.5f, -0.5f) << QVector3D( 0.5f, 0.5f, 0.5f) << QVector3D( 0.5f, -0.5f, 0.5f) << QVector3D(-0.5f, 0.5f, 0.5f) << QVector3D( 0.5f, 0.5f, 0.5f) << QVector3D( 0.5f, 0.5f, -0.5f) // Top << QVector3D( 0.5f, 0.5f, -0.5f) << QVector3D(-0.5f, 0.5f, -0.5f) << QVector3D(-0.5f, 0.5f, 0.5f) << QVector3D(-0.5f, -0.5f, -0.5f) << QVector3D( 0.5f, -0.5f, -0.5f) << QVector3D( 0.5f, -0.5f, 0.5f) // Bottom << QVector3D( 0.5f, -0.5f, 0.5f) << QVector3D(-0.5f, -0.5f, 0.5f) << QVector3D(-0.5f, -0.5f, -0.5f); colors << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) // Front << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) // Back << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.5f, 0.3f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) // Left << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) // Right << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.5f, 0.3f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) // Top << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) // Bottom << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f) << QVector3D(0.1f, 0.3f, 0.5f); }
void ScreenWidget::initializeGL(){ glClearColor(1,1,1,1); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1280,0,720,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_DEPTH_TEST); //static GLfloat lightPosition[4] = { 0, 0, 10, 1.0 }; //glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); //QDir::setCurrent(QCoreApplication::applicationDirPath()); QDir absoluteDirectory = QDir::currentPath(); //qDebug() << absoluteDirectory.cdUp(); qDebug() << absoluteDirectory.cd("Shader"); QString vertexShader = absoluteDirectory.path() + "/vertexShader.vsh"; QString fragmentShader = absoluteDirectory.path() + "/fragmentShader.fsh"; qDebug() << vertexShader << " AND " << fragmentShader; QFileInfo checkFile(vertexShader); QFileInfo checkFile2(fragmentShader); if(!checkFile.exists()){ qDebug() << "Can't find the file..."; }else{ qDebug() << "The file exists!"; } if(!checkFile2.exists()){ qDebug() << "Can't find the file..."; }else{ qDebug() << "The file2 exists!"; } if (!prepareShaderProgram(vertexShader, fragmentShader)){ return; } }
void GLES2Lesson::render() { clearBuffers(); prepareShaderProgram(); setPerspective(); resetTransformMatrices(); glUniformMatrix4fv(modelMatrixAttributePosition, 1, false, &glm::mat4(1.0f)[0][0]); checkGlError("before drawing"); glEnableVertexAttribArray(vertexAttributePosition); glEnableVertexAttribArray(textureCoordinatesAttributePosition); for (auto &pair : mBatches) { glBindTexture(GL_TEXTURE_2D, pair.first); pair.second->draw(vertexAttributePosition, textureCoordinatesAttributePosition); } glDisableVertexAttribArray(vertexAttributePosition); glDisableVertexAttribArray(textureCoordinatesAttributePosition); checkGlError("after drawing"); }
void SimpleTextureScene::initialise() { m_funcs = m_context->functions(); m_funcs->initializeOpenGLFunctions(); // mplayer's output is definitely easier to parse than ffmpeg's... QProcess movieFileParameters; movieFileParameters.start("mplayer", QStringList() << "-identify" << "-vo" << "null" << "-ao" << "null" << "-frames" << "0" << "-vc" << "null" << "--" << m_movieFile, QIODevice::ReadOnly); movieFileParameters.waitForFinished(); QString mplayerOutput = QString::fromLocal8Bit(movieFileParameters.readAllStandardOutput()); QRegularExpression widthRe("^ID_VIDEO_WIDTH=(.*)", QRegularExpression::MultilineOption); QRegularExpressionMatch widthMatch = widthRe.match(mplayerOutput); if (widthMatch.hasMatch()) m_frameSize.setWidth(widthMatch.captured(1).toInt()); QRegularExpression heightRe("^ID_VIDEO_HEIGHT=(.*)", QRegularExpression::MultilineOption); QRegularExpressionMatch heightMatch = heightRe.match(mplayerOutput); if (heightMatch.hasMatch()) m_frameSize.setHeight(heightMatch.captured(1).toInt()); if (m_frameSize.width() <= 0 || m_frameSize.height() <= 0) qFatal("Cannot determine the input file frame size!"); qDebug() << "Got frame size:" << m_frameSize; // Set the clear color to black glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // Prepare a complete shader program... prepareShaderProgram( ":/shaders/simpletexture.vert", ":/shaders/simpletexture.frag" ); // Prepare the vertex, texture and index buffers prepareVertexBuffers(); // Prepare the VAO prepareVertexArrayObject(); // Prepare the texture data itself (textures and pixel unpack buffer objects) prepareTexture(); // Link texture unit 0 to the "ySampler" variable in the fragment shader m_shader.setUniformValue( "ySampler", 0 ); // Link texture unit 1 to the "uvSampler" variable in the fragment shader m_shader.setUniformValue( "uvSampler", 1 ); m_videoDecoder.start("ffmpeg", QStringList() << "-i" << m_movieFile << "-f" << "rawvideo" << "-vcodec" << "rawvideo" << "-pix_fmt" << "nv12" << "-an" << "-ss" << "180" // jump to 3m << "-", QIODevice::ReadOnly); m_videoDecoder.closeWriteChannel(); m_videoDecoder.closeReadChannel(QProcess::StandardError); }