Regarding the sv_position input in the fragment shader...

I was making a shader to show in screen the depth buffer ( learning how to do it), and realized something a bit odd. I have this code:

struct v2f
{
    float4 pos : SV_POSITION;
    float4 projPos : TEXCOORD1; //Screen position of pos
};

//vertex program
v2f vert(appdata_base v)
{
    v2f o;
    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    o.projPos = (o.pos / o.pos.w) * 0.5 + 0.5;
    return o;
}
// fragment
half4 frag(v2f i) : COLOR
{
    float depth = Linear01Depth(tex2D(_CameraDepthTexture, i.projPos.xy).r);
    half4 color;
    color.xyz = depth;
    color.w = 1;
    return color;
}

If I understood correctly ( and i’m guessing I didn’t :stuck_out_tongue: ), the position that comes in to the fragment shader, is the vertex position in clip space, before the perspective division ( as stated here http://wiki.unity3d.com/index.php?title=Shader_Code#Vertex_Shader_to_Fragment_Shader_Structure_.28v2f.29 ).

So that means that the position what comes out of the vertex program and then comes in to the fragment program, are the same ( since multiplying by the MVP already gives me the vertex position in clip space).

So in theory, I could move the perspective division and multiplication operations to the fragment shader, and it should result in the same results, but they aren’t ( it comes all white ).

float depth = Linear01Depth(tex2D(_CameraDepthTexture, (i.pos.xy/i.pos.w) * 0.5 + 0.5).r);    // doesn't work

So crearly there’s something that I didn’t understand correctly. Any help appreciated. Cheers

(btw by projection space I hope they are referring to the same transformation showed here http://http.developer.nvidia.com/CgTutorial/elementLinks/fig4_1.jpg , after the projection transformation you get into clip space)

SV_POSITION semantic has different meaning when used in vertex and pixel shader respectively. It is a position in clip space in vertex shader and screen space position in pixel shader. So in your pixel shader i.pos.x is in range from 0 to screenWidth and i.pos.y is in range from 0 to screenHeight. SV_POSITION in pixel shader is an replacement for VPOS semantic from the old days. It will only work under DX10 and up or equivalent OpenGL.

Oh you just cleared up a big misunderstanding that I had.
I would like to ask one more question, according to this image:


There it says that ( on the left) after the perspective divide , you get “Normalized Device Coordinates - real” ( and by real I suppose that they are referring to screen size in pixels) , but according to this (section 4.1.10) and this you only get the “real” coordinates after the viewport transform, so in the normalized device coordinates you still have the homogeneous form. Is that correct?

Cheers
(and btw that image I got it from here section 9.3.1)

SV_POSITION etc should work on all hardware unity supports.

I guess by “real” they mean “not homogeneous”. You have 4D homogeneous clips space, you do perspective divide and you have NDC. NDC is 3D space where x and y are in range [-1, 1] and z is in range [-1, 1] on OpenGL and [0, 1] on DirectX. Then you apply viewport transform and you have screen space (or window space in that picture).

I’m pretty sure you can’t read pixel position in pixel shader on older GPUs and OpenGL ES doesn’t support it as well.

I see, thanks a lot :slight_smile: