Dynamic Textures in Qt3D with C++
-
I'm looking for a way to dynamically create and update a texture from C++ to be used in a custom shader.
This seems to be a rather basic use case but I am getting completely lost in the underdocumented depths of Qt3D.
I simply want to create a QTexture2D and set it to a Material property.In essence, I want the equivalent to
glGenTextures
+glTexImage2D
, however I can't clearly map this to theQTexture2D
interface.It seems that I need to use
QTexture2D::updateData
to upload data, but the documentation suggests I still need to initialize the texture with the dimensions first? Do I need to implement my ownQTextureImageDataGenerator
if I want to dynamically update it?I can't find any example code that would put me in the right direction, so any help will be highly appreciated!
-
Ok, I figured out how to use
updateData
properly. Leaving this here for posterity. For my use case, I needed to upload a grayscale 3D texture but this should be the same for any texture type:using namespace Qt3DRender; QTexture * tex = new QTexture3D; tex->setSize(vol.width(), vol.height(), vol.depth()); tex->setFormat(QTexture3D::TextureFormat::R8_UNorm); tex->setLayers(1); tex->setGenerateMipMaps(false); QTextureWrapMode wm(QTextureWrapMode::ClampToBorder); tex->setWrapMode(wm); data->setFormat(QOpenGLTexture::TextureFormat::R8_UNorm); data->setWidth(vol.width()); data->setHeight(vol.height()); data->setDepth(vol.depth()); data->setMipLevels(1); data->setLayers(1); data->setPixelFormat(QOpenGLTexture::PixelFormat::Red); data->setPixelType(QOpenGLTexture::PixelType::UInt8); QByteArray qba; qba.setRawData((const char *)vol.dataUint8(), static_cast<int>(vol.byteSize())); data->setData(qba, 1); QTextureDataUpdate update; update.setX(0); update.setY(0); update.setData(data); tex->updateData(update); Qt3DRender::QParameter p(); p.setName("volume"); // the uniform name in the shader p.setValue(QVariant::fromValue(tex)); QMaterial * mat = ...; // queried from the qml mat->addParameter(p);
The Qt3D test for texture update was pretty helpful in figuring this out.
-
@Jakob-Weiss
Is there any QT 3d Volume Rendering exmple in Qt? We are also trying to get Texture3d work in shader. Up to now, thanks to your tip, we made Texture2d work. We did the same in Texture3d, but it just didn't work and always shows black. Thanks if there is any tip.- QML is like:
parameters: [ Parameter { id: mainTex name: "mainTex" value: m_mainTexture }, Parameter { id: myTex3D name: "myTex3D" value: m_mainTex3D } ]
- frag Shader is like:
layout(std140, binding = auto) uniform custom_uniforms { vec3 maincolor; }; layout(binding = auto) uniform sampler2D mainTex; layout(binding = auto) uniform sampler3D myTex3D; layout(location = 0) in vec3 worldPosition; layout(location = 1) in vec2 v_texcoord; layout(location = 0) out vec4 fragColor; void main() { //vec4 txtColor = texture(mainTex, v_texcoord); vec4 txtColor = texture(myTex3D, vec3(v_texcoord.x,v_texcoord.y,0.5)); float value_3D = txtColor.r * 100; fragColor = vec4(value_3D,value_3D,value_3D,1.0); }
- C++ is like:
m_texture3D = new Qt3DRender::QTexture3D(); m_texture3D->setSize(128,128,128); m_texture3D->setFormat(Qt3DRender::QTexture3D::R8_UNorm); m_texture3D->setLayers(1); m_texture3D->setGenerateMipMaps(false); Qt3DRender::QTextureWrapMode wm(Qt3DRender::QTextureWrapMode::ClampToBorder); m_texture3D->setWrapMode(wm); //m_texture3D->setMinificationFilter(Qt3DRender::QTexture3D::Linear); //m_texture3D->setMagnificationFilter(Qt3DRender::QTexture3D::Linear); rawPixelData3D.resize(128 * 128 * 128 * sizeof(uchar)); uchar *pixels3D = reinterpret_cast<uchar *>(rawPixelData3D.data()); std::memset(pixels3D, 60, 128 * 128 * 128 * sizeof(uchar)); Qt3DRender::QTextureImageDataPtr imageData3D = Qt3DRender::QTextureImageDataPtr::create(); imageData3D->setFormat(QOpenGLTexture::TextureFormat::R8_UNorm); imageData3D->setWidth(128); imageData3D->setHeight(128); imageData3D->setDepth(128); imageData3D->setMipLevels(1); imageData3D->setLayers(1); imageData3D->setPixelFormat(QOpenGLTexture::PixelFormat::Red); imageData3D->setPixelType(QOpenGLTexture::PixelType::UInt8); imageData3D->setData(rawPixelData3D, 1, false); Qt3DRender::QTextureDataUpdate update3D; update3D.setX(0); update3D.setY(0); update3D.setData(imageData3D); m_texture3D->updateData(update3D);