1
\$\begingroup\$

I ran into a problem with using gl_FragCoord variable to access texels. The problem can be illustrated by following example:

First I render a textured quad into texture of size (W, H) where W and H are viewport width and height correspondingly. Then I draw another quad with lower left corner in (0, 0) and upper right corner in (W, H) (so that it effectively takes whole viewport) which is textured with this texture. Let's call it quad A. Then I draw another quad (let's call it quad B) on top of it, with lower left corner in (0, H1) and upper right in (W, H) and also use the same texture for it. The whole scene can be illustrated by this picture:

scene

As you can see, the bottom part of the first quad lays in quad A and a top part in quad B. Thus when I experiment with fragment shader for quad B I can see whether the top part of the quad matches the bottom part.

Now to the problem:

When in fragment shader for quad B I use

gl_FragColor = texture2D(u_backgroundTexture, v_texCoord);

(v_texCoord is (0, 0) for lower left corner and (1, 1) for upper right)

to determine fragment color, everything is fine. Top and bottom parts of the first quad perfectly match each other:

good

However, when I change this line to:

gl_FragColor = texture2D(u_backgroundTexture, gl_FragCoord.xy / u_resolution);

(where u_resolution is a vec2(W, H))

the top and bottom parts of the quad doesn't match anymore. If I render that quad close to right edge of the screen I get following artifacts:

artifacts right

and if I draw it close to the left side artifacts looks like this:

artifacts left

Could anyone please explain what are the possible causes for such artifacts? Apparently I am missing some fundamental understanding of how texturing works, since in my mind texture2D(u_backgroundTexture, v_texCoord) should be completely equivalent to texture2D(u_backgroundTexture, gl_FragCoord.xy / u_resolution); in my case.

P.S. Obviously, for quad A I always use gl_FragColor = texture2D(u_backgroundTexture, v_texCoord) in fragment shader.

\$\endgroup\$
  • \$\begingroup\$ Is u_backgroundTexture perhaps a texture you're rendering to? \$\endgroup\$ – Nicol Bolas Jan 3 '16 at 20:59
  • \$\begingroup\$ Yes, it is the identifier of the texture to which I rendered first quad \$\endgroup\$ – Oleg Jan 3 '16 at 22:08
  • \$\begingroup\$ That wasn't what I asked. I asked if that was the texture you're rendering to. That is, are you trying to render to a texture you're reading from simultaneously. \$\endgroup\$ – Nicol Bolas Jan 4 '16 at 0:48
  • \$\begingroup\$ No, I only reading from this texture and render on screen. So the sequence looks like this: render first (small) quad into texture u_backgroundTexture, then render quad A on screen, then render quad B on screen. So both quads A and B only read values from this texture via texture2D. \$\endgroup\$ – Oleg Jan 4 '16 at 1:08
0
\$\begingroup\$

I finally found the root-cause of this weird discrepancy.

I use Cocos2d framework which builds projection matrix from the current camera settings. As it turned out, projection matrix built by Cocos2d has some precision loss. Thus, after vertices of quads A and B multiplied by projection matrix, the result vertices don't hit exact points (-1, -1), (-1, 1), (1, 1), (1, -1) in NDC as I would expect. The actual NDC of the points look more like (-1.00164..., -1.00164...) etc. This causes texture on quad A to be just a little bit stretched which is why it doesn't match texture on quad B.

To "fix" for this issue I changed coordinates of quads A and B to NDC and removed multiplication by Cocos2d's projection matrix from vertex shader.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.