Total opengl noob here.
I have a whole directory of images that I end up loading into memory and building textures from parts of these images. Constructing the textures from the subparts of these images on the fly is bogging the system down, but I won't know beforehand what portions of these images will need to be selected to build the textures. Is there a better way to handle this than creating a large number of textures? For instance, making one texture for each image and then sampling a subset of that texture to apply to each surface?
I can post code if it helps, but there is a lot of it. I was hoping for more of general guidelines and orientation towards using textures in an efficient way.
Sounds to me like you just want to adjust your texture coordinates.
Texture coordinates are given between 0 and 1.
To draw the whole texture onto a quad, you could do something like this:
glTexCoord2f(0.0f, 0.0f);
glVertex3f(...)
glTexCoord2f(1.0f, 0.0f);
glVertex3f(...)
glTexCoord2f(1.0f, 1.0f);
glVertex3f(...)
glTexCoord2f(0.0f, 1.0f);
glVertex3f(...)
But to draw just one quarter of the texture onto the same quad: (Note the different values for glTexCoord)
glTexCoord2f(0.0f, 0.0f);
glVertex3f(...)
glTexCoord2f(0.5f, 0.0f);
glVertex3f(...)
glTexCoord2f(0.5f, 0.5f);
glVertex3f(...)
glTexCoord2f(0.0f, 0.5f);
glVertex3f(...)
Look up OpenGL texturing tutorial on the almighty Google.
Related
I'm having a hard time figuring out what's going on with my texture:
Basically I am fetching a webcam stream as my underlying 2d texture canvas in OpenGL, and in my paintGL() I'm drawing stuff on it (as RGBA images with GL_BLEND).
Since I'm using a Kinect as a data source, I'm also getting the depth values from a tracked skeleton (a person), and converting them into GL values (XYZ varying between 0.0f and 1.0f).
So my goal is that, for instance, a loaded 2D Texture like a shirt, is now properly tracking the person in my RGB output display. But it seems my understanding of orthographic projection is wrong:
I'm constantly loading the 4 converted vertices into a VBO, but whenever I put the texture on top of this dynamic quad, it's always facing the screen.
I thought that putting this dynamic quad between the "background" canvas and the camera would result in a proper projection of the quad onto the canvas, which would give me the impression of a warping 2D texture, that seems to "bend" whenever the person rotates.
But the texture is always facing the camera and doesnt rotate.
I've also tried to manually rotate via a matrix and set that into my shader, but again, it only rotates the vertice quad itself (as: rotation simply makes the texture smaller) , and THEN puts the texture on top, instead of rotating the texture with it.
So, is it somehow possible to properly apply this to the texture?
I've thought about mixing a perspective projection in, but actually have no idea how to implement this...
EDIT:
I've actually already set my projection matrix up like the following:
In resizeGL():
projection.setToIdentity();
projection.ortho(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
projection.translate(0.0f, 0.0f, 3.0f);
In paintGL():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST); // turning this on/off makes no difference
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, &textureID);
program.setUniformValue("mvp_matrix", projection);
program.setUniformValue("texture", 0);
//draw 2d background quad
drawQuad();
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// switch to frustum to give perspective view
projection.setToIdentity();
projection.frustum(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
projection.translate(0.0f, 0.0f, 3.0f);
// bind cloth texture and draw ontop 2d quad
clothTexture->bind();
program.setUniformValue("mpv_matrix", projection);
drawShirtQuad();
// reset to ortho view
projection.setToIdentity();
projection.ortho(0.0f, 1.0f, 0.0f, 1.0f, 2.0f, -5.0f);
// release texture
clothTexture->release();
glDisable(GL_BLEND);
clothTexture is a QOpenGLTexture that has successfully loaded an RGBA image from a file.
Result: whenever I activate the frustum perspective, it results in a black screen. I think everything is correctly set up: POV is traversed towards positive z-axis in resizeGL(), and all the cloth vertices vary between 0 and 1 in XYZ, while the background is positioned at:
(0.0f, 0.0f, -1.0f), (1.0f, 0.0f, -1.0f), (1.0f, 1.0f, -1.0f), (0.0f, 1.0f, -1.0f).
So the cloth object is always positioned between background plane and POV. Am i missing something in the frustum setup ? I've simply set it up the same way as ortho...
EDIT:
Sorry for not mentiong; the matrix I'm using is a QMatrix4x4 type:
Frustum
These functions multiply the current matrix with the one you define as an argument, which should yield the same result as if I define a View matrix for instance, and then define my shader uniform "mvp_matrix" as projection * view, if I'm not mistaken. Maybe something like lookAt will do the trick; I'll just try messing around more. :)
You need to use a perspective projection to achieve desired result. Look here for example code for perspective projection matrix creation with glm.
Moving vertices wouldn't be needed as you will get proper positions with rotation applied in your model matrix.
EDIT: in your code where can i look at .frustum and .translate methods or from what library projection object is? It doesn't look like you are doing Projection * View by moving frustum matrix. Some info about roles of standard matrices.
Considering debugging if you get on screen black color instead of GL_COLOR_BUFFER_BIT color problem is not with matrix but earlier. Also i recommend to console.log your perspective matrix and compare it to correct one (which you can get for example in glm library).
After my last post, when someone recommended me to use pBuffers, I digged a bit on Google and I found some cool examples to make Offscreen Rendering, using pbuffers. Some example, available on nVidia's website, does a simple offscreen rendering, which just renders on the pbuffer context, reads the pixels into an array and then calls the opengl functions to DrawPixels.
I changed this example, in order to create a texture from the pixels read - Render it offscreen, read the pixels to the array, and then initialize a texture with this colorbit array. But this looks very redundant to me - We render the image, we copy it from Graphical Card memory into our memory (the array), to later copy it back to the graphical card in order to display it on screen, but just in a different rendering context. It looks kinda stupid the copies that I am making just to display the rendered texture, so I tried a different approach using glCopyTexImage2D(), which unfortunately doesn't work. I'll display code and explanations:
mypbuffer.Initialize(256, 256, false, false);
- The false values are for Sharing context and sharing object. They are false cause this fantastic graphical card doesn't support it.
Then I perform the usual initializations, to enable Blending, and GL_TEXTURE_2D.
CreateTexture();
mypbuffer.Activate();
int viewport[4];
glGetIntegerv(GL_VIEWPORT,(int*)viewport);
glViewport(0,0,xSize,ySize);
DrawScene(hDC);
//save data to texture using glCopyTexImage2D
glBindTexture(GL_TEXTURE_2D,texture);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
0,0, xSize, ySize, 0);
glClearColor(.0f, 0.5f, 0.5f, 1.0f); // Set The Clear Color To Medium Blue
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
// glBindTexture(GL_TEXTURE_2D,texture);
first = false;
mypbuffer.Deactivate();
- The DrawScene function is very simple, it just renders a triangle and a rectangle, which is suposed to be offscreen rendered (I HOPE). CreateTexture() creates an empty texture. The function should work, as it was tested in the previous way I described and it works.
After this, in the main loop, i just do the following:
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D,texture);
glRotatef(theta, 0.0f, 0.0f, 0.01f);
glBegin(GL_QUADS);
//Front Face
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-0.5, -0.5f, 0.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f( 0.5f, -0.5f, 0.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f( 0.5f, 0.5f, 0.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, 0.5f);
glEnd();
SwapBuffers(hDC);
theta = 0.10f;
Sleep (1);
The final result is just a window with a blue background, nothing got actually Rendered. Any Idea why is this happening? My Graphical Card doesn't support the extension wgl_ARB_render_texture, but this shouldn't be a problem when calling the glCopyTexImage2D() right?
My Card doesn't support FBO either
What you must do is, sort of "connect" your two OpenGL contexts so that the textures of your PBuffer context also show up in the main render context. The term you need to look for is "display list sharing". In Windows you connect the contexts retroactively using wglShareLists, on X11 and MacOS X you must supply the handle of the context to be shared at context creation.
An entirely different possibility and working just as well is reusing the same context on the PBuffer. It's a little known fact, that you can use OpenGL render contexts not only on the drawable it has been created with first, but on any drawable with compatible settings. So if your PBuffer matches your main window's pixel format, you can detach the render context from the main window and attach it to the PBuffer. Of course you then need low level access to the main window's device context/drawable, which is normally hidden behind a framework.
You should check whether your OpenGL implementation supports framebuffer objects: these object are able to be render targets, and they can have attached textures as color buffers, indeed rendering directly into a texture.
This should be the way to go, otherwise your method is the alternative.
I was texture mapping a primitive, a quad to be exact. I had a problem with the texture being somehow rotated 90 degrees to anticlockwise direction. I thought the problem would be with the loading code of the texture, but turned out it was actually a problem with the draw function.
So this was the code which draw the picture erroneously:
glVertex2f(0.0f, 0.0f); glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.5f, 0.0f); glTexCoord2f(1.0f, 1.0f);
glVertex2f(0.5f, 0.5f); glTexCoord2f(1.0f, 0.0f);
glVertex2f(0.0f, 0.5f); glTexCoord2f(0.0f, 0.0f);
and this one draw it just as I intended it to be drawn:
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(0.5f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex2f(0.5f, 0.5f);
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.5f);
What causes this kind of behaviour? I really didn't think this would have such effects to the drawing.
I really didn't think this would have such effects to the drawing.
Think about it. What does glTexCoord do? It specifies the texture coordinate, correct? But the texture coordinate of what?
Yes, you know it specifies the texture coordinate of the next vertex, but OpenGL doesn't know that. All glTexCoord does is set the values you pass it into a piece of memory.
glVertex does something more. It sets the vertex position, but it also tells OpenGL, "Take all of the vertex values I've set so far and render a vertex with it." That's why you can't call glVertex outside of glBegin/glEnd, even though you can do that with glTexCoord, glColor, etc.
So when you do glTexCoord(...); glVertex(...), you're saying "set the current texture coordinate to X, then set the position to Y and render with these values." When you do glVertex(...); glTexCoord(...);, you're saying, "set the position to Y and render with the previously set values, then set the current texture coordinate to X."
It's a little late to be setting the texture coordinate after you've already told OpenGL to render a vertex.
OpenGL functions in a state-wise fashion. Many GL function calls serve to change the current state so that when you call some other functions, they can use the current state to do the proper operation.
In your situation, the glVertex2f() call uses the current texture state to define which part of the texture gets mapped on which vertex. In your first series of call, the first call to glVertex2f() would have no previous texture state, so it would probably default to (0.0f, 0.0f), although it could also be undefined behavior. The second call to glVertex2f would then use the state set by your first call to glTexCoord2f(), then the third call to glVertex2f() uses the state set by the second call to glTexCoord2(), and so on.
In the future, make sure to set the proper GL state before you call the functions which use those states, and you should be good to go.
The order in which you call glVertex and glTexCoord definitely matters! Whenever you specify vertex attributes like glTexCoord, glColor, etc.. they apply all future vertices that you draw, until you change one of those attributes again. So in the previous example, your first vertex was being drawn with some unspecified previous tex coord, the second vertex with tex coord (0.0, 1.0), etc..
Probably the best explanation there is online : Texture mapping - Tutorial
And also just to make sure, texture coordinates (texCoor) are as following :
And the order in which they are called matters!
(0,0) bottom left corner
(0,1) upper left corner
(1,0) bottom right corner
(1,1) upper right corner
I am trying to do a Photoshop-like hue shift on a texture.
My code is somewhat like this:
glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
//bind texture, draw quad, etc.
Here is a picture describing what happens:
I can't post images yet, so here's a link.
i have a question concerning how to declare the points for a texture on a cube
to be exactly i mean the:
glTexCoord2f(x.f, y.f);
for the front side, my declaration works:
glBegin(GL_POLYGON); //Vorderseite
glNormal3f(0.0f, 0.0f, 1.0f);//normale für vorderseite
glTexCoord2f(0.0f, -1.f);
glVertex3f(-fSeitenL/2.0f,-fSeitenL/2.0f,+fSeitenL/2.0f);
glTexCoord2f(1.f, -1.f);
glVertex3f(+fSeitenL/2.0f,-fSeitenL/2.0f,+fSeitenL/2.0f);
glTexCoord2f(1.f, 0.0f);
glVertex3f(+fSeitenL/2.0f,+fSeitenL/2.0f,+fSeitenL/2.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-fSeitenL/2.0f,+fSeitenL/2.0f,+fSeitenL/2.0f);
glEnd();
but for the right side, it doesn't work, i suggest i need other parameters, for glTexCoord2f, but i don't know witch one.
glBegin(GL_POLYGON); //Rechte Seite
glNormal3f(1.0f, 0.0f, 0.0f); //normale für rechte seite
glTexCoord2f(0.0f, -1.f);
glVertex3f(+fSeitenL/2.0f,-fSeitenL/2.0f,+fSeitenL/2.0f);
glTexCoord2f(1.0f, -1.f);
glVertex3f(+fSeitenL/2.0f,-fSeitenL/2.0f,-fSeitenL/0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(+fSeitenL/2.0f,+fSeitenL/2.0f,-fSeitenL/0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(+fSeitenL/2.0f,+fSeitenL/2.0f,+fSeitenL/0.0f);
glEnd();
after all i close the "texture-declaration with"
glDisable(GL_TEXTURE_2D);
thanks in advance
edit:
the frontside is shown with the picture, the other side isn't shown, not even the "cubeside".
for now i just use a picture that's black with some random white spaces, so the exactly position is not that much importent, despite that i'm very interessted how to set the glTexCoord2f right.
Since you're using negative texture coordinates (or really anything outside the 0..1 range) you need to make sure that your texture wrap mode is set to repeat.
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
If those are set to GL_CLAMP instead, then any value less than 0 will be set to 0 and any value greater than 1 will be set to 1. But since you say the first part of your model textures correctly, this is probably not your problem.
The next most likely issue is lighting. If you turn off lighting with glDisable(GL_LIGHTING); does the entire model show up? If so, then you need to make sure you have a light facing the problem portion of your model, or add an ambient component to your light.
How exactly does it not work?
If the texture isn't showing up or the wrong texture is applied, it means you have to set a different texture with glBindTexture().
If the texture is aligned incorrectly, you have to make sure that the vertices that are shared between the two faces have the same texture coordinate.