Example #1
0
void Refraction::draw()
{
    _arrayBuf.bind();

    QOpenGLShaderProgram *program = GL::refraction();
    program->bind();
    int vertexLocation = program->attributeLocation("a_position");
    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(VertexData));
    int fragmentLocation = program->attributeLocation("a_texcoord");
    program->enableAttributeArray(fragmentLocation);
    program->setAttributeBuffer(fragmentLocation, GL_FLOAT, sizeof(QVector3D), 2, sizeof(VertexData));

    prepareMatrix();
    program->setUniformValue("mvp_matrix", GL::projection() * model);
    program->setUniformValue("refraction", 0);
    _texture->bind(0);



    program->setUniformValue("background", 1);
    GameObjects::background()->bind(1);
    program->setUniformValue("position", _position);
    program->setUniformValue("radius", _radius);

    glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, 0);
}
    void exposeEvent(QExposeEvent *)
    {
        if (!isExposed())
            return;

        if (!gl) {
            gl = new QOpenGLContext();
            gl->setFormat(requestedFormat());
            gl->create();
        }

        gl->makeCurrent(this);

        QOpenGLShaderProgram prog;
        prog.addShaderFromSourceCode(QOpenGLShader::Vertex,
                                     "attribute highp vec4 a_Pos;"
                                     "attribute lowp vec4 a_Color;"
                                     "varying lowp vec4 v_Color;"
                                     "void main() {"
                                     "    gl_Position = a_Pos;"
                                     "    v_Color = a_Color;"
                                     "}");
        prog.addShaderFromSourceCode(QOpenGLShader::Fragment,
                                     "varying lowp vec4 v_Color;"
                                     "void main() {"
                                     "    gl_FragColor = v_Color;"
                                     "}");
        prog.bind();

        glClearColor(0, 0, 0, 1);
        glClear(GL_COLOR_BUFFER_BIT);
        glViewport(0, 0, width(), height());

        prog.enableAttributeArray("a_Pos");
        prog.enableAttributeArray("a_Color");

        float coords[] = { -0.7f,  0.7f,
                           0.8f,  0.8f,
                           -0.8f, -0.8f,
                           0.7f, -0.7f
                         };
        float colors[] = { 1, 0, 0, 1,
                           0, 1, 0, 1,
                           0, 0, 1, 1,
                           0, 0, 0, 0
                         };

        prog.setAttributeArray("a_Pos", GL_FLOAT, coords, 2, 0);
        prog.setAttributeArray("a_Color", GL_FLOAT, colors, 4, 0);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        prog.disableAttributeArray("a_Pos");
        prog.disableAttributeArray("a_Color");

        gl->swapBuffers(this);
    }
Example #3
0
void
Scene_polylines_item::initializeBuffers(CGAL::Three::Viewer_interface *viewer = 0) const
{
    QOpenGLShaderProgram *program;
   //vao for the lines
    {
        program = getShaderProgram(PROGRAM_NO_SELECTION, viewer);
        program->bind();

        vaos[Edges]->bind();
        buffers[Edges_Vertices].bind();
        buffers[Edges_Vertices].allocate(positions_lines.data(),
                            static_cast<int>(positions_lines.size()*sizeof(float)));
        program->enableAttributeArray("vertex");
        program->setAttributeBuffer("vertex",GL_FLOAT,0,4);
        buffers[Edges_Vertices].release();
        vaos[Edges]->release();
        program->release();

        nb_lines = positions_lines.size();
        positions_lines.clear();
        positions_lines.swap(positions_lines);
    }
   are_buffers_filled = true;
}
Example #4
0
void
Scene_polylines_item_private::initializeBuffers(CGAL::Three::Viewer_interface *viewer = 0) const
{
  float lineWidth[2];
  viewer->glGetFloatv(GL_LINE_WIDTH_RANGE, lineWidth);
  line_Slider->setMaximum(lineWidth[1]);
    QOpenGLShaderProgram *program;
   //vao for the lines
    {
        program = item->getShaderProgram(Scene_polylines_item::PROGRAM_NO_SELECTION, viewer);
        program->bind();

        item->vaos[Edges]->bind();
        item->buffers[Edges_Vertices].bind();
        item->buffers[Edges_Vertices].allocate(positions_lines.data(),
                            static_cast<int>(positions_lines.size()*sizeof(float)));
        program->enableAttributeArray("vertex");
        program->setAttributeBuffer("vertex",GL_FLOAT,0,4);
        item->buffers[Edges_Vertices].release();
        item->vaos[Edges]->release();
        program->release();

        nb_lines = positions_lines.size();
        positions_lines.clear();
        positions_lines.swap(positions_lines);
    }
    item->are_buffers_filled = true;
}
Example #5
0
GraphicsLayer21::GraphicsLayer21(QOpenGLVertexArrayObject* vertex_array) :
	m_program(nullptr),
	m_vertex_array(vertex_array)
{
	initializeOpenGLFunctions();

	AppearanceDialog::setBevelsEnabled(true);

	glDisable(GL_BLEND);

	// Enable OpenGL features
	glEnable(GL_CULL_FACE);
	glEnable(GL_DEPTH_TEST);

	// Set OpenGL parameters
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDepthFunc(GL_LEQUAL);
	glFrontFace(GL_CCW);

	// Create vertex buffer object
	m_vertex_buffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
	m_vertex_buffer->setUsagePattern(QOpenGLBuffer::DynamicDraw);
	m_vertex_buffer->create();
	m_vertex_buffer->bind();

	// Load shaders
	QOpenGLShaderProgram* program = loadProgram(0);
	program->setAttributeBuffer(Position, GL_FLOAT, offsetof(Vertex, x), 3, sizeof(Vertex));
	program->enableAttributeArray(Position);

	program = loadProgram(1);
	program->setAttributeBuffer(TexCoord0, GL_FLOAT, offsetof(Vertex, s), 2, sizeof(Vertex));
	program->setAttributeBuffer(Position, GL_FLOAT, offsetof(Vertex, x), 3, sizeof(Vertex));
	program->enableAttributeArray(Position);
	program->setUniformValue("texture0", GLuint(0));

	program = loadProgram(2);
	program->setAttributeBuffer(TexCoord1, GL_FLOAT, offsetof(Vertex, s2), 2, sizeof(Vertex));
	program->setAttributeBuffer(TexCoord0, GL_FLOAT, offsetof(Vertex, s), 2, sizeof(Vertex));
	program->setAttributeBuffer(Position, GL_FLOAT, offsetof(Vertex, x), 3, sizeof(Vertex));
	program->enableAttributeArray(Position);
	program->setUniformValue("texture0", GLuint(0));
	program->setUniformValue("texture1", GLuint(1));
}
/******************************************************************************
* Renders a 2d polyline in the viewport.
******************************************************************************/
void ViewportSceneRenderer::render2DPolyline(const Point2* points, int count, const ColorA& color, bool closed)
{
	OVITO_STATIC_ASSERT(sizeof(points[0]) == 2*sizeof(GLfloat));

	// Load OpenGL shader.
	QOpenGLShaderProgram* shader = loadShaderProgram("line", ":/core/glsl/lines/line.vs", ":/core/glsl/lines/line.fs");
	if(!shader->bind())
		throw Exception(tr("Failed to bind OpenGL shader."));

	bool wasDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
	glDisable(GL_DEPTH_TEST);

	GLint vc[4];
	glGetIntegerv(GL_VIEWPORT, vc);
	QMatrix4x4 tm;
	tm.ortho(vc[0], vc[0] + vc[2], vc[1] + vc[3], vc[1], -1, 1);
	OVITO_CHECK_OPENGL(shader->setUniformValue("modelview_projection_matrix", tm));

	QOpenGLBuffer vertexBuffer;
	if(glformat().majorVersion() >= 3) {
		if(!vertexBuffer.create())
			throw Exception(tr("Failed to create OpenGL vertex buffer."));
		if(!vertexBuffer.bind())
				throw Exception(tr("Failed to bind OpenGL vertex buffer."));
		vertexBuffer.allocate(points, 2 * sizeof(GLfloat) * count);
		OVITO_CHECK_OPENGL(shader->enableAttributeArray("position"));
		OVITO_CHECK_OPENGL(shader->setAttributeBuffer("position", GL_FLOAT, 0, 2));
		vertexBuffer.release();
	}
	else {
		OVITO_CHECK_OPENGL(glEnableClientState(GL_VERTEX_ARRAY));
		OVITO_CHECK_OPENGL(glVertexPointer(2, GL_FLOAT, 0, points));
	}

	if(glformat().majorVersion() >= 3) {
		OVITO_CHECK_OPENGL(shader->disableAttributeArray("color"));
		OVITO_CHECK_OPENGL(shader->setAttributeValue("color", color.r(), color.g(), color.b(), color.a()));
	}
	else {
		OVITO_CHECK_OPENGL(glColor4(color));
	}

	OVITO_CHECK_OPENGL(glDrawArrays(closed ? GL_LINE_LOOP : GL_LINE_STRIP, 0, count));

	if(glformat().majorVersion() >= 3) {
		shader->disableAttributeArray("position");
	}
	else {
		OVITO_CHECK_OPENGL(glDisableClientState(GL_VERTEX_ARRAY));
	}
	shader->release();
	if(wasDepthTestEnabled) glEnable(GL_DEPTH_TEST);
}
Example #7
0
void Painter::renderScene(const Camera &camera)
{
    m_envMap->paint(camera);

    /* Paint gems */
    QOpenGLShaderProgram *gemProgram = (*m_shaderPrograms)[ShaderPrograms::GemProgram];
    gemProgram->bind();

    gemProgram->enableAttributeArray(0);
    gemProgram->enableAttributeArray(1);

    gemProgram->setUniformValue("envmap", 0);
    gemProgram->setUniformValue("gemStructureMap", 1);
    gemProgram->setUniformValue("rainbowMap", 2);
    gemProgram->setUniformValue("eye", camera.eye());
    gemProgram->setUniformValue("viewProjection", camera.viewProjection());
    m_gl->glActiveTexture(GL_TEXTURE0);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, m_envMap->cubeMapTexture());
    m_gl->glActiveTexture(GL_TEXTURE1);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, m_gemStructureMap->cubeMapTexture());
    m_gl->glActiveTexture(GL_TEXTURE2);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, m_rainbowMap->cubeMapTexture());

    QHash<ShaderPrograms, QOpenGLShaderProgram*> shaderPrograms;
    shaderPrograms.insert(ShaderPrograms::GemProgram, m_shaderPrograms->value(ShaderPrograms::GemProgram));
    shaderPrograms.insert(ShaderPrograms::LighRayProgram, m_shaderPrograms->value(ShaderPrograms::LighRayProgram));

    m_sceneRenderer->paint(*m_gl, camera.viewProjection(), shaderPrograms);

    m_gl->glActiveTexture(GL_TEXTURE0);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    m_gl->glActiveTexture(GL_TEXTURE1);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    m_gl->glActiveTexture(GL_TEXTURE2);
    m_gl->glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    m_gl->glBindTexture(GL_TEXTURE_2D, 0);

    gemProgram->disableAttributeArray(0);
    gemProgram->disableAttributeArray(1);

    gemProgram->release();
}
Example #8
0
void csSurface::draw(QOpenGLShaderProgram& program)
{
  if( _initRequired ) {
    initialize();
  }

  if( _meshInfo.isEmpty() ) {
    return;
  }

  glDisable(GL_CULL_FACE);

  program.setUniformValue("cs_Model", _model);
  program.setUniformValue("cs_zMin", _meshInfo.zMin());
  program.setUniformValue("cs_zInterval", _meshInfo.zInterval());
  program.setUniformValue("cs_ColorMap", TMU_COLORMAP);

  _surface->bind();
  const int vertexLoc = program.attributeLocation("cs_Vertex");
  program.enableAttributeArray(vertexLoc);
  program.setAttributeBuffer(vertexLoc, GL_FLOAT, 0, 3);

  _colorTexture->bind(TMU_COLORMAP, QOpenGLTexture::ResetTextureUnit);

  _strip->bind();
  const int numStrips       =   _meshInfo.rowCount()   -1;
  const int numVertPerStrip = 2*_meshInfo.columnCount();
  for(int y = 0; y < numStrips; y++) {
    const GLuint  offset  = sizeof(GLuint)*y*numVertPerStrip;
    const GLvoid *indices = (GLvoid*)offset;
    glDrawElements(GL_TRIANGLE_STRIP, numVertPerStrip, GL_UNSIGNED_INT, indices);
  }
  _strip->release();

  _colorTexture->release();

  program.disableAttributeArray(vertexLoc);
  _surface->release();
}
Example #9
0
void csSurface::drawMesh(QOpenGLShaderProgram& program)
{
  if( _initRequired ) {
    initialize();
  }

  if( _meshInfo.isEmpty() ) {
    return;
  }

  program.setUniformValue("cs_DepthOffset", csCoordinateBox::DepthOffset);
  program.setUniformValue("cs_Model", _model);

  _surface->bind();
  const int vertexLoc = program.attributeLocation("cs_Vertex");
  program.enableAttributeArray(vertexLoc);
  program.setAttributeBuffer(vertexLoc, GL_FLOAT, 0, 3);

  const int colorLoc = program.attributeLocation("cs_Color");
  program.setAttributeValue(colorLoc, QColor(Qt::black));

  // Along x-Axis
  for(int y = 0; y < _meshInfo.rowCount(); y++) {
    glDrawArrays(GL_LINE_STRIP,
                 y*_meshInfo.columnCount(), _meshInfo.columnCount());
  }

  // Along y-Axis
  _meshY->bind();
  for(int x = 0; x < _meshInfo.columnCount(); x++) {
    const GLuint  offset  = sizeof(GLuint)*x*_meshInfo.rowCount();
    const GLvoid *indices = (GLvoid*)offset;
    glDrawElements(GL_LINE_STRIP, _meshInfo.rowCount(), GL_UNSIGNED_INT, indices);
  }
  _meshY->release();

  program.disableAttributeArray(vertexLoc);
  _surface->release();
}
Example #10
0
void Viewer_impl::showDistance(QPoint pixel)
{
    static bool isAset = false;
    bool found;
    CGAL::qglviewer::Vec point;
    point = viewer->camera()->pointUnderPixel(pixel, found);
    if(!isAset && found)
    {
        //set APoint
        APoint = point;
        isAset = true;
        clearDistancedisplay();
    }
    else if (found)
    {
        //set BPoint
        BPoint = point;
        isAset = false;

        // fills the buffers
        std::vector<float> v;
        v.resize(6);
        v[0] = float(APoint.x); v[1] = float(APoint.y); v[2] = float(APoint.z);
        v[3] = float(BPoint.x); v[4] = float(BPoint.y); v[5] = float(BPoint.z);
       
        vao.bind();
        buffer.bind();
        buffer.allocate(v.data(),6*sizeof(float));
        rendering_program_dist.enableAttributeArray("vertex");
        rendering_program_dist.setAttributeBuffer("vertex",GL_FLOAT,0,3);
        buffer.release();
        vao.release();
        
        distance_is_displayed = true;
        double dist = std::sqrt((BPoint.x-APoint.x)*(BPoint.x-APoint.x) + (BPoint.y-APoint.y)*(BPoint.y-APoint.y) + (BPoint.z-APoint.z)*(BPoint.z-APoint.z));
        QFont font;
        font.setBold(true);
        TextItem *ACoord = new TextItem(float(APoint.x),
                                        float(APoint.y),
                                        float(APoint.z),
                                        QString("A(%1,%2,%3)").arg(APoint.x-viewer->offset().x).arg(APoint.y-viewer->offset().y).arg(APoint.z-viewer->offset().z), true, font, Qt::red, true);
        distance_text.append(ACoord);
        TextItem *BCoord = new TextItem(float(BPoint.x),
                                        float(BPoint.y),
                                        float(BPoint.z),
                                        QString("B(%1,%2,%3)").arg(BPoint.x-viewer->offset().x).arg(BPoint.y-viewer->offset().y).arg(BPoint.z-viewer->offset().z), true, font, Qt::red, true);
        distance_text.append(BCoord);
        CGAL::qglviewer::Vec centerPoint = 0.5*(BPoint+APoint);
        TextItem *centerCoord = new TextItem(float(centerPoint.x),
                                             float(centerPoint.y),
                                             float(centerPoint.z),
                                             QString(" distance: %1").arg(dist), true, font, Qt::red, true);

        distance_text.append(centerCoord);
        Q_FOREACH(TextItem* ti, distance_text)
          textRenderer->addText(ti);
        Q_EMIT(viewer->sendMessage(QString("First point : A(%1,%2,%3), second point : B(%4,%5,%6), distance between them : %7")
                  .arg(APoint.x-viewer->offset().x)
                  .arg(APoint.y-viewer->offset().y)
                  .arg(APoint.z-viewer->offset().z)
                  .arg(BPoint.x-viewer->offset().x)
                  .arg(BPoint.y-viewer->offset().y)
                  .arg(BPoint.z-viewer->offset().z)
                  .arg(dist)));
    }

}
Example #11
0
/******************************************************************************
* Renders the geometry as with extra information passed to the vertex shader.
******************************************************************************/
void OpenGLArrowPrimitive::renderWithElementInfo(ViewportSceneRenderer* renderer)
{
	QOpenGLShaderProgram* shader = renderer->isPicking() ? _pickingShader : _shader;
	if(!shader)
		return;
	if(!shader->bind())
		throw Exception(QStringLiteral("Failed to bind OpenGL shader."));

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	shader->setUniformValue("modelview_matrix",
			(QMatrix4x4)renderer->modelViewTM());
	shader->setUniformValue("modelview_uniform_scale", (float)pow(std::abs(renderer->modelViewTM().determinant()), (FloatType(1.0/3.0))));
	shader->setUniformValue("modelview_projection_matrix",
			(QMatrix4x4)(renderer->projParams().projectionMatrix * renderer->modelViewTM()));
	shader->setUniformValue("projection_matrix", (QMatrix4x4)renderer->projParams().projectionMatrix);
	shader->setUniformValue("inverse_projection_matrix", (QMatrix4x4)renderer->projParams().inverseProjectionMatrix);
	shader->setUniformValue("is_perspective", renderer->projParams().isPerspective);

	AffineTransformation viewModelTM = renderer->modelViewTM().inverse();
	Vector3 eye_pos = viewModelTM.translation();
	shader->setUniformValue("eye_pos", eye_pos.x(), eye_pos.y(), eye_pos.z());
	Vector3 viewDir = viewModelTM * Vector3(0,0,1);
	shader->setUniformValue("parallel_view_dir", viewDir.x(), viewDir.y(), viewDir.z());

	GLint viewportCoords[4];
	glGetIntegerv(GL_VIEWPORT, viewportCoords);
	shader->setUniformValue("viewport_origin", (float)viewportCoords[0], (float)viewportCoords[1]);
	shader->setUniformValue("inverse_viewport_size", 2.0f / (float)viewportCoords[2], 2.0f / (float)viewportCoords[3]);

	GLint pickingBaseID;
	if(renderer->isPicking()) {
		pickingBaseID = renderer->registerSubObjectIDs(elementCount());
		renderer->activateVertexIDs(shader, _chunkSize * _verticesPerElement, true);
		OVITO_CHECK_OPENGL(shader->setUniformValue("verticesPerElement", (GLint)_verticesPerElement));
	}

	for(int chunkIndex = 0; chunkIndex < _verticesWithElementInfo.size(); chunkIndex++, pickingBaseID += _chunkSize) {
		int chunkStart = chunkIndex * _chunkSize;
		int chunkSize = std::min(_elementCount - chunkStart, _chunkSize);

		if(renderer->isPicking())
			shader->setUniformValue("pickingBaseID", pickingBaseID);

		_verticesWithElementInfo[chunkIndex].bindPositions(renderer, shader, offsetof(VertexWithElementInfo, pos));
		_verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_base", GL_FLOAT, offsetof(VertexWithElementInfo, base), 3, sizeof(VertexWithElementInfo));
		_verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_axis", GL_FLOAT, offsetof(VertexWithElementInfo, dir), 3, sizeof(VertexWithElementInfo));
		_verticesWithElementInfo[chunkIndex].bind(renderer, shader, "cylinder_radius", GL_FLOAT, offsetof(VertexWithElementInfo, radius), 1, sizeof(VertexWithElementInfo));
		if(!renderer->isPicking())
			_verticesWithElementInfo[chunkIndex].bindColors(renderer, shader, 4, offsetof(VertexWithElementInfo, color));

		if(_usingGeometryShader && (shadingMode() == FlatShading || renderingQuality() == HighQuality)) {
			OVITO_CHECK_OPENGL(glDrawArrays(GL_POINTS, 0, chunkSize));
		}
		else {
			int stripPrimitivesPerElement = _stripPrimitiveVertexCounts.size() / _chunkSize;
			OVITO_CHECK_OPENGL(renderer->glMultiDrawArrays(GL_TRIANGLE_STRIP, _stripPrimitiveVertexStarts.data(), _stripPrimitiveVertexCounts.data(), stripPrimitivesPerElement * chunkSize));

			int fanPrimitivesPerElement = _fanPrimitiveVertexCounts.size() / _chunkSize;
			OVITO_CHECK_OPENGL(renderer->glMultiDrawArrays(GL_TRIANGLE_FAN, _fanPrimitiveVertexStarts.data(), _fanPrimitiveVertexCounts.data(), fanPrimitivesPerElement * chunkSize));
		}

		_verticesWithElementInfo[chunkIndex].detachPositions(renderer, shader);
		_verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_base");
		_verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_axis");
		_verticesWithElementInfo[chunkIndex].detach(renderer, shader, "cylinder_radius");
		if(!renderer->isPicking())
			_verticesWithElementInfo[chunkIndex].detachColors(renderer, shader);
	}
	shader->enableAttributeArray("cylinder_base");
	shader->enableAttributeArray("cylinder_axis");
	shader->enableAttributeArray("cylinder_radius");

	if(renderer->isPicking())
		renderer->deactivateVertexIDs(shader, true);

	shader->release();
}
Example #12
0
void VideoSurface::paintGL()
{
    mutex.lock();
    VideoFrame currFrame = frame;
    frame.invalidate();
    mutex.unlock();

    if (currFrame.isValid() && res != currFrame.resolution)
    {
        res = currFrame.resolution;

        // delete old texture
        if (textureId != 0)
            glDeleteTextures(1, &textureId);

        // a texture used to render the pbo (has the match the pixelformat of the source)
        glGenTextures(1,&textureId);
        glBindTexture(GL_TEXTURE_2D, textureId);
        glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, res.width(), res.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }

    if (currFrame.isValid())
    {
        pboIndex = (pboIndex + 1) % 2;
        int nextPboIndex = (pboIndex + 1) % 2;

        if (pboAllocSize != currFrame.frameData.size())
        {
            qDebug() << "VideoSurface: Resize pbo " << currFrame.frameData.size() << "(" << currFrame.resolution << ")" << "bytes (before" << pboAllocSize << ")";

            pbo[0]->bind();
            pbo[0]->allocate(currFrame.frameData.size());
            pbo[0]->release();

            pbo[1]->bind();
            pbo[1]->allocate(currFrame.frameData.size());
            pbo[1]->release();

            pboAllocSize = currFrame.frameData.size();
        }


        pbo[pboIndex]->bind();
        glBindTexture(GL_TEXTURE_2D, textureId);
        glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0);
        pbo[pboIndex]->unmap();
        pbo[pboIndex]->release();

        // transfer data
        pbo[nextPboIndex]->bind();
        void* ptr = pbo[nextPboIndex]->map(QOpenGLBuffer::WriteOnly);
        if (ptr)
            memcpy(ptr, currFrame.frameData.data(), currFrame.frameData.size());
        pbo[nextPboIndex]->unmap();
        pbo[nextPboIndex]->release();
    }

    // background
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    // keep aspect ratio
    float aspectRatio = float(res.width()) / float(res.height());
    if (width() < float(height()) * aspectRatio)
    {
        float h = float(width()) / aspectRatio;
        glViewport(0, (height() - h)*0.5f, width(), h);
    }
    else
    {
        float w = float(height()) * float(aspectRatio);
        glViewport((width() - w)*0.5f, 0, w, height());
    }

    QOpenGLShaderProgram* programm = nullptr;
    switch (frame.format)
    {
    case VideoFrame::YUV:
        programm = yuvProgramm;
        break;
    case VideoFrame::BGR:
        programm = bgrProgramm;
        break;
    default:
        break;
    }

    if (programm)
    {
        // render pbo
        static float values[] = {
            -1, -1,
            1, -1,
            -1, 1,
            1, 1
        };

        programm->bind();
        programm->setAttributeArray(0, GL_FLOAT, values, 2);
        programm->enableAttributeArray(0);
    }

    glBindTexture(GL_TEXTURE_2D, textureId);

    //draw fullscreen quad
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindTexture(GL_TEXTURE_2D, 0);

    if (programm)
    {
        programm->disableAttributeArray(0);
        programm->release();
    }
}