控制QML中的纹理3D对象不透明度

问题描述 投票:2回答:1

我对QML中的Qt 3D有点陌生,我正在尝试控制textured 3D对象的不透明度。为此,我正在使用simpleqml3d测试项目。

我玩过这些材料,但无法使用。这是我从IronMan.qml测试项目中修改的simpleqml3d实体:

import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Extras 2.0

Entity {
    id: root

    property real x: 0
    property real y: 0
    property real z: 0
    property real scale: 1.0

    Texture2D{
        id: texture
        TextureImage {
            source: "qrc:/man.png"
        }
    }

    //COPY RenderableEntity.qml in your project!!!!!!
    RenderableEntity{
        id: chest
        source: "qrc:/man.obj" //Path to iron man model. You can open it with 3D Builder on Windows 10
        position: Qt.vector3d(root.x, root.y, root.z)
        scale:  root.scale

//        material: DiffuseMapMaterial {
//            id: material
//            diffuse:  texture
//            specular: Qt.rgba( 0.2, 0.2, 0.2, 1.0 )
//            shininess: 2.0
//        }

//        material: DiffuseMapMaterial {
//            diffuse:  texture
//            specular: Qt.rgba( 0.2, 0.2, 0.2, 1.0 )
//            shininess: 2.0
//        }

//        material: DiffuseSpecularMaterial {
//            alphaBlending: true
//            diffuse: Qt.rgba(0.2, 0.2, 0.2, 0.0)//texture
//            specular: texture//Qt.rgba(0.2, 0.2, 0.2, 0.5)
//            shininess: 2.0
//        }

//        material: PhongMaterial {
//            ambient: Qt.rgba( 1, 0, 0, 0 )
//            diffuse: Qt.rgba( 1, 0, 0, 0 )
//            shininess: 50
//        }

//        material: PhongAlphaMaterial {
//            alpha: 0.0
//            diffuse: Qt.rgba(0.2, 0.2, 0.2, 0.0)//texture
//            specular: Qt.rgba(0.2, 0.2, 0.2, 0.0)
//            shininess: 2.0
//        }

        material: PhongAlphaMaterial {
            alpha: 0.0
            ambient: Qt.rgba( 1, 0, 0, 0 )
            diffuse: Qt.rgba( 1, 0, 0, 0 )
            shininess: 50
        }
    }
}

评论的材料是我玩过的材料。即使使用PhongAlphaMaterial,我也无法使用,当不透明度设置为0.0时,模型仍显示为:

enter image description here

[有人可以帮助我控制带纹理的3D对象的不透明度,但又不会失去纹理吗?

qt opengl qt5 shader qt3d
1个回答
0
投票

Qt3D没有为透明纹理对象提供材料,这意味着您必须自己实现它。我稍后再讲。


简单透明

关于您的透明度问题,我试用了代码,使以下内容可以工作,但没有按钮:

main.cpp

#include <Qt3DQuickExtras/qt3dquickwindow.h>
#include <Qt3DQuick/QQmlAspectEngine>
#include <QGuiApplication>
#include <QQmlEngine>
#include <QQmlContext>

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);
    Qt3DExtras::Quick::Qt3DQuickWindow view;

    view.engine()->qmlEngine()->rootContext()->setContextProperty("_window", &view);
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

    return app.exec();
}

main.qml

import QtQuick 2.1
import Qt3D.Core 2.0
import Qt3D.Render 2.9
import Qt3D.Input 2.0
import Qt3D.Extras 2.9

Entity {
    id: root
    objectName: "root"

    // Use the renderer configuration specified in ForwardRenderer.qml
    // and render from the mainCamera
    components: [
        RenderSettings {
            activeFrameGraph: RenderSurfaceSelector {
                id: renderSurfaceSelector

                CameraSelector {
                    id: cameraSelector
                    camera: camera
                    Viewport {
                        id: viewport
                        normalizedRect: Qt.rect(0, 0, 1, 1)
                        ClearBuffers {
                            buffers: ClearBuffers.AllBuffers
                            clearColor: "white"
                            NoDraw{}
                        }
                        LayerFilter {
                            layers: [opaqueLayer]

                        }
                        LayerFilter {
                            layers: [opaqueLayer]
                            filterMode: LayerFilter.DiscardAllMatchingLayers
                        }
                    }
                }
            }
        },
        // Event Source will be set by the Qt3DQuickWindow
        InputSettings { }
    ]

    Camera {
        id: camera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        nearPlane : 0.1
        farPlane : 1000.0
        position: Qt.vector3d( 0.0, 4.0, -5.0 )
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
    }

    FirstPersonCameraController { camera: camera }

    Entity {
        components: [
            PointLight {
                enabled: parent.enabled
                color: "black"
                intensity: 0
            }
        ]
    }

    Entity {
        PlaneMesh {
            id: groundMesh
            width: 50
            height: width
            meshResolution: Qt.size(2, 2)
        }

        Transform {
            id: groundTransform
            translation: Qt.vector3d(0, 0, 0)
        }

        Layer {
            id: opaqueLayer
        }

        PhongMaterial {
            id: material
            diffuse: Qt.rgba( 0.5, 0.5, 0.5, 1 )
            ambient: Qt.rgba( 0.5, 0.5, 0.5, 1 )
        }

        components: [
            groundMesh,
            groundTransform,
            material,
            opaqueLayer
        ]
    }

    Entity {
        id: sphere1

        Mesh {
            id: man
            source: "qrc:/man.obj"
        }

        components: [
            man,
            matSphere1Material
        ]

        PhongAlphaMaterial {
            id: matSphere1Material
            alpha: 0.1
            ambient: Qt.rgba( 1, 1, 0, 0.0 )
            diffuse: Qt.rgba( 1, 1, 0, 0.0 )
            shininess: 50
        }
    }
}

我简化了示例,以找出问题所在,并且看起来您在main.cpp中使用了错误的QML引擎。但是我建议您尝试一下Scene3DView示例,因为透明度可以与类似的设置一起使用(如果您的UI需要按钮)。我经常使用这些示例,并根据需要对其进行修改。我只是想让您开始使用我提供的代码。

如果问自己为什么我在那里有LayerFilters,请检查我的answer,这说明了为什么场景中有透明物体时,这是必要的。


透明纹理对象

这比较困难(而且我没有时间提供示例代码,不幸的是,也许在某些不起作用的时候开始然后提出问题)。在这里,您必须实现自己的着色器。 Qt3D根本不提供任何考虑alpha的现成实现。 q3dpostproc repository是一个对我很有帮助的存储库。您可以看到如何构建自己的Qt3D材质,加载自己的着色器并将参数传递给它们。

还有高级自定义材质示例,该示例可以为如何创建自定义着色器和传递参数提供很多帮助。

如果要查看如何在着色器中对对象进行纹理化,请签出shader of QTextureMaterial及其code。我试图在QML中重新创建它,但没有立即起作用。

我建议您尝试使用q3dpostproc代码,并尝试在其中纹理一个对象(该项目的结构有点复杂,因为它是一个展示,但是过了一会儿才有意义)。它已经具有使用纹理的着色器,因为它首先将所有内容绘制到屏幕外缓冲区,然后使用该纹理绘制屏幕。在使用自己的着色器成功纹理化了一个对象之后,您可以在其中执行以下操作:

fragColor = vec4(texture(...).xyz, 0.5);

这应该为您提供透明的纹理。最后,当您想使纹理正确照明时,可能只需要用更复杂的内容替换texture(...).xyz。但是为此,您可以在我链接的Qt3D GitHub存储库中检出phong着色器,或者从this repository或从Internet的其他地方获取一个。

希望此信息对您有所帮助。


编辑

我修改了q3dpostproc代码,以在GitHub branch中显示透明纹理。对象还没有点亮,但这应该使功能更清晰。

© www.soinside.com 2019 - 2024. All rights reserved.