QOpenGLTexture and shader?
-
Hi,
I have trying to generate a 3D texture to be used by a shader (displaying a slice). I have an old version, directly using the OpenGL functions. Its code is the following:Texture creation:
QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QOpenGLFunctions_3_2_Compatibility* func = currentContext->versionFunctions< QOpenGLFunctions_3_2_Compatibility >(); unsigned int imageId = 0; func->glEnable(GL_TEXTURE_3D); // Create OpenGL texture func->glGenTextures(1, &imageId); func->glBindTexture(GL_TEXTURE_3D, imageId); func->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); func->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); func->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); func->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); func->glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, (p_multipleTextures ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER)); GLfloat colorBorder[4] = {0.,0.,0.,0.}; func->glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, colorBorder); func->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); func->glTexImage3D(GL_TEXTURE_3D, 0, GL_ALPHA16, p_pow2x, p_pow2y, p_pow2z, 0, GL_ALPHA, GL_UNSIGNED_SHORT, p_textureBuffer); func->glBindTexture(GL_TEXTURE_3D, 0); func->glDisable(GL_TEXTURE_3D); m_textures.append(imageId); return true;
Texture usage:
func->glEnable(GL_TEXTURE_3D); QSharedPointer<OGLSliceShader> sliceShader = OGLShaderFactory::getInstance()->getShader(OGLShaderFactory::ShaderName::SLICE_SHADER).staticCast<OGLSliceShader>(); for (int i = 0; i < textures.size(); ++i) {// Active the texture func->glActiveTexture(GL_TEXTURE0 + i); func->glBindTexture(GL_TEXTURE_3D, textures[i]); }// Active the texture // Image is displayed by a shader sliceShader->start(OGLSliceShader::Mode::SLICE3D, contrast, brightness, textures.size()); func->glColor3fv(IMAGE_COLOR.data()); func->glBegin(GL_QUADS); func->glTexCoord3d(m_textureQuad[0].x(), m_textureQuad[0].y(), m_textureQuad[0].z()); func->glVertex3d(m_sliceQuad[0].x(), m_sliceQuad[0].y(), m_sliceQuad[0].z()); func->glTexCoord3d(m_textureQuad[1].x(), m_textureQuad[1].y(), m_textureQuad[1].z()); func->glVertex3d(m_sliceQuad[1].x(), m_sliceQuad[1].y(), m_sliceQuad[1].z()); func->glTexCoord3d(m_textureQuad[2].x(), m_textureQuad[2].y(), m_textureQuad[2].z()); func->glVertex3d(m_sliceQuad[2].x(), m_sliceQuad[2].y(), m_sliceQuad[2].z()); func->glTexCoord3d(m_textureQuad[3].x(), m_textureQuad[3].y(), m_textureQuad[3].z()); func->glVertex3d(m_sliceQuad[3].x(), m_sliceQuad[3].y(), m_sliceQuad[3].z()); func->glEnd(); sliceShader->stop(); for (int i = textures.size() - 1; i >=0 ; --i) {// Unbind textures func->glActiveTexture(GL_TEXTURE0 + i); func->glBindTexture(GL_TEXTURE_3D, 0); }// Unbind textures func->glDisable(GL_TEXTURE_3D);
And the fragment shader code is (really simple):
float toto = texture3D(tex3d0, gl_TexCoord[0].xyz).a; gl_FragColor = vec4(toto, toto, toto, 1.0);
This code works well.
Now, as I'm moving to Qt5.6 I would use QOpenGLTexture. So, I have modified the code as follow:
Texture creation:
QOpenGLTexture * currentTexture = new QOpenGLTexture(QOpenGLTexture::Target3D); QOpenGLPixelTransferOptions packAlignment; currentTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); currentTexture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToBorder); currentTexture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToBorder); currentTexture->setWrapMode(QOpenGLTexture::DirectionR, (p_multipleTextures ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::ClampToBorder)); currentTexture->setBorderColor(0.0f, 0.0f, 0.0f, 1.0f); // Border color is black currentTexture->setFormat(QOpenGLTexture::R16U); currentTexture->setSize(p_pow2x, p_pow2y, p_pow2z); packAlignment.setAlignment(1); currentTexture->allocateStorage(QOpenGLTexture::Red_Integer, QOpenGLTexture::UInt16); if (!currentTexture->isStorageAllocated()) {// problem allocating the storage INCAS_WARNING() << QString::fromLatin1("Cannot allocate storage for the current texture", 47); delete currentTexture; return false; }// problem allocating the storage currentTexture->setData(QOpenGLTexture::Red_Integer, QOpenGLTexture::UInt16, p_textureBuffer, &packAlignment);
Texture usage:
QSharedPointer<OGLSliceShader> sliceShader = OGLShaderFactory::getInstance()->getShader(OGLShaderFactory::ShaderName::SLICE_SHADER).staticCast<OGLSliceShader>(); for (int i = 0; i < textures.size(); ++i) {// Active the texture textures[i]->bind(i); }// Active the texture // Image is displayed by a shader sliceShader->start(OGLSliceShader::Mode::SLICE3D, contrast, brightness, textures.size()); func->glColor3fv(IMAGE_COLOR.data()); func->glBegin(GL_QUADS); func->glTexCoord3d(m_textureQuad[0].x(), m_textureQuad[0].y(), m_textureQuad[0].z()); func->glVertex3d(m_sliceQuad[0].x(), m_sliceQuad[0].y(), m_sliceQuad[0].z()); func->glTexCoord3d(m_textureQuad[1].x(), m_textureQuad[1].y(), m_textureQuad[1].z()); func->glVertex3d(m_sliceQuad[1].x(), m_sliceQuad[1].y(), m_sliceQuad[1].z()); func->glTexCoord3d(m_textureQuad[2].x(), m_textureQuad[2].y(), m_textureQuad[2].z()); func->glVertex3d(m_sliceQuad[2].x(), m_sliceQuad[2].y(), m_sliceQuad[2].z()); func->glTexCoord3d(m_textureQuad[3].x(), m_textureQuad[3].y(), m_textureQuad[3].z()); func->glVertex3d(m_sliceQuad[3].x(), m_sliceQuad[3].y(), m_sliceQuad[3].z()); func->glEnd(); sliceShader->stop(); for (int i = textures.size() - 1; i >=0 ; --i) {// Unbind textures textures[i]->release(); }// Unbind textures
So, I had to perform the following changes:
-
I'm using the red channel instead of alpha. I found no way to set the texture on the alpha channel only. So, in the shader I changed to this channel too,
-
I have no more the enable/disable GL_TEXTURE_3D.
With this new version I always have a black image. And,
-
If I use glReadTexImage, I obtain the data I set (so texture is correct),
-
If the shader uses the alpha channel instead of the red one, I also have a black image. And this is strange (not compliant with documentation),
-
If I force the enable/disable of GL_TEXTURE_3D there is no change
Do you have an idea of what I'm doing wrong?
Thnaks.
-
-
I did some new tries. With the direct use of OpenGL functions, I can use the shader by using GL_R16 + GL_RED + GL_UNSIGNED_SHORT. So I have just moved of channel.
But this association does not work with QOpenGLTexture. Setting the format to R16_UNorm (supposed to be GL_R16) and allocate the storage with QOpenGLTexture::Red (supposed to be GL_RED) and QOpenGLTexture::UInt16 (suppoed to be GL_UNSIGNED_SHORT), generates an OpenGL error.