Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repeated textures are severely distorted/shaking when rotating camera

I originally asked this question on gamedev, but none of the answers helped to solve problem, and I still have no clue what is the real cause. I didn't see anything about re-posting questions across SE in FAQs, so I can only hope this is okay. Moreover, in the retrospect the question is probably more related to graphics programming in general than just game development.

Edit 1 begins

The behaviour of the original post applies only to Windows XP and Windows 7, browsers Firefox and Chrome. On Ubuntu, there is no such distortion, but instead the textures "shake" while the camera is being rotated. When the rotation is halted, the shaking stops, but the textures may not be in the completely correct position.

Edit 1 ends

Edit 3 begins

The program has been tested on 4 different computers, and haven't worked as intended on any of them.

Edit 3 ends

I have a large voxel in WebGL which I want to cover with tiled texture each tile has the side length of 1 in the vertex space. In this test scenario the camera is pointing to the negative z direction and the sides of the voxel are in the x-y, x-z, y-z planes.

Smaller voxels (i.e. fewer repeats) work quite well, but at around 2000 x and y repeats per face (ie voxel size 2000*2000*2000) the textures start to look really ugly. When the camera points perpendicularly to the face the textures look correct regardless of the size/amount of repeats, but for voxels of the size mentioned above any rotation of even a couple of degrees causes a visible problem. Increasing the voxel size increases the distortion. The inverse is also true: with small voxels the textures look correct regardless of camera rotation. It seems to me that there is no hard threshold value for the size but that the effect starts to increase gradually from zero when the voxel is increased in size from the approx 2000 per side.

See http://imgur.com/a/spQIv for a visualization. The first image is how it should look like, but when the camera is rotated, the lines start to become distorted as in the second image. The effect gets worse by increasing the voxel size and by rotating the camera more. http://imgur.com/a/wRndy contains two additional images with more severe effect.

The textures (one X per texture) are originally 512*512 px. The screenshots have not been scaled in any way.

My first guess was float inaccuracies, but that's quite hard to believe since the object has only the dimensions of the order of 1000.

My second guess was some kind of weird int/float rounding error, but since everything is always handled in floats, I don't see how this could happen.

The third possibility I could think of is that this is just impossible and that textures should not be repeated that many times. However, this seems quite unlikely IMO. My guess (and hope) is that there is some kind of quite elementary problem.

Any suggestions about what can cause or commonly does cause this kind of thing are well appreciated, because I seem to be having a very hard time trying to narrow down the source of this problem on my own.

I'm using:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
gl.generateMipmap(gl.TEXTURE_2D);

and in the shader:

#ifdef GL_ES
precision highp float;
#endif

I also performed some very elementary calculations: For 32-bit floats the maximum significand is around 8.4 million. For voxel side length 2000 (which I noticed was the level where the effect became visible), one could naively expect approximately 0.00025 of a float rounding error in the coordinates. Assuming each repeat takes around 100 pixels in screen, the error should be significantly less than 1 pixel, which is not the case. Unless my calculation above was done incorrectly, I therefore would nominate that Float32 is not to blame and that the reason must be somewhere else.

The line texture is used only for visualizing the problem. The problem persists also with other (more natural) kinds of textures.

Edit 2 begins

Enabling or disabling antialiasing makes no visible difference

Edit 2 ends

like image 802
Asta Avatar asked Jan 09 '12 11:01

Asta


2 Answers

i believe that what you are seeing may really be caused by the precission. You correctly calculated that the floating-point coordinates should be pretty enough, the problem is the hardware is not using floats to lookup the textures. The texture interpolator units do have considerably lower precision (don't know how is it today, but it used to be as low as 16 bits on older GeForce cards).

So ... how can one exceed interpolator precision? By using large texture coordinates (many repeats) on a large geometry, which is exactly what you are doing. Remedy? Subdivide your geometry to be using smaller texture coordinates (you can shift texture coordinates in integer steps so they are closer to 0).

Here is a screenshot of how extreme it can look like (i weren't able to reproduce the error on my GeForce 260, but it is clearly visible on my Tegra 2 tablet, as shown in the image below).

like image 163
the swine Avatar answered Nov 14 '22 22:11

the swine


I ran into similar problem under iOS. After repeating the texture 127 times, bad things started to happen.

The solution that worked was this:

I used GL_TRIANGLE_STRIP with some degenerate triangles. The texture is aligned to the vertieces, so at the edge of the texture there is an invisible (degenerate) triangle, where the texture is "displayed" mirrored as I set the texture coordinate to the origin. Thus the next visible triangle shows the texture from coordinate (0.0, 0.0) and it never goes over coordinate (x, 127.0).

There is a blog post explaining this with some examples and pictures.

like image 25
Vili Avatar answered Nov 14 '22 22:11

Vili