首页 > 解决方案 > 给定具有两个输出变量的顶点着色器,如何在 Qt3D 中正确定义两个 QRenderTargets 以获得深度和颜色信息

问题描述

我的公司使用 Qt3D 来显示其 CAD 图形。对于这个应用程序,有必要实现像素正确的顺序无关透明度。作为实现这一目标的第一步,我尝试编写一个小应用程序,它将一个简单的平面渲染到深度纹理和一个 rgba 纹理。

这是我的“小”示例应用程序:

主文件

#include <QApplication>
#include <Qt3DRender/QTechniqueFilter>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QTextureImage>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QTexture>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DExtras/QTextureMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QRenderTarget>
#include <Qt3DRender/QRenderTargetOutput>
#include <Qt3DRender/QRenderTargetSelector>
#include <QDebug>
#include "TextureMaterial.h"

namespace {
    Qt3DCore::QEntity* createPlane()
    {
        auto entity = new Qt3DCore::QEntity;

        auto mesh = new Qt3DExtras::QPlaneMesh;
        mesh->setWidth(0.3);
        mesh->setHeight(0.3);
        entity->addComponent(mesh);

        return entity;
    }
}

void main(int argc, char** args) {
    QApplication app(argc, args);

    auto view = new Qt3DExtras::Qt3DWindow();

    auto mClearBuffers = new Qt3DRender::QClearBuffers;
    auto mMainCameraSelector = new Qt3DRender::QCameraSelector;
    mMainCameraSelector->setCamera(view->camera());
    auto mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
    auto mMainViewport = new Qt3DRender::QViewport;
    mMainViewport->setNormalizedRect(QRectF(0, 0, 1, 1));

    mClearBuffers->setClearColor(Qt::lightGray);
    mClearBuffers->setBuffers(Qt3DRender::QClearBuffers::BufferType::ColorDepthBuffer);
    mClearBuffers->setParent(mMainCameraSelector);

    mRenderSurfaceSelector->setParent(mMainViewport);
    mMainCameraSelector->setParent(mRenderSurfaceSelector);

    auto renderTargetSelector = new Qt3DRender::QRenderTargetSelector(mMainCameraSelector);
    auto renderTarget = new Qt3DRender::QRenderTarget(renderTargetSelector);
    { // Depth Texture Output

        auto depthTexture = new Qt3DRender::QTexture2D;
        depthTexture->setSize(400, 300);
        depthTexture->setFormat(Qt3DRender::QAbstractTexture::TextureFormat::DepthFormat);

        auto renderTargetOutput = new Qt3DRender::QRenderTargetOutput;
        renderTargetOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::AttachmentPoint::Depth);
        renderTargetOutput->setTexture(depthTexture);

        renderTarget->addOutput(renderTargetOutput);
    }
    {// Image Texture Output
        auto imageTexture = new Qt3DRender::QTexture2D;

        imageTexture->setSize(400, 300);
        imageTexture->setFormat(Qt3DRender::QAbstractTexture::TextureFormat::RGBA32F);
        auto renderTargetOutput = new Qt3DRender::QRenderTargetOutput;
        renderTargetOutput->setAttachmentPoint(Qt3DRender::QRenderTargetOutput::AttachmentPoint::Color1);
        renderTargetOutput->setTexture(imageTexture);

        renderTarget->addOutput(renderTargetOutput);
    }

    view->setActiveFrameGraph(mMainViewport);
    view->activeFrameGraph()->dumpObjectTree();

    auto rootEntity = new Qt3DCore::QEntity();
    view->setRootEntity(rootEntity);

    auto cameraEntity = view->camera();
    cameraEntity->lens()->setPerspectiveProjection(45.0f, 1., 0.1f, 10000.0f);
    cameraEntity->setPosition(QVector3D(0, 0.3, 0));
    cameraEntity->setUpVector(QVector3D(0, 1, 0));
    cameraEntity->setViewCenter(QVector3D(0, 0, 0));

    {
        auto mat = new TextureMaterial;
        auto plane = createPlane();
        plane->setParent(rootEntity);
        auto trans = new Qt3DCore::QTransform;
        //trans->setTranslation(QVector3D(0, -2, 0));
        trans->setRotation(QQuaternion::fromAxisAndAngle({ 1,0,0 }, 80));
        plane->addComponent(trans);
        plane->addComponent(mat);
    }

    view->setWidth(400);
    view->setHeight(300);
    view->show();
    app.exec();

}

纹理材料.h

#pragma once

#include <Qt3DRender/QMaterial>

namespace Qt3DRender {
    class QTechnique;
    class QRenderPass;
    class QShaderProgram;
}

class TextureMaterial : public Qt3DRender::QMaterial
{
    Q_OBJECT

public:
    explicit TextureMaterial(Qt3DCore::QNode* parent = nullptr);
    ~TextureMaterial();
};

纹理材料.cpp

#include "TextureMaterial.h"

#include <Qt3DRender/QMaterial>
#include <Qt3DRender/QEffect>
#include <Qt3DRender/QTechnique>
#include <Qt3DRender/QShaderProgram>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QGraphicsApiFilter>
#include <Qt3DRender/QAbstractTexture>
#include <QUrl>

TextureMaterial::TextureMaterial(Qt3DCore::QNode* parent) : QMaterial(parent)
{
    auto colorParm = new Qt3DRender::QParameter(QStringLiteral("diffuseColor"), QColor::fromRgbF(0.0,1.0,0.1,0.8)); // Green!!!
    auto shaderProgram = new Qt3DRender::QShaderProgram;
    shaderProgram->setVertexShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shader.vert"))));
    shaderProgram->setFragmentShaderCode(Qt3DRender::QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shader.frag"))));
    auto technique = new Qt3DRender::QTechnique;
    technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL);
    technique->graphicsApiFilter()->setMajorVersion(3);
    technique->graphicsApiFilter()->setMinorVersion(1);
    technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile);

    auto renderPass = new Qt3DRender::QRenderPass;
    renderPass->setShaderProgram(shaderProgram);

    technique->addRenderPass(renderPass);
    auto effect = new  Qt3DRender::QEffect;
    effect->addTechnique(technique);
    effect->addParameter(colorParm);

    setEffect(effect);
}

TextureMaterial::~TextureMaterial()
{
}

着色器.frag

#version 150 core

uniform vec4 diffuseColor;
in vec3 position;

out vec4 blendedColor;
out float depth;

void main()
{
    depth=gl_FragCoord.z; 
    blendedColor=diffuseColor; 
}

着色器.vert

#version 150 core

in vec3 vertexPosition;
out vec3 position;

uniform mat4 modelView;
uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4( vertexPosition, 1.0 );
}

文件.qrc

<!DOCTYPE RCC><RCC version="1.0">
    <qresource prefix="/">
      <file>shader.frag</file>
      <file>shader.vert</file>
    </qresource>
</RCC>

因为,片段着色器的所有输出都应该渲染到这两个纹理,我希望在我的Qt3dWindow.

令人惊讶的是,有一些输出取决于我的片段着色器blendedColordepth在我的片段着色器中的定义顺序。

如果首先定义深度,我会看到深度缓冲区,如果blendedColor先定义,我会看到diffuseColor.

这是我将看到的:

首先定义深度变量

首先定义 blendedColor out 变量

基本上,我有两个问题:

  1. 如果我的渲染目标是纹理,为什么我可以在查看器中看到depthand ?blendedColor
  2. 我如何检查纹理中渲染的内容depthTextureimageTexture
    • 例如,有没有办法将这些纹理保存为图像?

标签: c++qtopenglglslqt3d

解决方案


推荐阅读