Qt6 3D绘制三角形报错及无法显示问题求助
解决Qt6 3D绘制三角形的输入布局错误与显示问题
错误原因分析
控制台的Failed to create input layout错误,是因为你使用的QPhongMaterial要求几何体必须提供法线属性,但你的代码只定义了位置属性,渲染管线无法匹配材质所需的输入布局,从而抛出参数错误(0x80070057)。注释材质后错误消失,是因为没有了材质对法线的强制要求,但缺少合适的材质或相机设置导致三角形仍无法显示。
修复步骤
1. 解决材质管线错误
有两种可选方案:
方案A:改用无需法线的材质
替换QPhongMaterial为QUnlitMaterial或QFlatMaterial,这类材质只需要位置属性即可正常工作:
Qt3DExtras::QUnlitMaterial* material = new Qt3DExtras::QUnlitMaterial(); material->setColor(QColor("#686A63"));
方案B:为几何体添加法线属性
如果坚持使用QPhongMaterial,需要给每个顶点添加法线数据(平面三角形的法线可以统一设为z轴方向):
// 添加法线数据 QByteArray normalBufferData; normalBufferData.resize(3 * sizeof(QVector3D)); QVector3D* normals = reinterpret_cast<QVector3D*>(normalBufferData.data()); // 平面三角形法线指向z轴正方向 normals[0] = QVector3D(0.0f, 0.0f, 1.0f); normals[1] = QVector3D(0.0f, 0.0f, 1.0f); normals[2] = QVector3D(0.0f, 0.0f, 1.0f); Qt3DCore::QBuffer* normalDataBuffer = new Qt3DCore::QBuffer(geometry); normalDataBuffer->setData(normalBufferData); Qt3DCore::QAttribute* normalAttribute = new Qt3DCore::QAttribute(geometry); normalAttribute->setName(Qt3DCore::QAttribute::defaultNormalAttributeName()); normalAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute); normalAttribute->setBuffer(normalDataBuffer); normalAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float); normalAttribute->setVertexSize(3); normalAttribute->setCount(3); normalAttribute->setByteOffset(0); normalAttribute->setByteStride(sizeof(QVector3D)); geometry->addAttribute(normalAttribute); // 将法线属性加入几何体
2. 解决三角形不显示问题
即使修复了材质,仍需确保以下几点:
- 相机可见性:检查你的相机位置,确保三角形在相机视锥体内。例如设置相机位置在z轴正方向:
Qt3DExtras::QCamera* camera = view->camera(); camera->setPosition(QVector3D(0, 0, 5)); camera->lookAt(QVector3D(0, 0, 0)); - 背面剔除检查:Qt3D默认开启背面剔除,确保顶点顺序为逆时针(从相机视角观察)。你的顶点顺序
(0,0,0) → (1,0,0) → (0,1,0)从z轴正方向看是逆时针,符合要求;如果相机在z轴负方向,需要调整顶点顺序或关闭背面剔除:// 可选:关闭背面剔除(仅用于调试) Qt3DRender::QRenderStateSet* renderStateSet = new Qt3DRender::QRenderStateSet(); Qt3DRender::QCullFace* cullFace = new Qt3DRender::QCullFace(); cullFace->setMode(Qt3DRender::QCullFace::NoCulling); renderStateSet->addRenderState(cullFace); m_triangleObject->addComponent(renderStateSet);
完整修正代码示例(使用QUnlitMaterial)
QVector3D vertex1(0.0f, 0.0f, 0.0f); QVector3D vertex2(1.0f, 0.0f, 0.0f); QVector3D vertex3(0.0f, 1.0f, 0.0f); Qt3DCore::QEntity* m_triangleObject = new Qt3DCore::QEntity(m_sharedSceneRoot); Qt3DCore::QTransform* transform = new Qt3DCore::QTransform(); Qt3DCore::QGeometry* geometry = new Qt3DCore::QGeometry(m_triangleObject); Qt3DCore::QBuffer* vertexDataBuffer = new Qt3DCore::QBuffer(geometry); Qt3DCore::QAttribute* positionAttribute = new Qt3DCore::QAttribute(geometry); // 改用无需法线的QUnlitMaterial Qt3DExtras::QUnlitMaterial* material = new Qt3DExtras::QUnlitMaterial(); material->setColor(QColor("#686A63")); Qt3DRender::QGeometryRenderer* geometryRenderer = new Qt3DRender::QGeometryRenderer(); QByteArray vertexBufferData; vertexBufferData.resize(3 * sizeof(QVector3D)); QVector3D* positions = reinterpret_cast<QVector3D*>(vertexBufferData.data()); positions[0] = vertex1; positions[1] = vertex2; positions[2] = vertex3; vertexDataBuffer->setData(vertexBufferData); positionAttribute->setName(Qt3DCore::QAttribute::defaultPositionAttributeName()); positionAttribute->setAttributeType(Qt3DCore::QAttribute::VertexAttribute); positionAttribute->setBuffer(vertexDataBuffer); positionAttribute->setVertexBaseType(Qt3DCore::QAttribute::Float); positionAttribute->setVertexSize(3); positionAttribute->setCount(3); positionAttribute->setByteOffset(0); positionAttribute->setByteStride(sizeof(QVector3D)); geometry->addAttribute(positionAttribute); geometryRenderer->setGeometry(geometry); geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles); transform->setTranslation(QVector3D(0.0f, 0.0f, 0.0f)); m_triangleObject->addComponent(geometryRenderer); m_triangleObject->addComponent(material); m_triangleObject->addComponent(transform);
内容的提问来源于stack exchange,提问作者Razvan B
相关产品推荐
相关产品推荐

