Example #1
0
void Scene::paintGL(){
    setStates();                    // включаем буфер глубины, свет и прочее (возможно можно вынести в initGL)

    //glClear(GL_COLOR_BUFFER_BIT); // если включен буфер глубины, то без его очистки мы ничего не увидим
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glMatrixMode(GL_PROJECTION);
    //qgluPerspective(60.0, width / height, 0.01, 15.0);

    //glMatrixMode(GL_MODELVIEW);

    //пишем матрицы преобразований
    QMatrix4x4 LMM; // Local Model matrix (делает преобразования в локальных координатах объекта, для одного объекта их может быть несколько для разных частей объекта)
    QMatrix4x4 MM; // Model matrix (выносит координаты объекта в координаты пространства сцены,
                  //выполняется в следующем порядке - масштабирование, поворот, перенос)
                  // TranslationMatrix * RotationMatrix * ScaleMatrix * OriginalVector; (в коде это выглядит в обратном порядке)
    QMatrix4x4 MVM; // ModelView matrix (View matrix)("масштабирует крутит и перемещает весь мир")
    QMatrix4x4 CameraView; // тоже самое что и MVM, но для использования функции LookAt
    QMatrix4x4 PM; // Projection matrix // проекционная матрица
    QMatrix4x4 MVPM; // ModelViewProjection matrix (projection * view * model)
    if (perspective) {
        // устанавливаем трёхмерную канву (в перспективной проекции) для рисования (плоскости отсечения)
        // угол перспективы, отношение сторон, расстояние до ближней отсекающей плоскости и дальней
        PM.perspective(cameraFocusAngle,ratio,0.1f,100.0f);  // glFrustum( xmin, xmax, ymin, ymax, near, far)  // gluPerspective(fovy, aspect, near, far)
    }
    else {
        // устанавливаем трёхмерную канву (в ортогональной проекции) для рисования (плоскости отсечения)
        PM.ortho(-2.0f,2.0f,-2.0f,2.0f,-8.0f,8.0f); // glOrtho(left,right,bottom,top,near,far) // увеличение значений уменьшает фигуры на сцене (по Z задаём больше, чтобы не видеть отсечение фигур)
        // переносим по z дальше, обязательное условие для перспективной проекции // по оси z 0 это "глаз", - движение камеры назад, + вперёд.
    }
    ///MVM.translate(0.0f,0.0f,-6.0f); // переносим по z от "глаз", сдвигаем камеру на минус, т.е. в сторону затылка.
    // не работает в ортогональной проекции если перенести слишком далеко, за пределы куба отсечения
    // оппа, мы видим передние границы пирамиды отсечения, где всё отсекается (тут-то шейдерным сферам и конец)
    // изменяем масштаб фигуры (увеличиваем)
    ///MVM.scale(10.0f);  // отрицательное число переворачивает проекцию // влияет только на ортогональную проекцию // убивает Шферы
    // указываем угол поворота и ось поворота смотрящую из центра координат к точке x,y,z,
    MVM.rotate(m_angle,0.0f,1.0f,0.0f);  // поворот вокруг оси центра координат
    CameraView.lookAt(cameraEye,cameraCenter,cameraUp); // установка камеры (матрицы трансфрмации)
    MVM=CameraView*MVM;  // получаем матрицу трансформации итогового вида

    // находим проекционную инверсную мтрицу
    bool inverted;
    QMatrix4x4 PMi=PM.inverted(&inverted);
    if (!inverted)
        qDebug() << "PMi не конвертится";
    MVPM=PM*MVM;
    QMatrix4x4 MVPMi=MVPM.inverted(&inverted);
    if (!inverted)
        qDebug() << "MVPMi не конвертится";

    // РИСУЕМ ТРЕУГОЛЬНИК
    // инициализируем данные программы матрицы и атрибуты
    m_triangle->init();
    // зaпихиваем в его программу матрицу ориентации
    m_triangle->m_program.setUniformValue(m_triangle->m_matrixUniform, MVPM);
    // вызываем функцию рисования объекта (или объектов в for)
    m_triangle->draw();
    // проводим сброс инициализации параметров
    m_triangle->drop();//*/

    //РИСУЕМ СФЕРЫ
    m_shphere->init();
    m_shphere->m_program->setUniformValue(m_shphere->m_matrixUniform, MVPM);
    m_shphere->m_program->setUniformValue("PMi", PMi);
    m_shphere->m_program->setUniformValue("MVM", MVM);
    m_shphere->m_program->setUniformValue("MVPMi", MVPMi);
    m_shphere->m_program->setUniformValue("viewport",viewport);
    m_shphere->draw();
    m_shphere->drop();//*/

}
Example #2
0
void QtViewRenderer::render()
{
	QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
	OpenGLStateSaver state(f);

	f->glEnable(GL_BLEND);
	f->glBlendEquation(GL_FUNC_ADD);
	f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	f->glDisable(GL_CULL_FACE);
	f->glDisable(GL_DEPTH_TEST);
	f->glActiveTexture(GL_TEXTURE0);

	glClearColor(m_clearColor[0], m_clearColor[1], m_clearColor[2], 1.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glViewport(0, 0, m_width, m_height);
	QMatrix4x4 ortho;
	ortho.ortho(m_viewBounds[0], m_viewBounds[2], m_viewBounds[3], m_viewBounds[1], -1, 1);

	m_shader->bind();
	m_shader->setUniformValue(m_locationTex, 0);
	m_shader->setUniformValue(m_locationProjMtx, ortho);

	m_VAO->bind();

	int vboSize = 0, eboSize = 0;
	for (const auto cmd_list : m_drawLists)
	{
		if (cmd_list->vtxBuffer().empty() || cmd_list->idxBuffer().empty())
			continue;

		const DrawList::DrawIdx* idx_buffer_offset = nullptr;

		m_VBO->bind();
		int vtxSize = cmd_list->vtxBuffer().size() * sizeof(DrawList::DrawVert);
		if (vtxSize > vboSize)
		{
			m_VBO->allocate(vtxSize);
			vboSize = vtxSize;
		}
		m_VBO->write(0, &cmd_list->vtxBuffer().front(), vtxSize);

		m_EBO->bind();
		int idxSize = cmd_list->idxBuffer().size() * sizeof(DrawList::DrawIdx);
		if (idxSize > eboSize)
		{
			m_EBO->allocate(idxSize);
			eboSize = idxSize;
		}
		m_EBO->write(0, &cmd_list->idxBuffer().front(), idxSize);

		for (const auto& pcmd : cmd_list->cmdBuffer())
		{
			glBindTexture(GL_TEXTURE_2D, pcmd.textureId);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

			glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(pcmd.elemCount), GL_UNSIGNED_INT, idx_buffer_offset);
			idx_buffer_offset += pcmd.elemCount;
		}
	}

	m_shader->release();
	m_VAO->release();
}
Example #3
0
void ShaderNode::inputsUpdated( qint64 pTimeStamp )
{
	fugio::Performance	Perf( mNode, "inputsUpdated" );

	if( !mInitialised )
	{
		return;
	}

	OPENGL_PLUGIN_DEBUG;

	if( mPinShaderVertex->isUpdated( mLastShaderLoad ) || mPinShaderGeometry->isUpdated( mLastShaderLoad ) || mPinShaderFragment->isUpdated( mLastShaderLoad ) )
	{
		loadShader();

		mLastShaderLoad = pTimeStamp;
	}

	OPENGL_PLUGIN_DEBUG;

	if( !mProgramLinked )
	{
		return;
	}

	//-------------------------------------------------------------------------

	int		W, H, D;

	QList< QSharedPointer<InterfacePin> >	OutPinLst = mNode->enumOutputPins();
	QList< QSharedPointer<InterfacePin> >	InpPinLst = mNode->enumInputPins();

	//-------------------------------------------------------------------------

	glUseProgram( mProgramId );

	OPENGL_PLUGIN_DEBUG;

	QList<ShaderBindData>		Bindings;

	updateUniforms( Bindings, pTimeStamp );

	if( mPinOutputGeometry->isConnectedToActiveNode() )
	{
		mNode->context()->pinUpdated( mPinOutputGeometry );
	}

	if( activeBufferCount( OutPinLst ) == 0 )
	{
		glUseProgram( 0 );

		return;
	}

	//-------------------------------------------------------------------------
	// Bind all output buffers

	QVector<GLenum>		Buffers;

	bindOutputBuffers( Buffers, OutPinLst, W, H, D );

	if( mFrameBufferId != 0 )
	{
		glBindFramebuffer( GL_FRAMEBUFFER, mFrameBufferId );

		if( !Buffers.empty() )
		{
			glDrawBuffers( Buffers.size(), Buffers.data() );

			OPENGL_PLUGIN_DEBUG;
		}

		if( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
		{
			qDebug() << "glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE";
		}
	}

	//-------------------------------------------------------------------------

	InterfaceOpenGLState		*State = 0;

	if( mPinState->isConnected() )
	{
		State = qobject_cast<InterfaceOpenGLState *>( mPinState->connectedPin()->control()->object() );
	}

	if( State != 0 )
	{
		State->stateBegin();
	}

	//-------------------------------------------------------------------------

	if( true )
	{
		glViewport( 0, 0, W, H );

		glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

		QList<InterfaceGeometry*>		GeometryList;

		for( QList< QSharedPointer<InterfacePin> >::iterator it = InpPinLst.begin() ; it != InpPinLst.end() ; it++ )
		{
			QSharedPointer<InterfacePin>	InpPin = *it;

			if( !InpPin->isConnectedToActiveNode() )
			{
				continue;
			}

			QSharedPointer<InterfacePinControl>		 GeometryControl = InpPin->connectedPin()->control();

			InterfaceGeometry		*Geometry = ( GeometryControl.isNull() ? 0 : qobject_cast<InterfaceGeometry *>( GeometryControl->object() ) );

			if( Geometry != 0 )
			{
				GeometryList.append( Geometry );
			}
		}

		if( GeometryList.isEmpty() )
		{
			QMatrix4x4		pmvMatrix;

			pmvMatrix.setToIdentity();

			pmvMatrix.ortho( QRect( QPoint( 0, 0 ), QSize( W, H ) ) );

			glMatrixMode( GL_PROJECTION );
			glLoadIdentity();

			glLoadMatrixf( pmvMatrix.constData() );

			//Initialize Modelview Matrix
			glMatrixMode( GL_MODELVIEW );
			glLoadIdentity();

			glColor4f( 1.0, 1.0, 1.0, 1.0 );

			//glEnable( GL_BLEND );

			//glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

			//glActiveTexture( GL_TEXTURE0 );

			OPENGL_PLUGIN_DEBUG;

			GLint		x0 = 0;
			GLint		x1 = W;
			GLint		y0 = 0;
			GLint		y1 = H;

			glBegin( GL_QUADS );
				glMultiTexCoord2i( GL_TEXTURE0, x0, y1 );	glMultiTexCoord2f( GL_TEXTURE1, 0, 1 );		glVertex2i( x0, y0 );
				glMultiTexCoord2i( GL_TEXTURE0, x1, y1 );	glMultiTexCoord2f( GL_TEXTURE1, 1, 1 );		glVertex2i( x1, y0 );
				glMultiTexCoord2i( GL_TEXTURE0, x1, y0 );	glMultiTexCoord2f( GL_TEXTURE1, 1, 0 );		glVertex2i( x1, y1 );
				glMultiTexCoord2i( GL_TEXTURE0, x0, y0 );	glMultiTexCoord2f( GL_TEXTURE1, 0, 0 );		glVertex2i( x0, y1 );
			glEnd();
		}
		else
		{
			glMatrixMode( GL_PROJECTION );
			glLoadIdentity();

			//Initialize Modelview Matrix
			glMatrixMode( GL_MODELVIEW );
			glLoadIdentity();

			glColor4f( 1.0, 1.0, 1.0, 1.0 );

			//glEnable( GL_BLEND );

			//glBlendFunc( GL_ONE, GL_ONE );

			//glActiveTexture( GL_TEXTURE0 );

			OPENGL_PLUGIN_DEBUG;

			//glTranslatef( 0.0f, 0.0f, -5.0f );

			foreach( InterfaceGeometry *Geometry, GeometryList )
			{
				Geometry->drawGeometry();
			}
		}

		OPENGL_PLUGIN_DEBUG;
	}
Example #4
0
void GLSLBlurShader::init()
{
    QVector<float> kernel = gaussianKernel();
    const int size = kernel.size();
    const int center = size / 2;

    QByteArray vertexSource;
    QByteArray fragmentSource;

    // Vertex shader
    // ===================================================================
    QTextStream stream(&vertexSource);

    stream << "uniform mat4 u_modelViewProjectionMatrix;\n";
    stream << "uniform mat4 u_textureMatrix;\n";
    stream << "uniform vec2 pixelSize;\n\n";
    stream << "attribute vec4 vertex;\n";
    stream << "attribute vec4 texCoord;\n\n";
    stream << "varying vec4 samplePos[" << std::ceil(size / 2.0) << "];\n";
    stream << "\n";
    stream << "void main(void)\n";
    stream << "{\n";
    stream << "    vec4 center = vec4(u_textureMatrix * texCoord).stst;\n";
    stream << "    vec4 ps = pixelSize.stst;\n\n";
    for (int i = 0; i < size; i += 2) {
        float offset1, offset2;
        if (i < center) {
            offset1 = -(1.5 + (center - i - 1) * 2.0);
            offset2 = (i + 1) == center ? 0 : offset1 + 2;
        } else if (i > center) {
            offset1 = 1.5 + (i - center - 1) * 2.0;
            offset2 = (i + 1) == size ? 0 : offset1 + 2;
        } else {
            offset1 = 0;
            offset2 = 1.5;
        }
        stream << "    samplePos[" << i / 2 << "] = center + ps * vec4("
               << offset1 << ", " << offset1 << ", " << offset2 << ", " << offset2 << ");\n";
    }
    stream << "\n";
    stream << "    gl_Position = u_modelViewProjectionMatrix * vertex;\n";
    stream << "}\n";
    stream.flush();

    // Fragment shader
    // ===================================================================
    QTextStream stream2(&fragmentSource);

    stream2 << "uniform sampler2D texUnit;\n";
    stream2 << "varying vec4 samplePos[" << std::ceil(size / 2.0) << "];\n\n";

    for (int i = 0; i <= center; i++)
        stream2 << "const vec4 kernel" << i << " = vec4(" << kernel[i] << ");\n";
    stream2 << "\n";
    stream2 << "void main(void)\n";
    stream2 << "{\n";
    stream2 << "    vec4 sum = texture2D(texUnit, samplePos[0].st) * kernel0;\n";
    for (int i = 1; i < size; i++)
        stream2 << "    sum = sum + texture2D(texUnit, samplePos[" << i / 2 << ((i % 2) ? "].pq)" : "].st)")
                << " * kernel" << (i > center ? size - i - 1 : i) << ";\n";
    stream2 << "    gl_FragColor = sum;\n";
    stream2 << "}\n";
    stream2.flush();

    shader = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentSource);
    if (shader->isValid()) {
        QMatrix4x4 modelViewProjection;
        modelViewProjection.ortho(0, displayWidth(), displayHeight(), 0, 0, 65535);
        ShaderManager::instance()->pushShader(shader);
        shader->setUniform("texUnit", 0);
        shader->setUniform("u_textureMatrix", QMatrix4x4());
        shader->setUniform("u_modelViewProjectionMatrix", modelViewProjection);
        ShaderManager::instance()->popShader();
    }

    setIsValid(shader->isValid());
}
Example #5
0
void BlurEffect::doCachedBlur(EffectWindow *w, const QRegion& region, const float opacity)
{
    const QRect screen = effects->virtualScreenGeometry();
    const QRegion blurredRegion = blurRegion(w).translated(w->pos()) & screen;
    const QRegion expanded = expand(blurredRegion) & screen;
    const QRect r = expanded.boundingRect();

    // The background texture we get is only partially valid.

    CacheEntry it = windows.find(w);
    if (it == windows.end()) {
        BlurWindowInfo bwi;
        bwi.blurredBackground = GLTexture(r.width(),r.height());
        bwi.damagedRegion = expanded;
        bwi.dropCache = false;
        bwi.windowPos = w->pos();
        it = windows.insert(w, bwi);
    } else if (it->blurredBackground.size() != r.size()) {
        it->blurredBackground = GLTexture(r.width(),r.height());
        it->dropCache = false;
        it->windowPos = w->pos();
    } else if (it->windowPos != w->pos()) {
        it->dropCache = false;
        it->windowPos = w->pos();
    }

    GLTexture targetTexture = it->blurredBackground;
    targetTexture.setFilter(GL_LINEAR);
    targetTexture.setWrapMode(GL_CLAMP_TO_EDGE);
    shader->bind();
    QMatrix4x4 textureMatrix;
    QMatrix4x4 modelViewProjectionMatrix;

    /**
     * Which part of the background texture can be updated ?
     *
     * Well this is a rather difficult question. We kind of rely on the fact, that
     * we need a bigger background region being painted before, more precisely if we want to
     * blur region A we need the background region expand(A). This business logic is basically
     * done in prePaintWindow:
     *          data.paint |= expand(damagedArea);
     *
     * Now "data.paint" gets clipped and becomes what we receive as the "region" variable
     * in this function. In theory there is now only one function that does this clipping
     * and this is paintSimpleScreen. The clipping has the effect that "damagedRegion"
     * is no longer a subset of "region" and we cannot fully validate the cache within one
     * rendering pass. If we would now update the "damageRegion & region" part of the cache
     * we would wrongly update the part of the cache that is next to the "region" border and
     * which lies within "damagedRegion", just because we cannot assume that the framebuffer
     * outside of "region" is valid. Therefore the maximal damaged region of the cache that can
     * be repainted is given by:
     *          validUpdate = damagedRegion - expand(damagedRegion - region);
     *
     * Now you may ask what is with the rest of "damagedRegion & region" that is not part
     * of "validUpdate" but also might end up on the screen. Well under the assumption
     * that only the occlusion culling can shrink "data.paint", we can control this by reducing
     * the opaque area of every window by a margin of the blurring radius (c.f. prePaintWindow).
     * This way we are sure that this area is overpainted by a higher opaque window.
     *
     * Apparently paintSimpleScreen is not the only function that can influence "region".
     * In fact every effect's paintWindow that is called before Blur::paintWindow
     * can do so (e.g. SlidingPopups). Hence we have to make the compromise that we update
     * "damagedRegion & region" of the cache but only mark "validUpdate" as valid.
     **/
    const QRegion damagedRegion = it->damagedRegion;
    const QRegion updateBackground = damagedRegion & region;
    const QRegion validUpdate = damagedRegion - expand(damagedRegion - region);

    const QRegion horizontal = validUpdate.isEmpty() ? QRegion() : (updateBackground & screen);
    const QRegion vertical   = blurredRegion & region;

    const int horizontalOffset = 0;
    const int horizontalCount = horizontal.rectCount() * 6;

    const int verticalOffset = horizontalCount;
    const int verticalCount = vertical.rectCount() * 6;

    GLVertexBuffer *vbo = GLVertexBuffer::streamingBuffer();
    uploadGeometry(vbo, horizontal, vertical);

    vbo->bindArrays();

    if (!validUpdate.isEmpty()) {
        const QRect updateRect = (expand(updateBackground) & expanded).boundingRect();
        // First we have to copy the background from the frontbuffer
        // into a scratch texture (in this case "tex").
        tex.bind();

        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, updateRect.x(), displayHeight() - updateRect.y() - updateRect.height(),
                            updateRect.width(), updateRect.height());

        // Draw the texture on the offscreen framebuffer object, while blurring it horizontally
        target->attachTexture(targetTexture);
        GLRenderTarget::pushRenderTarget(target);

        shader->setDirection(Qt::Horizontal);
        shader->setPixelDistance(1.0 / tex.width());

        modelViewProjectionMatrix.ortho(0, r.width(), r.height(), 0 , 0, 65535);
        modelViewProjectionMatrix.translate(-r.x(), -r.y(), 0);
        shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);

        // Set up the texture matrix to transform from screen coordinates
        // to texture coordinates.
        textureMatrix.scale(1.0 / tex.width(), -1.0 / tex.height(), 1);
        textureMatrix.translate(-updateRect.x(), -updateRect.height() - updateRect.y(), 0);
        shader->setTextureMatrix(textureMatrix);

        vbo->draw(GL_TRIANGLES, horizontalOffset, horizontalCount);

        GLRenderTarget::popRenderTarget();
        tex.unbind();
        // mark the updated region as valid
        it->damagedRegion -= validUpdate;
    }

    // Now draw the horizontally blurred area back to the backbuffer, while
    // blurring it vertically and clipping it to the window shape.
    targetTexture.bind();

    shader->setDirection(Qt::Vertical);
    shader->setPixelDistance(1.0 / targetTexture.height());

    // Modulate the blurred texture with the window opacity if the window isn't opaque
    if (opacity < 1.0) {
        glEnable(GL_BLEND);
        glBlendColor(0, 0, 0, opacity);
        glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
    }

    modelViewProjectionMatrix.setToIdentity();
    const QSize screenSize = effects->virtualScreenSize();
    modelViewProjectionMatrix.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535);
    shader->setModelViewProjectionMatrix(modelViewProjectionMatrix);

    // Set the up the texture matrix to transform from screen coordinates
    // to texture coordinates.
    textureMatrix.setToIdentity();
    textureMatrix.scale(1.0 / targetTexture.width(), -1.0 / targetTexture.height(), 1);
    textureMatrix.translate(-r.x(), -targetTexture.height() - r.y(), 0);
    shader->setTextureMatrix(textureMatrix);

    vbo->draw(GL_TRIANGLES, verticalOffset, verticalCount);
    vbo->unbindArrays();

    if (opacity < 1.0) {
        glDisable(GL_BLEND);
    }

    targetTexture.unbind();
    shader->unbind();
}
Example #6
0
void KisOpenGLCanvas2::drawImage()
{
    if (!d->displayShader) {
        return;
    }

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    KisCoordinatesConverter *converter = coordinatesConverter();

    d->displayShader->bind();

    QMatrix4x4 projectionMatrix;
    projectionMatrix.setToIdentity();
    projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL);

    // Set view/projection matrices
    QMatrix4x4 modelMatrix(coordinatesConverter()->imageToWidgetTransform());
    modelMatrix.optimize();
    modelMatrix = projectionMatrix * modelMatrix;
    d->displayShader->setUniformValue(d->displayShader->location(Uniform::ModelViewProjection), modelMatrix);

    QMatrix4x4 textureMatrix;
    textureMatrix.setToIdentity();
    d->displayShader->setUniformValue(d->displayShader->location(Uniform::TextureMatrix), textureMatrix);

    QRectF widgetRect(0,0, width(), height());
    QRectF widgetRectInImagePixels = converter->documentToImage(converter->widgetToDocument(widgetRect));

    qreal scaleX, scaleY;
    converter->imageScale(&scaleX, &scaleY);
    d->displayShader->setUniformValue(d->displayShader->location(Uniform::ViewportScale), (GLfloat) scaleX);
    d->displayShader->setUniformValue(d->displayShader->location(Uniform::TexelSize), (GLfloat) d->openGLImageTextures->texelSize());

    QRect ir = d->openGLImageTextures->storedImageBounds();
    QRect wr = widgetRectInImagePixels.toAlignedRect();

    if (!d->wrapAroundMode) {
        // if we don't want to paint wrapping images, just limit the
        // processing area, and the code will handle all the rest
        wr &= ir;
    }

    int firstColumn = d->xToColWithWrapCompensation(wr.left(), ir);
    int lastColumn = d->xToColWithWrapCompensation(wr.right(), ir);
    int firstRow = d->yToRowWithWrapCompensation(wr.top(), ir);
    int lastRow = d->yToRowWithWrapCompensation(wr.bottom(), ir);

    int minColumn = d->openGLImageTextures->xToCol(ir.left());
    int maxColumn = d->openGLImageTextures->xToCol(ir.right());
    int minRow = d->openGLImageTextures->yToRow(ir.top());
    int maxRow = d->openGLImageTextures->yToRow(ir.bottom());

    int imageColumns = maxColumn - minColumn + 1;
    int imageRows = maxRow - minRow + 1;

    for (int col = firstColumn; col <= lastColumn; col++) {
        for (int row = firstRow; row <= lastRow; row++) {

            int effectiveCol = col;
            int effectiveRow = row;
            QPointF tileWrappingTranslation;

            if (effectiveCol > maxColumn || effectiveCol < minColumn) {
                int translationStep = floor(qreal(col) / imageColumns);
                int originCol = translationStep * imageColumns;
                effectiveCol = col - originCol;
                tileWrappingTranslation.rx() = translationStep * ir.width();
            }

            if (effectiveRow > maxRow || effectiveRow < minRow) {
                int translationStep = floor(qreal(row) / imageRows);
                int originRow = translationStep * imageRows;
                effectiveRow = row - originRow;
                tileWrappingTranslation.ry() = translationStep * ir.height();
            }

            KisTextureTile *tile =
                    d->openGLImageTextures->getTextureTileCR(effectiveCol, effectiveRow);

            if (!tile) {
                warnUI << "OpenGL: Trying to paint texture tile but it has not been created yet.";
                continue;
            }

            /*
             * We create a float rect here to workaround Qt's
             * "history reasons" in calculation of right()
             * and bottom() coordinates of integer rects.
             */
            QRectF textureRect(tile->tileRectInTexturePixels());
            QRectF modelRect(tile->tileRectInImagePixels().translated(tileWrappingTranslation.x(), tileWrappingTranslation.y()));

            //Setup the geometry for rendering
            if (KisOpenGL::hasOpenGL3()) {
                rectToVertices(d->vertices, modelRect);

                d->quadBuffers[0].bind();
                d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float));

                rectToTexCoords(d->texCoords, textureRect);
                d->quadBuffers[1].bind();
                d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float));
            }
            else {
                rectToVertices(d->vertices, modelRect);
                d->displayShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
                d->displayShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices);

                rectToTexCoords(d->texCoords, textureRect);
                d->displayShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
                d->displayShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords);
            }

            if (d->displayFilter) {
                glActiveTexture(GL_TEXTURE0 + 1);
                glBindTexture(GL_TEXTURE_3D, d->displayFilter->lutTexture());
                d->displayShader->setUniformValue(d->displayShader->location(Uniform::Texture1), 1);
            }

            int currentLodPlane = tile->currentLodPlane();
            if (d->displayShader->location(Uniform::FixedLodLevel) >= 0) {
                d->displayShader->setUniformValue(d->displayShader->location(Uniform::FixedLodLevel),
                                                  (GLfloat) currentLodPlane);
            }

            glActiveTexture(GL_TEXTURE0);
            tile->bindToActiveTexture();

            if (currentLodPlane > 0) {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
            } else if (SCALE_MORE_OR_EQUAL_TO(scaleX, scaleY, 2.0)) {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            } else {
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

                switch(d->filterMode) {
                case KisOpenGL::NearestFilterMode:
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                    break;
                case KisOpenGL::BilinearFilterMode:
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                    break;
                case KisOpenGL::TrilinearFilterMode:
                    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                    break;
                case KisOpenGL::HighQualityFiltering:
                    if (SCALE_LESS_THAN(scaleX, scaleY, 0.5)) {
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
                    } else {
                        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                    }
                    break;
                }
            }

            glDrawArrays(GL_TRIANGLES, 0, 6);
        }
    }

    glBindTexture(GL_TEXTURE_2D, 0);
    d->displayShader->release();
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
Example #7
0
void KisOpenGLCanvas2::drawCheckers()
{
    if (!d->checkerShader) {
        return;
    }

    KisCoordinatesConverter *converter = coordinatesConverter();
    QTransform textureTransform;
    QTransform modelTransform;
    QRectF textureRect;
    QRectF modelRect;

    QRectF viewportRect = !d->wrapAroundMode ?
                converter->imageRectInViewportPixels() :
                converter->widgetToViewport(this->rect());

    converter->getOpenGLCheckersInfo(viewportRect,
                                     &textureTransform, &modelTransform, &textureRect, &modelRect, d->scrollCheckers);

    textureTransform *= QTransform::fromScale(d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE,
                                              d->checkSizeScale / KisOpenGLImageTextures::BACKGROUND_TEXTURE_SIZE);

    if (!d->checkerShader->bind()) {
        qWarning() << "Could not bind checker shader";
        return;
    }

    QMatrix4x4 projectionMatrix;
    projectionMatrix.setToIdentity();
    projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL);

    // Set view/projection matrices
    QMatrix4x4 modelMatrix(modelTransform);
    modelMatrix.optimize();
    modelMatrix = projectionMatrix * modelMatrix;
    d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::ModelViewProjection), modelMatrix);

    QMatrix4x4 textureMatrix(textureTransform);
    d->checkerShader->setUniformValue(d->checkerShader->location(Uniform::TextureMatrix), textureMatrix);

    //Setup the geometry for rendering
    if (KisOpenGL::hasOpenGL3()) {
        rectToVertices(d->vertices, modelRect);

        d->quadBuffers[0].bind();
        d->quadBuffers[0].write(0, d->vertices, 3 * 6 * sizeof(float));

        rectToTexCoords(d->texCoords, textureRect);
        d->quadBuffers[1].bind();
        d->quadBuffers[1].write(0, d->texCoords, 2 * 6 * sizeof(float));
    }
    else {
        rectToVertices(d->vertices, modelRect);
        d->checkerShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
        d->checkerShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, d->vertices);

        rectToTexCoords(d->texCoords, textureRect);
        d->checkerShader->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);
        d->checkerShader->setAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE, d->texCoords);
    }

    // render checkers
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, d->openGLImageTextures->checkerTexture());

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glBindTexture(GL_TEXTURE_2D, 0);
    d->checkerShader->release();
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
Example #8
0
void KisOpenGLCanvas2::paintToolOutline(const QPainterPath &path)
{
    d->cursorShader->bind();

    // setup the mvp transformation
    KisCoordinatesConverter *converter = coordinatesConverter();

    QMatrix4x4 projectionMatrix;
    projectionMatrix.setToIdentity();
    projectionMatrix.ortho(0, width(), height(), 0, NEAR_VAL, FAR_VAL);

    // Set view/projection matrices
    QMatrix4x4 modelMatrix(converter->flakeToWidgetTransform());
    modelMatrix.optimize();
    modelMatrix = projectionMatrix * modelMatrix;
    d->cursorShader->setUniformValue(d->cursorShader->location(Uniform::ModelViewProjection), modelMatrix);

    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    // XXX: glLogicOp not in ES 2.0 -- it would be better to use another method.
    // It is defined in 3.1 core profile onward.
    // Actually, https://www.opengl.org/sdk/docs/man/html/glLogicOp.xhtml says it's in 2.0 onwards,
    // only not in ES, but we don't care about ES, so we could use the function directly.
    glEnable(GL_COLOR_LOGIC_OP);
    if (ptr_glLogicOp) {
        ptr_glLogicOp(GL_XOR);
    }

    // Paint the tool outline
    if (KisOpenGL::hasOpenGL3()) {
        d->outlineVAO.bind();
        d->lineBuffer.bind();
    }

    // Convert every disjointed subpath to a polygon and draw that polygon
    QList<QPolygonF> subPathPolygons = path.toSubpathPolygons();
    for (int i = 0; i < subPathPolygons.size(); i++) {
        const QPolygonF& polygon = subPathPolygons.at(i);

        QVector<QVector3D> vertices;
        vertices.resize(polygon.count());
        for (int j = 0; j < polygon.count(); j++) {
            QPointF p = polygon.at(j);
            vertices[j].setX(p.x());
            vertices[j].setY(p.y());
        }
        if (KisOpenGL::hasOpenGL3()) {
            d->lineBuffer.allocate(vertices.constData(), 3 * vertices.size() * sizeof(float));
        }
        else {
            d->cursorShader->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);
            d->cursorShader->setAttributeArray(PROGRAM_VERTEX_ATTRIBUTE, vertices.constData());
        }

        glDrawArrays(GL_LINE_STRIP, 0, vertices.size());
    }

    if (KisOpenGL::hasOpenGL3()) {
        d->lineBuffer.release();
        d->outlineVAO.release();
    }

    glDisable(GL_COLOR_LOGIC_OP);

    d->cursorShader->release();
}
void QOpenGLRenderer::render(render::Mesh mesh)
{
	//const qreal retinaScale = devicePixelRatio();
	glViewport(0, 0, viewportWidth * retinaScale, viewportHeight * retinaScale);

	//glClear(GL_COLOR_BUFFER_BIT);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	// Enable depth buffer
	glEnable(GL_DEPTH_TEST); // to init
	// Enable back face culling
	glEnable(GL_CULL_FACE); // to init

	glEnable(GL_TEXTURE_2D);

	// Note: OpenGL: CCW triangles = front-facing.
	// Coord-axis: right = +x, up = +y, to back = -z, to front = +z

	m_program->bind();

	// Store the 3DMM vertices in GLfloat's
	// Todo: Measure time. Possible improvements: 1) See if Vec3f is in contiguous storage, if yes, maybe change my Vertex/Mesh structure.
	// 2) Maybe change the datatypes (see http://www.opengl.org/wiki/Vertex_Specification_Best_Practices 'Attribute sizes')
	vector<GLfloat> mmVertices;
	//render::Mesh mesh = morphableModel.getMean();
	mmVertices.clear();
	int numTriangles = mesh.tvi.size();
	for (int i = 0; i < numTriangles; ++i)
	{
		// First vertex x, y, z of the triangle
		const auto& triangle = mesh.tvi[i];
		mmVertices.push_back(mesh.vertex[triangle[0]].position[0]);
		mmVertices.push_back(mesh.vertex[triangle[0]].position[1]);
		mmVertices.push_back(mesh.vertex[triangle[0]].position[2]);
		// Second vertex x, y, z
		mmVertices.push_back(mesh.vertex[triangle[1]].position[0]);
		mmVertices.push_back(mesh.vertex[triangle[1]].position[1]);
		mmVertices.push_back(mesh.vertex[triangle[1]].position[2]);
		// Third vertex x, y, z
		mmVertices.push_back(mesh.vertex[triangle[2]].position[0]);
		mmVertices.push_back(mesh.vertex[triangle[2]].position[1]);
		mmVertices.push_back(mesh.vertex[triangle[2]].position[2]);
	}
	vector<GLfloat> mmColors;
	for (int i = 0; i < numTriangles; ++i)
	{
		// First vertex x, y, z of the triangle
		const auto& triangle = mesh.tci[i];
		mmColors.push_back(mesh.vertex[triangle[0]].color[0]);
		mmColors.push_back(mesh.vertex[triangle[0]].color[1]);
		mmColors.push_back(mesh.vertex[triangle[0]].color[2]);
		// Second vertex x, y, z
		mmColors.push_back(mesh.vertex[triangle[1]].color[0]);
		mmColors.push_back(mesh.vertex[triangle[1]].color[1]);
		mmColors.push_back(mesh.vertex[triangle[1]].color[2]);
		// Third vertex x, y, z
		mmColors.push_back(mesh.vertex[triangle[2]].color[0]);
		mmColors.push_back(mesh.vertex[triangle[2]].color[1]);
		mmColors.push_back(mesh.vertex[triangle[2]].color[2]);
	}
	vector<GLfloat> mmTex;
	for (int i = 0; i < numTriangles; ++i)
	{
		// First vertex u, v of the triangle
		const auto& triangle = mesh.tci[i]; // use tti?
		mmTex.push_back(mesh.vertex[triangle[0]].texcrd[0]);
		mmTex.push_back(mesh.vertex[triangle[0]].texcrd[1]);
		// Second vertex u, v
		mmTex.push_back(mesh.vertex[triangle[1]].texcrd[0]);
		mmTex.push_back(mesh.vertex[triangle[1]].texcrd[1]);
		// Third vertex u, v
		mmTex.push_back(mesh.vertex[triangle[2]].texcrd[0]);
		mmTex.push_back(mesh.vertex[triangle[2]].texcrd[1]);
	}

	float aspect = static_cast<float>(viewportWidth) / static_cast<float>(viewportHeight);
	QMatrix4x4 matrix;
	matrix.ortho(-1.0f*aspect, 1.0f*aspect, -1.0f, 1.0f, 0.1f, 100.0f); // l r b t n f
	//matrix.ortho(-70.0f, 70.0f, -70.0f, 70.0f, 0.1f, 1000.0f);
	//matrix.perspective(60, aspect, 0.1, 100.0);
	matrix.translate(0, 0, -2);
	matrix.rotate(15.0f, 1.0f, 0.0f, 0.0f);
	matrix.rotate(30.0f, 0.0f, 1.0f, 0.0f);
	//matrix.scale(0.009f);
	matrix.scale(0.008f);

	m_program->setUniformValue(m_matrixUniform, matrix);

	glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, &mmVertices[0]); // vertices
	glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, &mmColors[0]); // colors
	glVertexAttribPointer(m_texAttr, 2, GL_FLOAT, GL_FALSE, 0, &mmTex[0]); // texCoords
	m_program->setAttributeValue(m_texWeightAttr, 1.0f);
	m_program->setUniformValue("texture", texture);
	glActiveTexture(GL_TEXTURE0 + 1);
	glBindTexture(GL_TEXTURE_2D, texture);

	glEnableVertexAttribArray(m_posAttr);
	glEnableVertexAttribArray(m_colAttr);
	glEnableVertexAttribArray(m_texAttr);

	glDrawArrays(GL_TRIANGLES, 0, numTriangles * 3); // 6; (2 triangles) how many vertices to render

	glDisableVertexAttribArray(m_texAttr);
	glDisableVertexAttribArray(m_colAttr);
	glDisableVertexAttribArray(m_posAttr);

	m_program->release();

	cv::Mat framebuffer = cv::imread("C:\\Users\\Patrik\\Documents\\GitHub\\box_screenbuffer11.png");
	cv::Mat textureMap = render::utils::MeshUtils::extractTexture(mesh, matrix, viewportWidth, viewportHeight, framebuffer);
	cv::imwrite("C:\\Users\\Patrik\\Documents\\GitHub\\img_extracted11.png", textureMap);
	++m_frame;
}
Example #10
0
void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, this->width(),  this->height());

    int current_width = width();
    int current_height = height();

    // Set orthographic Matrix
    QMatrix4x4 orthoMatrix;

    orthoMatrix.ortho(0.0 +  _scrollOffset.x(),
                      (float)current_width +  _scrollOffset.x(),
                      (float)current_height + _scrollOffset.y(),
                      0.0 + _scrollOffset.y(),
                      -100, 100);

    // Translate the view to the middle
    QMatrix4x4 transformMatrix;
    transformMatrix.setToIdentity();
    transformMatrix.scale(_zoomFactor);

    _shaderProgram->setUniformValue(_mvpMatrixLocation, orthoMatrix * transformMatrix);

    _tilePainter->DrawTiles();

    _shaderProgram->setUniformValue(_use_color_location, (GLfloat)1.0);

    if(_dotsVao.isCreated() && SystemParams::show_grid)
    {
        int verticesPerDot = 4 + 2;
        _dotsVao.bind();
        uint nDots = _gridSize.width() * _gridSize.height();
        nDots += (_gridSize.width() + 1) * (_gridSize.height() + 1);
        for(uint a = 0; a < nDots; a++)
            { glDrawArrays(GL_TRIANGLE_FAN, a * verticesPerDot, verticesPerDot); }
        _dotsVao.release();
    }

    if(_drawBreakVao.isCreated() && _isMouseDown)
    {
        _shaderProgram->setUniformValue(_use_color_location, (GLfloat)1.0);
        glLineWidth(2.0f);
        _drawBreakVao.bind();
        glDrawArrays(GL_LINES, 0, 2);
        _drawBreakVao.release();
    }

    if(_breakLinesVao.isCreated() && SystemParams::show_grid)
    {
        _shaderProgram->setUniformValue(_use_color_location, (GLfloat)1.0);
        glLineWidth(2.0f);
        _breakLinesVao.bind();
        glDrawArrays(GL_LINES, 0, _breakLines.size() * 2);
        _breakLinesVao.release();
    }


    if(_cellLinesVao.isCreated() && SystemParams::show_grid)
    {
        _shaderProgram->setUniformValue(_use_color_location, (GLfloat)1.0);
        glLineWidth(0.5f);
        _cellLinesVao.bind();
        glDrawArrays(GL_LINES, 0, _cellLines.size() * 2);
        _cellLinesVao.release();
    }
}