You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++ Qt3D中显示图像?求纹理绑定极简示例

用C++ Qt3D加载图像到纹理并绑定到tex0的极简示例

我之前刚好做过类似的Qt3D纹理绑定需求,给你一个纯C++的极简实现示例——完全不用QML,核心就是把图像(摄像头)数据塞进Qt3D的纹理缓冲区,再绑定到材质的tex0上。

步骤1:搭建基础Qt3D场景

先把最基本的窗口、根实体、相机这些核心结构搭起来:

#include <QGuiApplication>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraLens>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DRender/QTexture2D>
#include <Qt3DRender/QTextureImage>
#include <Qt3DRender/QBuffer>
#include <Qt3DRender/QTextureDataGenerator>
#include <Qt3DExtras/QPlaneMesh>

// 先提前声明自定义纹理生成器类
class CustomTextureDataGenerator;

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    // 创建Qt3D显示窗口
    Qt3DExtras::Qt3DWindow view;
    view.defaultFrameGraph()->setClearColor(QColor(Qt::black));

    // 场景根实体
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
    view.setRootEntity(rootEntity);

    // 设置相机参数
    Qt3DRender::QCamera *camera = view.camera();
    camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    camera->setPosition(QVector3D(0, 0, 5.0f));
    camera->setViewCenter(QVector3D(0, 0, 0));

步骤2:准备图像数据并创建纹理

这里我模拟了一张渐变测试图,你直接把这段替换成你从摄像头拿到的像素数组就行,注意要是RGBA格式(每个像素4字节):

// 模拟摄像头输出的图像数据(640x480分辨率)
    const int imgWidth = 640;
    const int imgHeight = 480;
    QByteArray imageData;
    imageData.resize(imgWidth * imgHeight * 4); // RGBA占4字节/像素

    // 生成测试渐变图(替换成你的摄像头像素数据即可)
    uchar *pixelData = reinterpret_cast<uchar*>(imageData.data());
    for (int y = 0; y < imgHeight; ++y) {
        for (int x = 0; x < imgWidth; ++x) {
            pixelData[(y * imgWidth + x) * 4 + 0] = qMin(x * 255 / imgWidth, 255); // R通道
            pixelData[(y * imgWidth + x) * 4 + 1] = qMin(y * 255 / imgHeight, 255); // G通道
            pixelData[(y * imgWidth + x) * 4 + 2] = 255; // B通道
            pixelData[(y * imgWidth + x) * 4 + 3] = 255; // 透明度通道
        }
    }

    // 创建2D纹理对象
    Qt3DRender::QTexture2D *texture = new Qt3DRender::QTexture2D(rootEntity);
    texture->setWidth(imgWidth);
    texture->setHeight(imgHeight);
    texture->setFormat(Qt3DRender::QAbstractTexture::RGBA8_UNorm);
    texture->setWrapMode(Qt3DRender::QTextureWrapMode(Qt3DRender::QTextureWrapMode::ClampToEdge));
    texture->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
    texture->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);

    // 创建存储图像数据的缓冲区
    Qt3DRender::QBuffer *dataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, texture);
    dataBuffer->setData(imageData);

    // 创建纹理图像,绑定缓冲区
    Qt3DRender::QTextureImage *textureImage = new Qt3DRender::QTextureImage(texture);
    textureImage->setDataGenerator(Qt3DRender::QTextureDataGeneratorPtr(new CustomTextureDataGenerator(dataBuffer, imgWidth, imgHeight)));
    texture->addTextureImage(textureImage);

步骤3:实现自定义纹理数据生成器

这个类是Qt3D读取缓冲区数据生成纹理的关键,必须实现指定的接口:

// 自定义纹理数据生成器——负责从缓冲区读取数据并生成Qt3D可识别的纹理格式
class CustomTextureDataGenerator : public Qt3DRender::QTextureDataGenerator
{
public:
    CustomTextureDataGenerator(Qt3DRender::QBuffer *buffer, int width, int height)
        : m_dataBuffer(buffer), m_width(width), m_height(height) {}

    Qt3DRender::QTextureDataPtr operator ()() override {
        auto textureData = Qt3DRender::QTextureDataPtr::create();
        textureData->setWidth(m_width);
        textureData->setHeight(m_height);
        textureData->setDepth(1);
        textureData->setFormat(Qt3DRender::QAbstractTexture::RGBA8_UNorm);
        textureData->setTarget(Qt3DRender::QAbstractTexture::Target2D);
        textureData->setPixelFormat(Qt3DRender::QTextureData::RGBA);
        textureData->setPixelType(Qt3DRender::QTextureData::UInt8);
        textureData->setData(m_dataBuffer->data());
        return textureData;
    }

    bool operator ==(const Qt3DRender::QTextureDataGenerator &other) const override {
        const auto otherGenerator = qobject_cast<const CustomTextureDataGenerator*>(&other);
        return otherGenerator && m_dataBuffer == otherGenerator->m_dataBuffer && 
               m_width == otherGenerator->m_width && m_height == otherGenerator->m_height;
    }

    QT3D_FUNCTOR(CustomTextureDataGenerator)

private:
    Qt3DRender::QBuffer *m_dataBuffer;
    int m_width;
    int m_height;
};

步骤4:绑定纹理到平面实体

最后把纹理贴到一个平面上,用Phong材质的diffuse通道绑定纹理(对应着色器里的tex0):

// 创建平面网格(尺寸对应640:480的比例)
    Qt3DExtras::QPlaneMesh *planeMesh = new Qt3DExtras::QPlaneMesh();
    planeMesh->setWidth(4.0f);
    planeMesh->setHeight(3.0f);

    // 创建材质并绑定纹理
    Qt3DExtras::QPhongMaterial *material = new Qt3DExtras::QPhongMaterial(rootEntity);
    material->setDiffuse(texture); // 这里就把纹理绑定到了tex0通道

    // 创建平面实体,把网格和材质挂上去
    Qt3DCore::QEntity *planeEntity = new Qt3DCore::QEntity(rootEntity);
    planeEntity->addComponent(planeMesh);
    planeEntity->addComponent(material);

    // 显示窗口
    view.show();

    return app.exec();
}

实时更新摄像头画面的关键提示

如果要实时刷新摄像头数据,只需要两步:

  1. 定期把新的摄像头像素数据更新到dataBuffer里(调用dataBuffer->setData(newPixelData))
  2. 调用textureImage->update()触发纹理重新生成

这样就能实现AR应用里的实时摄像头画面显示了。

内容的提问来源于stack exchange,提问作者Ben Hoff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:20:23