如何在 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);
main.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
main.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 彩色立方体中选择颜色?的主要内容,如果未能解决你的问题,请参考以下文章