Search Unity

Vertex shader with lookup textures and different sizes of textures

Discussion in 'Shaders' started by pahe, Jul 22, 2017.

  1. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    Hi guys.

    I'm struggling a bit with my vertex shader. The following code is giving me the colors of my lookup texture (_AnimationTex) and I distort the vertices of my main texture with it.

    Code (CSharp):
    1. float4 distortion = tex2Dlod(_AnimationTex, float4(IN.texcoord0.xy,0,0)); // texcoord0 is for the main texture, not the _AnimationTex
    2.  
    3. // distortion.x = textures red channel
    4. // distortion.y = textures green channel
    5. // distortion.z = textures blue channel
    6. // distortion.w = textures alpha channel
    7.  
    8. distortedPosition.x += distortion.r * _xDistortionFactor * distortionFactor; // red color used for x-axis
    9. distortedPosition.y += distortion.g * _yDistortionFactor * distortionFactor; // green used for y-axis
    10. distortedPosition.z += distortion.b * _yDistortionFactor * distortionFactor; // blue used for z-axis
    11.  
    12. IN.vertex = distortedPosition;
    13. OUT.pos = UnityObjectToClipPos(IN.vertex);
    That seems to work, but now I wonder if my lookup texture has to be the same size as my main texture. I attached both textures, which differ in size and format. When I'm running my shader, the distortion is not at the positions I would like them to have, but bigger (like the lookup texture is streched up). Is it possible to have different texture sized or do both textures have to be the same size?

    Thx for help,
    Patrick

    Lookup texture and background:
    Animation.jpg waterbackground.jpg

    How I would like it to be positioned:
    level.jpg
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    The textures does not have to be the same size, but if both textures are using the same UVs they do need to match positionally. UVs are a normalized positions within the texture, their pixel dimensions are irrelevant.

    To explain that differently, UVs usually have a range of 0.0 to 1.0 where 0.0, 0.0 is the bottom left of the image, and 1.0, 1.0 is the top right. 0.5, 0.5 is the center of the image, regardless of the texture resolution, or aspect ratio.

    Since your lookup texture appears to be cropped down from the original image you either need to un-crop it, or you need to adjust the UVs it uses to offset & scale it to line up with the area you want it to overlap.
     
    pahe likes this.
  3. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    Ok, thank you for the explanation. Is there an easy way to achieve that uncropping or to calculate this offset and scale? And if not, how would I start with the calculation? I would know how to do it in C# for a transform, but I'm not that familiar with shader code.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    By default any texture you add to a shader properties list gets a scale offset parameter that shows up on the material inspector. The values you set there gets passed to the shader via a _TextureName_ST variable. Default shaders usually have a _MainTex_ST already pre-defined. Within the shader there's usually also a TRANSFORM_TEX(v.uv, _MainTex) or something like that, and that's a shader macro to apply that _ST variable.

    Here's what that macro does (copy / pasted from UnityCG.cginc):
    Code (CSharp):
    1. // Transforms 2D UV by scale/bias property
    2. #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    turns into:
    o.uv = v.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;

    What you'll want to do is use something like:
    tex2Dlod(_AnimationTex, float4(TRANSFORM_TEX(IN.texcoord.xy, _AnimationTex),0,0));

    Then modify the scale and offset settings for the animation tex to position it where you want. If you want to be precise about it rather than just fiddling with the numbers then you'll need to do the math for it.

    Scale = _MainTex Resolution / _AnimationTex Resolution
    Offset = Pixel offset from bottom left / _AnimationTex Resolution * Scale

    In the case of your textures that would be
    scale = (4096, 1489) / (3074, 432) = (1.3325, 3.4468)
    offset = (694, 511) / (3074, 432) * (1.3325, 3.4468) = (0.124259, 0.0914931)

    Put those numbers into the scale and offset values and it should line up (assuming I didn't f up someplace)
     
    hopeful and pahe like this.
  5. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    @bgolus Wow... thanks a lot for the help! I'll try it out.