PDA

View Full Version : How to share textures between QGLWidgets



jshafferman
1st July 2014, 16:10
I am currently having problems sharing texture objects between several (currently two) different QGLWidgets. I first create a custom QGLWidget and I override its initializeGL() function and do texture initialization in there. Here is the following code:



SharedGLWidget::SharedGLWidget(QWidget *parent) :
QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::Rgba | QGL::DepthBuffer), parent)
{
}

void SharedGLWidget::initializeGL()
{
GLbyte *pBytes;
GLint iWidth, iHeight, iComponents;
GLenum eFormat;

// Load texture
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
pBytes = gltLoadTGA("../SharedTest/stone.tga", &iWidth, &iHeight, &iComponents, &eFormat);
glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
free(pBytes);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
}


Then I create a second QGLWidget and do normal Qt rendering stuff with the exception of loading the textures again.



GLWidget::GLWidget(QWidget *parent, const QGLWidget *sharedWidget, Qt::WindowFlags f)
: QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::Rgba | QGL::DepthBuffer), parent, sharedWidget, f)
, xRot(0.0f)
, yRot(0.0f)
{
}

void GLWidget::initializeGL()
{
// Light values and coordinates
GLfloat whiteLight[] = { 0.05f, 0.05f, 0.05f, 1.0f };
GLfloat sourceLight[] = { 0.25f, 0.25f, 0.25f, 1.0f };
GLfloat lightPos[] = { -10.f, 5.0f, 5.0f, 1.0f };

glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clock-wise polygons face out
glEnable(GL_CULL_FACE); // Do not calculate inside of jet

// Enable lighting
glEnable(GL_LIGHTING);

// Setup and enable light 0
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_AMBIENT,sourceLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);

// Enable color tracking
glEnable(GL_COLOR_MATERIAL);

// Set Material properties to follow glColor values
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

// Black blue background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

glEnable(GL_TEXTURE_2D);
}

void GLWidget::paintGL()
{
M3DVector3f vNormal;
M3DVector3f vCorners[5] = { { 0.0f, .80f, 0.0f }, // Top 0
{ -0.5f, 0.0f, -.50f }, // Back left 1
{ 0.5f, 0.0f, -0.50f }, // Back right 2
{ 0.5f, 0.0f, 0.5f }, // Front right 3
{ -0.5f, 0.0f, 0.5f }}; // Front left 4

// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Save the matrix state and do the rotations
glPushMatrix();
// Move object back and do in place rotation
glTranslatef(0.0f, -0.25f, -4.0f);
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);

// Draw the Pyramid
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_TRIANGLES);
// Bottom section - two triangles
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3fv(vCorners[2]);

glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[4]);

glTexCoord2f(0.0f, 1.0f);
glVertex3fv(vCorners[1]);


glTexCoord2f(1.0f, 1.0f);
glVertex3fv(vCorners[2]);

glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[3]);

glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[4]);

// Front Face
m3dFindNormal(vNormal, vCorners[0], vCorners[4], vCorners[3]);
glNormal3fv(vNormal);
glTexCoord2f(0.5f, 1.0f);
glVertex3fv(vCorners[0]);
glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[4]);
glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[3]);

// Left Face
m3dFindNormal(vNormal, vCorners[0], vCorners[1], vCorners[4]);
glNormal3fv(vNormal);
glTexCoord2f(0.5f, 1.0f);
glVertex3fv(vCorners[0]);
glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[1]);
glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[4]);

// Back Face
m3dFindNormal(vNormal, vCorners[0], vCorners[2], vCorners[1]);
glNormal3fv(vNormal);
glTexCoord2f(0.5f, 1.0f);
glVertex3fv(vCorners[0]);

glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[2]);

glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[1]);

// Right Face
m3dFindNormal(vNormal, vCorners[0], vCorners[3], vCorners[2]);
glNormal3fv(vNormal);
glTexCoord2f(0.5f, 1.0f);
glVertex3fv(vCorners[0]);
glTexCoord2f(0.0f, 0.0f);
glVertex3fv(vCorners[3]);
glTexCoord2f(1.0f, 0.0f);
glVertex3fv(vCorners[2]);
glEnd();


// Restore the matrix state
glPopMatrix();

// Buffer swap
swapBuffers();
}


In my main.cpp I pass the first QGLWidget with just the texture initialization as the sharedWidget for the second QGLWidget:



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

SharedGLWidget* glwidget1 = new SharedGLWidget;

GLWidget* widget = new GLWidget(0, glwidget1);
widget->show();

app.exec();
}


I am not sure what I am missing but when widget is shown the texture isn't showing up (the pyramid is drawn but with no texturing). I am wondering what I am missing and if anyone has any idea as to how I can do this. I am only creating one texture object thus I was trying to not use glGenBuffers for texture objects but if this is something that has to be done I will try to do it while I wait for some responses. I am curious if I do go that route, how the glBind call would be preformed in the rendering widget. Thanks for any help!

jshafferman
1st July 2014, 21:22
I did find one potential issue, but it didn't resolve my problem. I moved all of the initializeGL() calls from the shared widget to the constructor because I forgot that initializeGL() is only called before paintGL is called and not called at all if sharedwidget->show() isn't called. However this didn't solve my problem :(

feiz
28th April 2015, 09:52
You can share texture object use GLwidget construct function ,
QGLWidget::QGLWidget ( QWidget * parent = 0, const QGLWidget * shareWidget = 0, Qt::WindowFlags f = 0 ),it will share texture object with shareWidget.But I want share texture object with multi qglwidget ,