Search Unity

Question What is the meaning of screenposition.xy/screenposition.w

Discussion in 'Shaders' started by Chahorain, Oct 19, 2021.

  1. Chahorain

    Chahorain

    Joined:
    Dec 20, 2017
    Posts:
    25
    This could be a very dumb question, but I am struggling the meaning of screenposition.xy/screenposition.w while calculating the screenspace shader, what does the xy and w contain and why do we need to have this division?
    I read a sentance from https://www.ronja-tutorials.com/post/039-screenspace-texture/
    "This division is to counteract the perspective correction the GPU automatically performs on interpolators."
    I cannot understand the meaning of this sentance, can anyone help me please...
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Modern GPUs do what's called "perspective correction" on things like UVs, or really any value that's interpolated from the vertex shader to the fragment shader. To understand why, look the PlayStation 1. The weird way the textures on walls warp in that game is a direct result of that console not having perspective correction. Every console afterwards and all modern GPUs do.

    Wikipedia's page on texture mapping has a great example of the kind of artifacts that show up on the PS1, as well as perspective correction.


    The "Affine" example is what a flat quad angled slightly away from the viewer might look like on the PS1, where the "Correct" example is using perspective correction and is more what you want for that flat quad. (Note, the Affine example is also what it looks like on modern GPUs if you just have a mesh that's a parallelogram instead of a flat quad that's angled away from the viewer.)

    Why you have the w here at all has to do with how linear perspective projection works, and how perspective projection is applied. Suffice to say if you really want to know search for "homogeneous coordinates" and then be prepared to be confused; the TLDR is for values that you want to have perspective correction, the GPU is multiplying them by the linear world depth, interpolating those values, and then dividing them by the interpolated world depth value, and the result is proper perspective correction.

    The problem is for screen space UVs you don't want the perspective correction. If you do the divide by w in the vertex shader beforehand the screen space UVs start to warp weirdly ... because they're being treated as if they're supposed to be surface texture UVs and being perspective corrected. If you interpolate the values already multiplied by the linear world depth, and then divide by that "perspective correct" interpolated linear world depth, you can undo the perspective correction and get affine texture mapping again. Which is what you want for screen space UVs.



    If none of that made any sense to you still, the TLDR is "to make them work correctly". If you divide by w in the vertex shader it'll warp weirdly.


    Alternatively if you're not using a surface shader you can use the
    noperspective
    modifier on the variable in the struct to tell the shader to not do perspective correction, and then you can do the divide by w in the vertex shader.
     
    Chahorain and Invertex like this.
  3. Chahorain

    Chahorain

    Joined:
    Dec 20, 2017
    Posts:
    25
    Thank you! I will try to digest this information and come back if I still cannot understand!