PDA

View Full Version : Textures + Multiple QGLWidgets



KShots
12th July 2006, 23:00
Hello all...

I'm working a project where I have a QWorkspace containing many sub-classed QGLWidgets, and I'm running into problems. Before I get into those, I'd like to ask some generic questions (which may give me some insight on my below problems):

1. With multiple QGLContexts, will I need to bind the same textures to each QGLWidget to get the texture to show up, or do they share texture data?

Now, what I'm currently doing is loading the textures into OGL from my QMainWindow widget - not from any of my QGLWidgets. I am doing this because I want all current and future QGLWidgets to know about whatever textures I am loading. I can envision two scenarios if this is incorrect:

1. I need to go to at least one QGLWidget and load the texture, which all other current and future QGLWidgets would then know about

2. I need to go to all current QGLWidgets and load the texture, then all future QGLWidgets would need to load the texture(s) when they are initialized

Personally, I'd like to be able to do it externally to my QGLWidgets and be done with it.

With my current method, I load in my texture... but when I display it, I get a white model (no textures).

Here's what I'm doing. This first section is where I load in the texture:
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
int depth;
if(T.GetBPP() == 24)
{
depth = GL_RGB;
}
else
{
depth = GL_RGBA;
}
glTexImage2D(GL_TEXTURE_2D, 0, depth, T.GetWidth(), T.GetHeight(), 0, depth, GL_UNSIGNED_BYTE, T.GetData());As I'm just trying to make the thing "work" for now, I've simplified it - it's not really very usable beyond one texture.

texture - This holds my unique texture ID. I make sure it is unique through the use of glGenTextures()

T - This is a texture class I use... it decoded a bitmap file and holds the important data from it (I'd rather use this than the Qt equivalent loader for this application. I've checked that it has valid data).

I have glEnable(GL_TEXTURE_2D) in my initializeGL() function

That covers the loading of the texture. Now when I draw the model:
...
const Triangle * T = &TT->GetOList()[i]->GetConst();
assert(T);
if(T->GetTextureNumber() != 0xFFFFFFFF)
{
glBindTexture(GL_TEXTURE_2D, T->GetTextureNumber());
}
glBegin(GL_TRIANGLES);
for(char j = 0; j < 3; j++)
{
if(renderMode == GL_RENDER)
{
//glColor3ubv(!j?Yellow:j==1?Red:Green);
if(T->GetTextureNumber() != 0xFFFFFFFF)
{
glTexCoord2fv((*T).GetTexture(j)->GetConst().GetFloatStyle());
}
}
glNormal3fv((*T)[j].GetNormal().GetFloatStyle());
glVertex4fv((*T)[j].GetConst().GetFloatStyle());
}
glEnd();
...I tried to display just the interesting portion of the draw code... basically, for each triangle, I do textures, then normals, then the vertex. I bind the texture before the glBegin() function.

I'm starting to run out of ideas on what I'm missing :(

KShots
16th July 2006, 15:49
Well, I've managed to get the textures to show up in a single QGLWidget... but not in others. I was able to do so by having that specific widget load in the texture, rather than taking a step back and having the app load the texture.

This isn't useful.

Is there a way to have each QGLWidget share textures? Or do I really have to load a texture in all current and future QGLWidgets if they share a scene but not a viewpoint?

jacek
16th July 2006, 15:52
See opengl/textures example.

KShots
18th July 2006, 17:17
Got it. For other's reference, look at the constructor on QGLWidget, specifically, the shareWidget parameter.

jp-deivis
19th October 2007, 15:11
Hi KShots. Well... Can you tell me how did you resolve the problem? See, I have the same one, but with a 3D texture. If you made the texture to be shared among the widgets, What did you do? I tried many ways. The last what I did was this, but seems not to work:



QGLContext *cx;

. . .


widgetVolumen = new Rendering(centralWidget);
widgetVolumen->setObjectName(QString::fromUtf8("wVolumen"));
widgetVolumen->setGeometry(QRect(230, 10, 531, 471));
if(wVolumen->isValid())
{
printf("wVolumen valid context!\n");

cx = new QGLContext(widgetVolumen->context()->format());

/*if(cx->create())
{
printf("Funciono contexto\n");
}
else
{
printf("No funciono contexto\n");
}*/
}
else
{
printf("Invalid context!\n");
exit(-1);
}
if(widgetVolumen->isSharing())
{
printf("Volumen GLcontext is shared!\n");
}
else
{
printf("Not Sharing!\n");
}
widgetPlane1 = new Rendering(cx, framePlane1, widgetVolumen);
widgetPlane1->setObjectName(QString::fromUtf8("wCorte1"));
widgetPlane1->setGeometry(QRect(5, 4, 241, 191));


The cx->create() is necessary? It is comented due to some segmentation faults it causes me. What I am trying here is to share the context to see if the texture is able for the others widgets, I do not knwo if I am doing in the right way.

The texture is loaded in other class, one called FileIO:



bool FileIO::readFileRaw(const QString & filename)
{

QFile file(filename);
if (!file.open(QIODevice::ReadOnly))
return false;

pixels = new GLubyte [length_x * length_y * length_z];

if (pixels==NULL)
{
QMessageBox::information(this, tr("Read_data"),
tr("Out of memory"),
QMessageBox::Ok| QMessageBox::Escape);
}
else
{

/*read data*/
QApplication::setOverrideCursor(Qt::WaitCursor);
file.read((char*)pixels ,length_x * length_y * length_z);
}

glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1,&texName);
glBindTexture(GL_TEXTURE_3D_EXT,texName);

// set the texture parameters
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3DEXT(GL_TEXTURE_3D_EXT,0,GL_INTENSITY8, length_x,length_y,length_z,0,GL_LUMINANCE,GL_UNSIG NED_BYTE,pixels);

file.close();
return true;
}

KShots
19th October 2007, 15:58
Hmm... if that's really all you're doing, I think you're going about it in the wrong way. When you subclass QGLWidget, note that there are multiple constructors available. Specifically, there is a pointer to a "shareWidget" (docs (http://doc.trolltech.com/4.3/qglwidget.html#QGLWidget)) in all the constructors. What you do is have a central QGLWidget to pass to all your other QGLWidget sub-classes which will share texture memory and display lists.

In my case, I created what I call a "hidden viewport" - Basically a viewport that always exists (even if there are no visible OpenGL widgets in existence) whose only purpose is to be the place to centrally store all the textures and display lists and share them out to the other widgets. Just pass a pointer to this widget right after you give a parent to your GLWidget and you should be set. Here's a short example:
QGLWidget * hiddenViewPort = new QGLWidget(this);
myViewPort * mvp = new myViewPort(this, hiddenViewPort);Now all the textures and display lists are shared between these viewports. Do the same with any future viewports and you should be set. Just be careful that they have compatible formats (see the docs link above).

jp-deivis
19th October 2007, 18:49
Let me see if I understand your suggest and say what I understand of Qt & GL.

As I see, when I load my texture to the texture memory, it becomes available to the first QGLWidget what is created, and for that reason the others widgets can't access to the memory texture as the first one does, right?

What you propose is to create a first GLWidget with that "privilege" of accessing the texture memory and passes it as the shareWidget parameter to the others widgets (which displays some stuff) and to share with them that "privilege", right?

Following what you posted, I did this:



QGLWidget *central = new QGLWidget(this);
. . .
wVolume = new Rendering(mainWidget, central);
wPlane1 = new Rendering(frame1, central);
wplane2 = new Rendering(fram2, central);
. . .


where mainWidget is the main window of my app, and frame1 and frame2 contain wPlane1 and wPlane2 respectively.

jp-deivis
19th October 2007, 19:15
I started a new thread (before find this one). It is "Share a 3D texture in four QGLWidgets" where there is more information about the problem. Can you move to that thread? There are already some replies.

KShots
19th October 2007, 21:23
I'm posting further replies in the topic you mentioned