7
votes

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

2
Have you tried it on different computers/browsers? Or the "webgl.prefer-native-gl" setting?Ville Krumlinde
Excellent point, I almost forgot to do so. I have tested it on Win XP on both the newest Firefox and Chrome, and on Ubuntu on Chrome. The behaviour on Windows is approximately the same regardless of the browser. On Ubuntu the textures shake when rotating the camera, but do not get distorted. I will edit the question with this update. I haven't tried the setting you mentioned, but will do it later when I get to the Win XP computer.Asta
That option set to true caused the page to not work at all :(Asta
Are all your tests done on the same computer? Perhaps if you make a public page we could help test it on other hardware.Ville Krumlinde
I hate to throw this out, but seeing as how you say it's working everywhere but the one OS, I suspect that there may be some faulty drivers at play. Not to say you couldn't work around it by twiddling options (you may have hit on some obscure and rarely tested edge case state), but I don't know of any legitimate reason for getting the behavior you are seeing.Toji

2 Answers

6
votes

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).

2
votes

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.