how to map a texture onto a grid of tiles seamlessly? - opengl

I have a grid of 8 X 8 points and want to overlay an image on it. I divide the inner grid of 6 X 6 into 4 equal sub-parts of size 3 X 3 each. Let us call this sub-part as tile. The idea is to render these tiles along with their corresponding textures. I divide the grid into tiles because in future I want to test it on a larger grid.
I have done it using following approach but I get seams along the edges. I can't figure out why the seams appear.
First the tiles have corresponding starting co-ords as {(0,0),(0,3),(3,0),(3,3)}.
I have an image of 8 X 8 size which I want to overlay on the super_grid and I store its rgba values in some super_data(8 X 8).
While rendering the tiles I draw them as quads and then overlay the corresponding texture on them. So, if (a,b) are starting co-ords for a particular tile, then I initialize the
quad vertices ={(a-0.5,b-0.5),(a+3-0.5,b-0.5),(a+3-0.5,b+3-0.5),(a-0.5,b+3-0.5)}
and if xs = 1/(tileWidth+1)=1/(3+1)=1/4 and ys =1/(tileHeight+1)=1/4, then
texture Coordinates are {(xs/2,ys/2),(1-xs/2,ys/2),(1-xs/2,1-ys/2),(xs/2,1-ys/2)}
So, for the first tile,
quadVertices={(-0.5,-0.5),(3.5,-0.5),(3.5,3.5),(-0.5,3.5)}
textureCoords={(1/8,1/8),(1-1/8,1/8),(1-1/8,1-1/8),(1/8,1-1/8)}.
Before, passing a texture for the tile I initialize the texture : int image = new int [tileWidth+2] [tileHeight+2] by using the super_data. We take these dimensions because some part of tile texture overlap with the adjacent tiles(that is the reason why we account for this part while calculation of quadVertices).
Finally, to generate the texture, use
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tileWidth + 2, tileHeight + 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
Everything above works fine, I get a grid with image overlayed on it. However, I get seams at the edges. How can I get rid of the seams?

Have you got polygon smoothing on? Try turning it off:
glDisable(GL_POLYGON_SMOOTH)

Try GL_CLAMP_TO_EDGE instead of GL_CLAMP.

You'll need to make sure the vertexes at the same location (or adjacent) use precise texture coordinates. Calculating based on world coordinates, as it appears you're doing, should be able to handle that.
The second part of the issue is the texture itself. Make sure the texture will tile properly when you place it. This becomes more difficult with overlapping tiles; typically you just make sure edges match properly.

Related

Opengl 4.0 Texture issue

Hi I am trying to render texture on a rectangle. I am using GL_CLAMP_TO_BORDER because I dont want texture to repeat itself.
glTextureParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTextureParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
I am expecting output to be something like this : Notice non-texels are grey which is its face color.
But I am getting this output :
Area mentioned in no 2 I guess can be resolved if I enable the blending but I am not getting any solution for Area 1.
I know I havn't shared any code because I really can't ,is there any additional gl calls I need to make to resolve the issue ?
GL_CLAMP_TO_BORDER clamps to the border color defined in the texture/sampler object. That is, texture coordinates outside the [0, 1] range will fetch that border color.
If you didn't set that border color, it will likely be black.
The clamping mode you probably want is GL_CLAMP_TO_EDGE. That means that the color you get for out-of-range fetches is the color of the nearest edge texels of the texture.

Looping a texture on a surface

I want to know how to loop a texture on the surface of an object.
For a practical example, I'm trying to handle rendering world geometry, so that when I resize a world object twice the size of its texture, the texture will then appear twice - not double in size.
Is there any proper way to handle this? The only thing I can think of would be to physically create a brand new texture which is of the right size and manually copied X amount of times, but that sounds like it would eat up a lot of memory really quickly.
Here's a picture showing what I'm looking for, when resizing a plane on the XAxis:
Along with many other variables, I pass an object's UVMap to my shader as the "texture coordinate", and then I perform the following for rendering an object's texture prior to the draw arrays call:
QImage image;
image = worldObject->getQImage(i); //Within a for loop, grabs the right texture if the object has differing textures per face of object
glBindTexture(GL_TEXTURE_2D, spot);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
This is very easy to do. Where you currently use texture coordinates in the range [0.0, 1.0], you simply use a bigger range. For example, to repeat the texture twice, as shown in your example, you specify texture coordinates in the range [0.0, 2.0].
This works in combination with using GL_REPEAT for the texture wrap mode:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
These values are actually the default, so there's no need to set them if you did not set them to a different value earlier.
This specifies that the texture should be repeated for texture coordinates outside the [0.0, 1.0] range. For example, texture coordinates between 1.0 and 2.0 will be equivalent to the coordinates between 0.0 and 1.0, repeating the whole texture.

Missing green color component using glTexImage2D function, why?

I'm writing my 3D engine, without OpenGL or DirectX. Every 3D calculations are my own code. When a whole frame is calculated (a 2D color array), I have to draw it to a window, and to do this I use GLUT and OpenGL. But, I don't use OpenGL's 3D features.
So I have a 2D color array (actually a 1D unsigned char array, which is used as a 2D array), and I have to draw it with OpenGL/GLUT, in an efficient way.
There are two important things:
performance (FPS value)
easy to resize, auto-scale the window's content
I wrote 3 possible solutions:
2 for loop, every pixel is a GL_QUADS with a color. Very slow, but working good, and window resize is also working good.
glDrawPixels, not the most efficient, but I'm satisfied with the FPS-value. Unfortunately, when I resize the window, the content don't scale automatically. I tried to write my own resize callback function, but it never worked. Green is not missing, it's OK.
The best solution is probably to make a texture from that unsigned char array, and draw only one GL_QUADS. Very fast, and window resize working good, the content scaling automatically. But, and this is my question, green color component is missing, I don't know why.
Some hours ago, I used float array, 3 components, and 0...1 values. Green was missing, so I decided to use unsigned char array, because it's smaller. Now, I use 4 components, but the 4th is always unused. Values are 0...255. Green is still missing. My texturing code:
GLuint TexID;
glGenTextures(1, &TexID);
glPixelStorei(GL_UNPACK_ALIGNMENT, TexID); // I tried PACK/UNPACK and ALIGNMENT/ROW_LENGTH, green is still missing
glTexImage2D(GL_TEXTURE_2D, 0, RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, a->output);
glTexParametri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParametri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glBindTexture(GL_TEXTURE_2D, TexID);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
// glTexCoord2f ... glVertex2f ... four times
glEnd();
glDisable(GL_TEXTURE_2D);
glDeleteTextures(1, &TexID);
If I use glDrawPixels, it is working good, R, G and B components are on the window. But when I use the code above with glTexImage2D, green component is missing. I tried a lots of things, but nothing solved this green-issue.
I draw coloured cubes with my 3D engine, and which contains green component (for example orange, white or green), it has a different color, without the green component. Orange is red-like, green is black, etc. 3D objects which doesn't contain green component, are good, for example red cubes are red, blue cubes are blue.
I think, glTexImage2D's parameters are wrong, and I have to change them.
glPixelStorei(GL_UNPACK_ALIGNMENT, TexID); is very wrong.
Accepted values for that function are:
1, 2, 4 and 8
And they represent the row-alignment (in bytes) for the image data you upload. For an 8-bit per-component RGBA image, you generally want either 1 or 4 (default).
You are extremely lucky here if this actually works. Miraculously TexID must be 1 (probably because you only have 1 texture loaded). As soon as you have 3 textures loaded and you wind up with a value for TexID of 3 you're going to generate GL_INVALID_VALUE and your program's not going to work at all.

opengl copying textures is skewing the textures

I'm copying a texture from a framebuffer to an empty texture using
float *temp = new float[width*height*4];
glBindTexture(GL_TEXTURE_2D, fbTex2);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, temp);
glBindTexture(GL_TEXTURE_2D, colour_map_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, temp);
(yes I tried glCopyImageSubData() and it didn't work)
and colour_map_tex is initialized as
glGenTextures(1,&colour_map_tex);
glBindTexture(GL_TEXTURE_2D, colour_map_tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
this is then used to hold a colour map (everything drawn but using a single colour for each object/mesh) which is drawn to a frame buffer and then used to make a mask.
but the issue is when I use the mask, everything is aligned ie. the mask and the texture it is masking are lined up, but when I move the camera around the translations are slightly different which results in the masked image being really skewed in relation to the actual scene.
so my questions are, is there anything that is likely to be the cause of the skewing? or anything that can be done to fix it? would a 3rd frame buffer be a better idea instead of copying the data to an empty texture? and if so why?
overview of what is happening :
1. whole scene is being rendered with textures to a framebuffer.
2. whole scene is rendered a second time without textures but each mesh has a colour associated with it, this is rendered to a second framebuffer and is for a mask.
3. the mask texture is copied to an empty texture
4. the texture from the first frame buffer is drawn onto a plane the size of the viewport ( drawn to the second framebuffer)
5. the mask is overlayed onto the plane to mask out parts of the texture (drawn to the second view buffer)
6. the texture from the first frame buffer is drawn on to a plane the size of the viewport, this time drawn to the screen
7. there is an optional post processed image generated from the texture in the second frame buffer. which is semi transparent and drawn over the rendering of the scene.
I havent posted the whole display function because its pretty big but I'm happy to post more if there is a specific bit that you want.

How to turn off OpenGL filtering when scaling up textures?

I already have these lines in here when I'm loading the texture:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
But when I scale the image here during rendering:
glTexCoord2d(0.0,0.0);
glTexCoord2d(0.0454,0.0);
glTexCoord2d(0.0454,1.0);
glTexCoord2d(1.0,1.0);
I get really bad filtering on the texture (the texture is a spritesheet with multiple frames and I'd rather not make an individual file for each frame).
You're doing it right in terms of texture filtering. However, it's not enough to avoid all sampling artifacts, especially if you move your sprites. You must also make sure that:
Your sprites' size in pixels (on the screen) is an integral multiple of the their size in texels (in the texture)
You draw your sprites at integral coordinates in pixels (or integral-and-a-half, depending on how OpenGL positions texels in textures, I can't remember)
To illustrate the problem, say you have a 32x32 sprite (in the texture) and you map it to a 43x43-pixel quad on screen. Then the GPU only has 32 texels to fill a width of 43 pixels, so it needs to duplicate some of the texels. Exactly which texels are duplicated will depend on the coordinates of your quad on-screen (if you use non-integral coordinates). So moving sprites will appear to have weirdly flickering colors as the GPU decides to duplicate different texels to fill your quad.
To avoid this problem and achieve the best-looking sprites, you really want each texel to map to a single on-screen pixel. If you do this, then using GL_NEAREST or GL_LINEAR won't matter anymore since every pixel will only use the color from a single texel.
You're texture coordinates are pretty confusing to me because they don't form a square or rectangle (you have 3 different X values), nor are you showing the corresponding vertex coordinates (if you aren't interleaving those tex coords with vertex coords, you're just overwriting one texture coordinate over and over).
If you're trying to access a given (square) sub-region of the texture, then I would expect your texCoords to look something like this:
float x, float y; // position of the sprite in the texture
float height, float width; // size of the sprite in the texture
glBegin(GL_TRIANGLE_STRIP)
// lower left
glVertex3D(...)
glTexCoord2d(x, y);
// lower right
glVertex3D(...)
glTexCoord2d(x, y + width);
// upper left
glVertex3D(...)
glTexCoord2d(x + height, y);
// upper right
glVertex3D(...)
glTexCoord2d(x + height, y + width);
glEnd()