如何使用 qml 将多个纹理图像或一个图像应用到 qt 6 中的立方体中?

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

你好,我正在使用 QTCreator 和 qml 学习 Qt 3d 6.4.2 版本,在研究了官方 qt 文档,甚至在堆栈溢出中,我没有找到一种方法将多个图像作为立方体的面或一个纹理图像映射,我尝试使用 CubeMapTexture 但出现错误,我也尝试使用材质,但我也不能

这是重现的最小代码

import QtQuick
import QtQuick3D
import QtQuick3D.Effects
import QtQuick3D.Helpers
import QtQuick.Controls
import QtQuick.Layouts

Window {
    id: window
    width: 1280
    height: 720
    visible: true
    title: "Example"
    color: "#848895"

    SplitView {
        id: splitView
        anchors.fill: parent

        View3D {
            id: viewport
            SplitView.fillHeight: true
            SplitView.fillWidth: true
            SplitView.minimumWidth: splitView.width * 0.5
            environment: SceneEnvironment {
                property bool enableEffects: false
                antialiasingMode: SceneEnvironment.MSAA
                antialiasingQuality: SceneEnvironment.High
                lightProbe: Texture {
                    source: "maps/OpenfootageNET_garage-1024.hdr"
                }
                effects: enableEffects ? [bloom, scurveTonemap] : []
                backgroundMode: SceneEnvironment.SkyBox

                SCurveTonemap {
                    id: scurveTonemap
                }
                HDRBloomTonemap {
                    id: bloom
                }
            }

            Node {
                id: originNode
                PerspectiveCamera {
                    id: cameraNode
                    z: 600
                    clipNear: 1
                    clipFar: 10000
                }
            }

            PrincipledMaterial {
                id: basicMaterial
                baseColorMap: CubeMapTexture{
                    source: "maps/side.png"
                }
            }

            Model {
                id: cube
                source: "#Cube"
                materials: basicMaterial
                pickable: true
            }


            OrbitCameraController {
                origin: originNode
                camera: cameraNode
            }

            MouseArea {
                id: pickController
                anchors.fill: parent
                onClicked: function(mouse) {
                    let pickResult = viewport.pick(mouse.x, mouse.y);
                    if (pickResult.objectHit) {
                        let pickedObject = pickResult.objectHit;
                        // Move the camera orbit origin to be the clicked object
                        originNode.position = pickedObject.position
                    }
                }
            }

        }
    }
}

使用 CubeMapTexture 的错误是“Sampler qt_BaseColorMap_sampler 需要 2D 纹理,但关联的纹理是立方体贴图。这会导致问题。” 但在其他方面,我无法将多个纹理放入立方体中,或者只能将一个纹理放入其中并进行映射。

qt qml qt6 qt3d
1个回答
1
投票

对于

Texture
,请考虑使用
sourceItem
。这将允许您使用传统的 2D 组件(例如
Image
)作为纹理。在我的示例中,我使用了 SVG 图像,以便我可以快速将矢量图形的混合应用到我的纹理。对于您来说,您不必限制自己使用
Image
作为您的
sourceItem
。您可以选择任何 2D 组件,例如
Item
Rectangle
Text
Label
Canvas
Shape

      materials: [
           DefaultMaterial {
                diffuseMap: Texture {
                    sourceItem: Image {
                        anchors.centerIn: parent
                        width: 224
                        height: 224
                        source: "Dice1.svg"
                        sourceSize: Qt.size(width, height)
                        cache: false
                    }
                }
            }
        ]

如果您使用“#Cube”,则您使用的材质在所有 6 个面上都将相同。如果切换为使用 6 个“#Rectangle”,则可以为每个矩形使用不同的材质。我们可以使用这种技术来创建 6 面骰子。骰子的每个面都使用自己的 SVG 图像进行渲染:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D
Page {
    id: page
    background: Rectangle { color: "#848895" }
    header: Frame {
        background: Rectangle { color: "#eee" }
        CheckBox { id: chkLabels; text: qsTr("Labels"); checked: true }
    }
    Node {
        id: standAloneScene
        DirectionalLight { ambientColor: Qt.rgba(1.0, 1.0, 1.0, 1.0) }
        Node {
            id: node
            Repeater3D {
                model: [
                    ["Dice1.svg", 0, 0 ],
                    ["Dice6.svg", 0, 180 ],
                    ["Dice3.svg", 0, 90 ],
                    ["Dice4.svg", 0, -90 ],
                    ["Dice2.svg", 90, 0 ],
                    ["Dice5.svg", -90, 0 ],
                ]
                delegate: Node {
                    eulerRotation.x: modelData[1]
                    eulerRotation.y: modelData[2]
                    Model {
                        source: "#Rectangle"
                        materials: [
                            DefaultMaterial {
                                diffuseMap: Texture {
                                    sourceItem: Item {
                                        anchors.centerIn: parent
                                        width: 224
                                        height: 224
                                        Image {
                                            anchors.fill: parent
                                            source: modelData[0]
                                            sourceSize: Qt.size(width, height)
                                            cache: false
                                        }
                                        Label {
                                            visible: chkLabels.checked
                                            anchors.horizontalCenter: parent.horizontalCenter
                                            anchors.bottom: parent.bottom
                                            anchors.bottomMargin: 10
                                            text: modelData[0]
                                            color: "white"
                                            Rectangle {
                                                anchors.fill: parent
                                                anchors.margins: -5
                                                color: "blue"
                                                border.color: "yellow"
                                                radius: 5
                                                z: -2
                                            }
                                        }
                                    }
                                }
                            }
                        ]
                        z: 50
                    }
                }
            }
        }
        OrthographicCamera {
            id: cameraOrthographicFront
            lookAtNode: node
            y: 800; z: 1000
            property double sc: 300/Math.max(Math.min(page.width, page.height), 1)
            scale: Qt.vector3d(sc, sc, 1)
        }
    }
    View3D {
        anchors.fill: parent
        importScene: standAloneScene
        camera: cameraOrthographicFront
    }
    NumberAnimation {
        target: node
        property: "eulerRotation.y"
        loops: Animation.Infinite
        running: true
        from: 720; to: 0
        duration: 10000
    }
    NumberAnimation {
        target: node
        property: "eulerRotation.x"
        loops: Animation.Infinite
        running: true
        from: 360; to: 0
        duration: 10000
    }
}

// Dice1.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="16" cy="16" r="4" fill="#800"/>
</svg>

// Dice2.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice3.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="16" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice4.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#800"/>
<circle cx="24" cy="8" r="3" fill="#800"/>
<circle cx="8" cy="24" r="3" fill="#800"/>
<circle cx="24" cy="24" r="3" fill="#800"/>
</svg>

// Dice5.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#ccc"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="16" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
<circle cx="24" cy="24" r="3" fill="#ccc"/>
</svg>

// Dice6.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#444"/>
<circle cx="8" cy="8" r="3" fill="#ccc"/>
<circle cx="8" cy="16" r="3" fill="#ccc"/>
<circle cx="8" cy="24" r="3" fill="#ccc"/>
<circle cx="24" cy="8" r="3" fill="#ccc"/>
<circle cx="24" cy="16" r="3" fill="#ccc"/>
<circle cx="24" cy="24" r="3" fill="#ccc"/>
</svg>

您可以在线尝试!

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