Search Unity

How can i read from a specific UV position on frag shader?

Discussion in 'Shaders' started by FranFndz, Sep 2, 2019.

  1. FranFndz

    FranFndz

    Joined:
    Sep 20, 2018
    Posts:
    178
    I think is a well asked question but i still can not do it in a nice way.

    For example, i have a shader who read from a ramp texture.
    Width 64 px, Height 1 px.
    it go White to Black.
    on my Shader i just do:
    tex2D(_time.y, 0).

    Now i have the same texture but in each Y pixel a diferent ramp texture.
    Width 64 px, Height 3 px.
    y 1 pixel : White to Black
    y 2 pixel: Black White Black
    y 3 pixel: Red to Grenn.

    i try to get the colors using the same technique as above:
    tex2D(_time.y, 0).
    tex2D(_time.y, 0.5).
    tex2D(_time.y, 1).

    for the y 1 and y 3 i got it with no issues, but y 2 is kinda dirty, is no perfect at all.
    i fixed the issue duplicating the y Pixel;
    Width 64 px, Height 6 px.
    y 1-2 pixel : White to Black
    y 3-4 pixel: Black White Black
    y 5-6 pixel: Red to Grenn.

    Now it work perfectly. but why? What if i want to have 32 diferent gradients stored insideY texture?
    How can i read the texture by lines?
    I tought my issue was:
    Texture is no Linear so the Gamma give me the error. I create the texture from script and save as linear, still same issue.
    Texture is Repeat and not Clamp. Even if i change those properties the result is the same.
    The texture is bind to the quad so i dont have enought vertex to take the pixel?

    Appreciate any help.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    This makes no sense to me. 1 and 3 shouldn’t work at all (and be identical), where 2 should be correct. This makes me think you’re importing the texture and it’s being converted into a 64x4 compressed texture and you’re using wrap set to clamp. Make sure you’re using an uncompressed texture, and that you have “Power of Two” set to “None” to keep Unity from rescaling the texture. Make sure the preview of the texture in the inspector is showing RGB24 64x3.

    After that, know that a UV of float2(time, 0.0) isn’t the first pixel, it’s the top of the image, between the top and bottom pixels. The first pixel’s value depends on the resolution of the texture, but it’s 0.5/texture height. In the case of a 3 pixel height texture, it should be:

    tex2D(_RampTex, float2(_Time.y, 0.1666667); // y 1
    tex2D(_RampTex, float2(_Time.y, 0.5); // y 2
    tex2D(_RampTex, float2(_Time.y, 0.66666670.8333333); // y 3

    Unity automatically passes texture dimensions to the shader via a special uniform variable:
    float4 _MyTextureName_TexelSize;

    So you can use ramp textures of arbitrary dimensions and use an index to select the appropriate row.

    tex2D(_RampTex, float2(_Time.y, _RampTex_TexelSize.y * 0.5 + _Index * _RampTex_TexelSize.y); // 0 based index
     
    Last edited: Sep 3, 2019
  3. resetme

    resetme

    Joined:
    Jun 27, 2012
    Posts:
    204
    Again, thank you for always helping people.

    Yes, is not 0 , 1. but is 0.1 and 0.9 (for y 1 and y 3).

    I marked the texture as None for Power of 2 and now is working flawless with only 3 pixels height.

    0.166667 give me the correct ramp, 0.5 also correct, but 0.6 Is not showing the ramp properly, so I did 1-0.166 (0.83) and I have the correct ramp now.

    Using the texel size is awesome!

    This was really helpful for me thanks!

    Ups, this is my personal account, the other one is company account.

    Any time u come to Japan let me buy u some sushi.
     
    Last edited: Sep 3, 2019
    bgolus likes this.