如何在 qml 的 3d 彩色立方体中选择颜色?

Posted

技术标签:

【中文标题】如何在 qml 的 3d 彩色立方体中选择颜色?【英文标题】:How to pick a color in a 3d colored cube in qml? 【发布时间】:2021-08-16 09:58:31 【问题描述】:

我正在使用 QML 开发一个 3D 颜色选择器立方体,我已经开发了立方体纹理,但我不知道如何编码颜色选择。

我希望当我单击立方体面时具有我单击的颜色,是否可以在 qml 中做到这一点?

这是我的立方体代码:

Entity 
    id: root

    Camera 
        id: mainCamera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16/9
        nearPlane : 0.1
        farPlane : 1000.0
        position: Qt.vector3d(0.0, 4.49373, -3.78577)
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: cubeTransform.translation
    

    CustomCameraController 
        id: mainCameraController
        camera: mainCamera
    

    components: [

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(1, 0, 0)

        ,

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(0, 1, 0)

        ,

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(-1, 0, 0)

        ,

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(0, -1, 0)

        ,

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(0, 0, 1)

        ,

        DirectionalLight
            color: "#e0eef0"
            intensity: 0.4
            enabled: true
            worldDirection: Qt.vector3d(0, 0, -1)

        ,


        RenderSettings 

            Viewport 
                normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)

                RenderSurfaceSelector 
                    CameraSelector 
                        id: cameraSelector
                        camera: mainCamera

                        FrustumCulling 

                            ClearBuffers 
                                buffers: ClearBuffers.AllBuffers
                                clearColor: "black"
                                NoDraw 
                            

                            LayerFilter 
                                filterMode: LayerFilter.DiscardAnyMatchingLayers
                                layers: [topLayer]
                            

                            LayerFilter 
                                filterMode: LayerFilter.AcceptAnyMatchingLayers
                                layers: [topLayer]

                                ClearBuffers 
                                    buffers: ClearBuffers.DepthBuffer
                                
                            
                        
                    

                

            
        ,

        InputSettings 
    ]

    Layer 
        id: topLayer
        recursive: true
    

    Entity 
            id: cubeEntity


            Texture2D 
                id: cubeTexture

                TextureImage 
                    source: "qrc:/texture.png"
                
            

            Mesh 
                id: cubeMesh

                source: "qrc:/cube.obj"
            

            Transform 
                id: cubeTransform
            

            ObjectPicker 
                id: cubePicker

                onClicked: 

                    console.log("x : " + pick.localIntersection.normalized().x)
                    console.log("y : " + pick.localIntersection.normalized().y)
                    console.log("z : " + pick.localIntersection.normalized().z)

                
            

            NormalDiffuseMapMaterial
                id: cubeMaterial
                diffuse: cubeTexture
                normal: cubeTexture
                specular: "black"
                shininess: 50
            

            components: [cubeMesh, cubeTransform, cubeMaterial, cubePicker]

    


我补充一下,如果有人可以帮助我,我的实际立方体的图片会很棒

【问题讨论】:

我的话题,我需要帮助,请 立方体上的颜色似乎取决于 x、y 和 z 坐标。那么为什么不直接使用在代码示例中已经检索到的点击坐标呢? 感谢您的回答。我不使用这个点击坐标,因为有时它们是负数,我不理解这个值 它们是负数,因为您的模型具有负的 xyz 坐标,有什么不明白的?坐标不代表颜色,而是您在模型上单击的位置。您可以做的是在第二遍中将您的模型渲染到屏幕外纹理,没有任何闪电但带有纹理。然后,当用户单击时,您使用QRenderCapture 获得渲染并检查颜色。我通过颜色here 实现了实例选择,这应该可以帮助您入门。 嗨!我对 3d 完全不熟悉,而且我不知道如何在我的案例中使用您的示例,因为我为我的立方体使用了一个模式。是否可以进行采访或电话讨论? 【参考方案1】:

这里是使用 qml、opengl 和 c++ 进行颜色选择的答案:

C++ 类

pixelvaluereader.h

#pragma once

#include <QObject>
#include <Qt3DRender/QRenderCaptureReply>

class PixelValueReader : public QObject

  Q_OBJECT
public:
  explicit PixelValueReader(QObject *parent = nullptr);


  Q_INVOKABLE QColor getColor(Qt3DRender::QRenderCaptureReply *reply, int x, int y);

signals:

  void newColor(QColor color);

;

pixelvaluereader.cpp

#include "pixelvaluereader.h"
#include <QDebug>




PixelValueReader::PixelValueReader(QObject* parent)
    : QObject(parent)






QColor PixelValueReader::getColor(Qt3DRender::QRenderCaptureReply* reply, int x, int y)


    QRgb pixel = reply->image().pixel(x, y);

    int red = qRed(pixel);
    int blue = qBlue(pixel);
    int green = qGreen(pixel);
    int alpha = qAlpha(pixel);

    qDebug() << red * 0xFF000000 + green * 0xFF0000 + blue * 0xFF00 + alpha;

    if (red * 0xFF000000 + green * 0xFF0000 + blue * 0xFF00 + alpha > 0) 
      emit newColor(QColor(pixel));
      qDebug() << "color : " << QColor(pixel).name(); // here is the color of the pixel

    
    // RGBA captures the ID but since we masked and right shifted the respective values in the shader
    // (e.g. (red & 0xFF000000) >> 24 for red) to prevent overflow in the color values we have to
    // undo the shift here again.
    return QColor(pixel);

ma​​in.cpp

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


#include "pixelvaluereader.h"

//Q_DECLARE_METATYPE(Qt3DRender::QAbstractTextureImage)

    int main(int argc, char* argv[])
    
      QGuiApplication app(argc, argv);
    
      QVector<QVector3D> pos;
      pos << QVector3D(1, 1, 0);
      pos << QVector3D(-1, 2, 8);
      pos << QVector3D(1, 1, 7);
      pos << QVector3D(0, 0, 4);
      pos << QVector3D(1, 5, 1);
      pos << QVector3D(-3, 3, 0);
      pos << QVector3D(2, 2, -2);
    
    
      PixelValueReader *valueReader = new PixelValueReader();
      qmlRegisterType<PixelValueReader>("PixelValueReader", 1, 0, "PixelValueReader");
    
    
      Qt3DExtras::Quick::Qt3DQuickWindow view;
      view.setTitle("Instanced Rendering");
      view.resize(1600, 800);
      view.engine()->qmlEngine()->rootContext()->setContextProperty("_window", &view);
      view.engine()->qmlEngine()->rootContext()->setContextProperty("pixelValueReader", valueReader);
      view.setSource(QUrl("qrc:/main.qml"));
      view.show();
    
      return app.exec();
    

Opengl

对于 opengl 代码,您可以在 Florian Blume git 项目中找到它:here

QML

ma​​in.qml

import QtQuick 2.1 as QQ2
import Qt3D.Core 2.0
import Qt3D.Render 2.10
import Qt3D.Input 2.0
import Qt3D.Extras 2.0

Entity 

    components: [
        rendSettings,
        inputSettings,
        light1,
        light2,
        light3,
        light4,
        light5,
        light6
    ]

    DirectionalLight
        id: light1
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(1, 0, 0)

    

    DirectionalLight
        id: light2
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(0, 1, 0)

    

    DirectionalLight
        id: light3
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(-1, 0, 0)

    

    DirectionalLight
        id: light4
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(0, -1, 0)

    

    DirectionalLight
        id: light5
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(0, 0, 1)

    

    DirectionalLight
        id: light6
        color: "#e0eef0"
        intensity: 0.4
        enabled: true
        worldDirection: Qt.vector3d(0, 0, -1)

    

    InputSettings  id: inputSettings 

    RenderSettings 
        id: rendSettings
        activeFrameGraph: RenderSurfaceSelector 
            id: surfaceSelector
            Viewport 
                normalizedRect: Qt.rect(0, 0, 1, 1)
                CameraSelector 
                    camera: camera
                    ClearBuffers 
                        buffers: ClearBuffers.ColorDepthBuffer
                        clearColor: "transparent"
                        FrustumCulling 
                            DepthTest 
                                depthFunction: DepthTest.LessOrEqual

                                RenderPassFilter 
                                    matchAny: []
                                
                                RenderPassFilter 
                                    matchAny: []
                                    RenderTargetSelector 
                                        target: rt
                                        TextureRenderTarget 
                                            id: rt
                                            width: surfaceSelector.surface ? surfaceSelector.surface.width : 512
                                            height: surfaceSelector.surface ? surfaceSelector.surface.height : 256
                                        
                                        RenderCapture 
                                            id: renderCapture
                                        
                                    
                                
                            

                        
                    
                
            
        

    

    MouseDevice 
        id: mouseDevice
    

    MouseHandler 
        sourceDevice: mouseDevice

        property var reply
        property bool isHold: false
        property var x
        property var y

        onReleased: 
            if (!isHold) 
                x = mouse.x
                y = mouse.y
                doRenderCapture()
            

            isHold = false;
        


        onPositionChanged: 
            if (mouse.buttons === 1)
                isHold = true
            

        

        function doRenderCapture() 
            reply = renderCapture.requestCapture()
            reply.completeChanged.connect(onRenderCaptureCompleted)
        

        function onRenderCaptureCompleted() 
            var color = pixelValueReader.getColor(reply, x, y)
        

    

    Camera 
        id: camera
        projectionType: CameraLens.PerspectiveProjection
        fieldOfView: 45
        aspectRatio: 16/9
        nearPlane : 0.1
        farPlane : 1000.0
        position: Qt.vector3d(0.0, 4.49373, -3.78577)
        upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
        viewCenter: cubeTransform.translation
    

    CustomCameraController camera: camera

    Entity 
            id: cubeEntity


            Texture2D 
                id: cubeTexture

                TextureImage 
                    source: "qrc:/texture.png"
                
            

            Mesh 
                id: cubeMesh

                source: "qrc:/cube.obj"
            

            Transform 
                id: cubeTransform
            

            NormalDiffuseMapMaterial
                id: cubeMaterial
                diffuse: cubeTexture
                normal: cubeTexture
                specular: "black"
                shininess: 50
            

            components: [cubeMesh, cubeTransform, cubeMaterial]

    


TextureRenderTarget.qml

import Qt3D.Core 2.0
import Qt3D.Render 2.0

RenderTarget 
    id: rt

    property real width: 512
    property real height: 512

    property alias colorTexture: colorTexture
    property variant depthTexture

    attachments : [
        RenderTargetOutput 
            attachmentPoint: RenderTargetOutput.Color0
            texture: Texture2D 
                id: colorTexture
                width: rt.width
                height: rt.height
                format: Texture.RGBA8_UNorm
                minificationFilter: Texture.Linear
                magnificationFilter: Texture.Linear
            
        ,
        RenderTargetOutput 
            attachmentPoint: RenderTargetOutput.Depth
            texture : Texture2D 
                id: depthTexture
                width: rt.width
                height: rt.height
                format: Texture.D32
                minificationFilter: Texture.Linear
                magnificationFilter: Texture.Linear
                comparisonFunction: Texture.CompareLessEqual
                comparisonMode: Texture.CompareRefToTexture
            
        
    ]

我的 CustomCameraController 没有改变

【讨论】:

以上是关于如何在 qml 的 3d 彩色立方体中选择颜色?的主要内容,如果未能解决你的问题,请参考以下文章

求教QML RadioButton单选问题

Unity3D中改变模型的颜色问题

如何css制作3d旋转立方体效果?

如何使用 Three.js 更改立方体的颜色

如何将编辑器中的彩色代码复制word中保持原来的颜色?

QML 加载并显示具有颜色属性的 .ply 网格