Управление непрозрачностью текстурированного 3D-объекта в QML - PullRequest
3 голосов
/ 18 апреля 2020

Я немного новичок в Qt 3D в QML и пытаюсь контролировать непрозрачность текстурированного 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-объектов, но также без потери текстуры?

Редактировать:

Я принял ответ Флориана Блюма, и поскольку ответ основан на репозитории Github, я решил, что лучше иметь этот код и здесь, на StackOverflow, если с ним случится что-то плохое ветвь хранилища веток. Поэтому я опубликую здесь источники, которые полностью обеспечивают работу проекта.

simpleqml3d.pro

TEMPLATE = app

QT += core gui widgets 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras
CONFIG += c++11

SOURCES += main.cpp

RESOURCES += resources.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

main. cpp

/****************************************************************************
**
** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#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;

        // Expose the window as a context property so we can set the aspect ratio
    view.engine()->qmlEngine()->rootContext()->setContextProperty("_window", &view);
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

    return app.exec();
}

resources.qr c

<RCC>
    <qresource prefix="/">
        <file>main.qml</file>
        <file>IronMan.qml</file>
        <file>man.obj</file>
        <file>man.png</file>
        <file>TextureAlphaMaterial.qml</file>
    </qresource>
    <qresource prefix="/shaders">
        <file>unlittexture.frag</file>
        <file>unlittexture.vert</file>
    </qresource>
</RCC>

main.qml

/****************************************************************************
**
** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

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
                            NoDepthMask {}
                        }
                    }
                }
            }
        },
        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
        ]
    }
    IronMan {
        id: ironMan
    }
}

IronMan.qml

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

import QtQml 2.14

Entity {
    id: root

    property vector3d position: Qt.vector3d(0, 0, 0)
    property real scale: 1.0
    property real rotationAngle: 0.0
    property vector3d rotationAxis: Qt.vector3d(1, 0, 0)
    property alias source: mesh.source
    property Material material

    components: [ transform, mesh, material ]

    Transform {
        id: transform
        scale: root.scale
        rotation: fromAxisAndAngle(root.rotationAxis, root.rotationAngle)
        translation: root.position
    }

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

    material: TextureAlphaMaterial {
        id: material

        opacity: 0.5
    }
}

TextureAlphaMaterial.qml

import Qt3D.Core 2.0
import Qt3D.Render 2.0

Material {
    id: root

    property real opacity: 1.

    parameters: [
        Parameter {
            name: "diffuseTexture"
            value: Texture2D {
                textureImages: [
                    TextureImage {
                        source: "qrc:/man.png"
                    }
                ]
            }
        }
    ]

    effect: Effect {
        id: rootEffect

        parameters: [
            Parameter
            {
                name: "opacity"
                value: root.opacity
            }
        ]
        techniques: [
            Technique {
                graphicsApiFilter {
                    api: GraphicsApiFilter.OpenGL
                    profile: GraphicsApiFilter.CoreProfile
                    majorVersion: 3
                    minorVersion: 1
                }

                filterKeys: [ FilterKey { name: "renderingStyle"; value: "forward" } ]

                renderPasses: [
                    RenderPass {
                        shaderProgram: ShaderProgram {
                            vertexShaderCode:   loadSource("qrc:/shaders/unlittexture.vert")
                            fragmentShaderCode: loadSource("qrc:/shaders/unlittexture.frag")
                        } 
                        renderStates: [
                            DepthTest {
                                depthFunction: DepthTest.LessOrEqual
                            },
                            NoDepthMask {
                            },
                            BlendEquation {
                                blendFunction: BlendEquation.Add
                            },
                            BlendEquationArguments {
                                sourceRgb: BlendEquationArguments.One
                                destinationRgb: BlendEquationArguments.OneMinusSourceAlpha
                                sourceAlpha: BlendEquationArguments.One
                                destinationAlpha: BlendEquationArguments.OneMinusSourceAlpha
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

unlittexture.frag

#version 150 core

uniform sampler2D diffuseTexture;
uniform float opacity;

in vec3 position;
in vec2 texCoord;

out vec4 fragColor;


void main()
{
    fragColor = vec4(texture(diffuseTexture, texCoord).xyz * opacity, opacity);
}

unlittexture.vert

#version 150 core

in vec3 vertexPosition;
in vec2 vertexTexCoord;

out vec3 position;
out vec2 texCoord;

uniform mat4 modelView;
uniform mat4 mvp;

void main()
{
    vec3 t = vec3(vertexTexCoord, 1.0);
    texCoord = (t / t.z).xy;
    position = vec3(modelView * vec4(vertexPosition, 1.0));

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

Примечание:

Вы можете заменить man.obj и man.png на любую 3D-модель (экспортированную в obj с помощью Blender или любой другой 3D программное обеспечение) или сопоставленные текстуры соответственно. Тем не менее, их можно найти в хранилище Флориана или в хранилище трипольского администратора .

Это конечный результат:

enter image description here

1 Ответ

1 голос
/ 22 апреля 2020

Редактировать 2

Я изменил ваш проект. Теперь он показывает модель с прозрачной текстурой, вы можете найти ее на GitHub . Обязательно ознакомьтесь с веткой transparent_texture.

. Я не реализовал функциональность, которая позволяет динамически устанавливать прозрачность, но я думаю, что вы можете сделать это самостоятельно, начиная с примера. Модель также не горит, т. Е. Отображается только текстура без какой-либо молнии, но легко реализовать некоторую простую фоновую молнию, посмотрев на другие материалы Qt3D.


Оригинальный ответ

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
        }
    }
}

Я упростил ваш пример, чтобы выяснить причину проблемы, и похоже, что вы использовали неверный механизм QML в main.cpp. Но я бы посоветовал вам попробовать пример Scene3DView, потому что прозрачность работает с такой же настройкой, как ваша (если вам нужны кнопки в вашем пользовательском интерфейсе). Я часто использую примеры и модифицирую их под свои нужды. Я просто хотел, чтобы вы начали с кода, который я предоставил.

Если вы спросите себя, почему у меня там LayerFilters, зацените мой ответ , который объясняет, почему это необходимо, когда у вас есть Прозрачные объекты в вашей сцене.

Прозрачные текстурированные объекты

Это сложнее (и, к сожалению, у меня нет времени, чтобы привести пример кода, возможно, запустите, а затем задавайте вопросы, когда что-то не так Работа). Здесь вы должны реализовать свой собственный шейдер. Qt3D просто не предлагает никаких готовых реализаций, учитывающих альфа. Один репозиторий, который мне всегда очень помог, - это q3dpostpro c репозиторий . Вы можете увидеть, как вы можете создавать свои собственные материалы Qt3D, загружать свои собственные шейдеры и передавать им параметры.

Есть также пример Advanced Custom Material, который может помочь вам в создании пользовательских шейдеров и передаче их дальше. параметры.

Если вы хотите увидеть, как текстурировать объект в шейдере, извлеките шейдер из QTextureMaterial и его код . Я пытался воссоздать его в QML, но это не сработало сразу.

Я бы посоветовал вам поиграться с кодом q3dpostpro c и попытаться текстурировать один из объектов (структуру Проект немного сложнее, потому что это витрина, но через некоторое время все это имеет смысл). У него уже есть шейдер, который использует текстурирование, потому что он сначала выводит aws все в буфер за пределами экрана, а затем использует эту текстуру для рисования экрана. После того, как вы успешно текстурировали один из объектов с помощью своего собственного шейдера, вы можете сделать в нем что-то вроде этого:

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

Это должно дать вам прозрачную текстуру. Вам, вероятно, просто нужно заменить texture(...).xyz в конце на что-то более сложное, когда вы хотите, чтобы текстуры были освещены правильно. Но для этого вы можете проверить фонг-шейдер в репозитории Qt3D GitHub, который я связал, или получить его из этого репозитория или где-то еще из inte rnet.

Я надеюсь, что эта информация помогает.


Редактировать 1

Я изменил код q3dpostpro c, чтобы показывать прозрачные текстуры в ветви GitHub . Объекты еще не освещены, но это должно прояснить функционирование.

...