Search Unity

Accessing _GrabTexture from within Cg programs

Discussion in 'Shaders' started by cblarsen, Apr 23, 2008.

  1. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I am having trouble generating texture coordinates for the grabtexture for use in my Cg fragment code.

    There seems to have been a way that worked on 1.x, but doesn't anymore. I took some code from Aras' refraction shader on the wiki, and it seems to work as badly as my own code on 2.0:
    Code (csharp):
    1.  
    2. // Irrelevant details clipped out
    3. sampler2D _MainTex : register(s1);
    4. samplerRECT _GrabTexture : register(s0);
    5.  
    6. struct v2f {
    7.     V2F_POS_FOG;
    8.     float4 uvrefr    : TEXCOORD0;
    9.     float2 uv         : TEXCOORD1;
    10.     float3 normal    : TEXCOORD2;
    11. };
    12.  
    13. v2f vert (appdata_base v)
    14. {
    15.     ...
    16.     o.uvrefr = mul( glstate.matrix.texture[0], v.vertex );
    17.     ...
    18.     return o;
    19. }
    20.  
    21. half4 frag( v2f i ) : COLOR
    22. {
    23.     ...
    24.     half4 refr = texRECTproj( _GrabTexture, i.uvrefr );
    25.     ...
    26. }
    I assume, that what is needed is doing an objectspace to viewspace to pixelspace transformation.

    I have attempted doing:
    Code (csharp):
    1. struct v2f {
    2.     float4 pos : POSITION;
    3.     float2 tex;
    4.     float4 uvgrab;
    5.     float3 viewDirT;   
    6. };
    7.  
    8. v2f_trace binary_trace_vert (appdata_tan v)
    9. {
    10.     v2f_trace o;
    11.     o.pos = mul( glstate.matrix.mvp, v.vertex );
    12.  
    13.         // Pretending to know the width and height
    14.         // of the viewport
    15.     const float viewportwidth = 300;
    16.     const float viewportheight = 200;
    17.     float4x4 viewtopixels =  
    18.   float4x4(viewportwidth/2, 0, 0, 0,
    19.            0,  viewportheight/2, 0, 0,
    20.            0, 0, 1, 0,
    21.            viewportwidth/2, viewportheight/2, 0, 1 );
    22.     o.uvgrab = mul(viewtopixels, o.pos);
    23.         ...
    24. };
    25.  
    26. float4 binary_trace_frag( v2f_trace i) : COLOR
    27. {
    28.    ...
    29.    // This doesn't really work:
    30.    float4 grabdata = texRECTproj(_GrabTexture, i.uvgrab );
    31.    // What seems to get close is:
    32.    float4 grabdata = texRECT( _GrabTexture, (i.uvgrab.xy + float2(1,1)) * viewportwidth);
    33.  
    34.    ...
    35. }
    36.  
    So there are two problems here:
    - The projective transform doesn't seem to work as I would expect
    - I don't really know the size of the viewport from within a shader. Or do I?
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    (sorry for not replying earlier, this thread slipped through my radar)

    The Refraction shader does work for me.

    How it computes the coordinates: GrabPass sets up a texture matrix that goes from object coordinates into final screen coordinates. You can see that the code transforms vertex position with the texture matrix.

    Of course, one complication is that it's hard to know which texture matrix to use. Refraction shader solves this by binding textures to sampler registers explicitly, and issuing dummy SetTexture commands in appropriate order.

    You can also write shader in a regular way, and manually check out which texture matrix to use.
     
  3. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    No worries. I know you are a busy guy :)
    And not for me. I will try to make a new clean attempt to figure out if it was just me, or if it is an issue with my particular card. (Radeon X1900)
    Well, this explanation fits pretty much what I expected, and I did try assigning registers and dummy SetTexture, but that shader got really messed up, so I am going to try from scratch with something simple.

    Thanks for confirming how it should work :)
     
  4. cblarsen

    cblarsen

    Joined:
    Mar 10, 2007
    Posts:
    266
    I figured it out: USER ERROR! :oops:

    Yep, I had somehow overlooked the Unity Pro standard refraction shader and was trying to use the 1.x one.

    At least this shows how to combine GrabTexture with a custom fragment shader. I will be wanting to write my own vertex shader too, which is going to be interesting, but my confidence in Unity and the Cg compiler has been restored for now. :)