It looks like that sampling the same exact color data from different areas of a texture atlas results in different vec4
in the GLSL fragment shader.
In other words, texture2D
is directly dependent of the specified texture coordinates, and not only transitively because of the color of the texel at those coordinates.
To say that with an example, I am getting the impression that sampling a red pixel surrounded by blue pixels from, say, (0.1, 0.2)
may give a different result than sampling the same shade of red surrounded by the same shade of blue at, say, (0.7, 0.3)
.
Is this non-deterministic behavior that I am observing likely to be real?
Additional details
I have a atlas that we use to texture multiple screen-aligned quads. Each vertex has a xy
position and uv
texture coordinates. The allotted rectangles in the atlas do not overlap; furthermore, a 2 pixel margin exists between adjacent rectangles. We are using linear filtering and no mipmapping.
The atlas is populated dynamically using sprites downloaded from the web. Two different runs of the program may have the atlas populated in different orders, even if user input is exactly the same, due to the fact that some HTTP requests may complete before others.
So now imagine that on a run we have a Princess Peach sprite in the middle of the screen; the texture is coming from the upper left corner of the atlas, because Princess Peach was the first sprite added to the scene.
In another run, there have been a few sprites loaded but now their quads are not on the screen and again we have Princess Peach in the middle, in the same exact position as the first run. But this time the texture is coming from a different region of the atlas.
Problem: rendered images are not the same. The differences are imperceptible and usually consist of only a few pixels near the edges of the rendered sprites. The differences are detected by a screenshot testing framework. Where is the source of randomness?
Even more details
- It's a WebGL project.
- It happens on both GeForce and Quadro cards.
- Using nearest neighbor sampling leads to more stable (and ugly) renderings but it does not fully eliminate the problem.
- Enforcing a strict order when copying the sprites to the atlas fully solves the problem, but it is not an acceptable solution.
- I inspected the GL state using an inspector and I found two frames that should have been the same in two different runs of the program; the state is the same in both cases, the only difference being a different arrangement of sprites in the atlas, and consequently different texture coordinates in the array buffer.
- I know that I could test using some sort of fuzzy/thresholded comparison but first I would like to rule out bugs on my side.