What is TRANSFORM_UV?

I’m trying to retrofit an old, obsolete package from the forums, and am running into shader errors that I have no idea how to handle.

This is the original shader:

// Upgrade NOTE: replaced 'PositionFog()' with multiply of UNITY_MATRIX_MVP by position
// Upgrade NOTE: replaced 'V2F_POS_FOG' with 'float4 pos : SV_POSITION'

Shader "TestShader" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _MainTex ("Base (RGB)", 2D) = "grass" {}
        _LightPower ("Light Power", Float) = 0.0
    }
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma fragmentoption ARB_fog_exp2
            #include "UnityCG.cginc"

            float4 _Color;
            sampler2D _MainTex;
            float _LightPower;

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 color : COLOR0;
                //float4 lighting : TEXCOORD1;
            };

            struct indata
            {
                float4 vertex;
                float3 normal;
                float4 texcoord;
                float4 color;
            };

            v2f vert(indata v)
            {
                v2f o;
                o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                o.uv = TRANSFORM_UV(0);
                o.color = v.color; //_Color; //v.normal * 0.5 + 0.5;
                //o.lighting = v.color;
                return o;
            }

            half4 frag(v2f i) : COLOR
            {
               
                return half4(i.color*tex2D(_MainTex, i.uv).rgb, 1);//*i.lighting;
            }
            ENDCG

            //Material {
            //    Diffuse [_Color]
            //}
            //Lighting On
            //SetTexture [_MainTex] {
            //    constantColor[_Color]
            //}
        }
    }
}

This throws this error :

Shader error in 'TestShader': 'vert': input parameter 'v' missing semantics at line 38 (on d3d11)

I fixed this by changing the ‘indata’ struct to this:

struct indata
{
    float4 vertex : POSITION;
    //float3 normal;
    //float4 texcoord;
    float4 color : COLOR;
};

This reveals the following error:

Shader error in 'TestShader': invalid subscript 'texcoord' at line 42 (on d3d11)

I now know that this is due to the presence of the macro “TRANSFORM_UV”. I only know this because of this page, the only reference to what “TRANSFORM_UV” actually does that I could find.

Why can’t I find any documentation whatsoever concerning this? What does it do, and how do I fix this error?

That page you linked describes exactly what the function did (I think it was removed in Unity 3.0, certainly isn’t in 4 or 5), and the steps to replace it, so I’m confused what more you want.

edit: ah, the error you’re getting is you commented out the texcoord from the “indata” struct. You haven’t even gotten to the point of getting an error about TRANSFORM_UV itself. (Maybe it still does exist ?!) You need that value, but it should be:

float2 texcoord : TEXCOORD;

You might want to read this (all 5 parts):

Won’t immediately help with upgrading old shaders, but will help you understand the parts of the shader better.

The macro references an external variable not passed to it? This seems very strange.

The page mentions in passing what it’s used for, but not explicitly what it does. What is the significance of the macro’s argument, what external values does it reference, and what does it return?

You’re dealing with a very, very old shader. That page you linked has a few clues in it, but here’s the basics.

Textures were assigned to one of a handful of API defined register indexes. The texture transform (scale & offset) were stored in similarly API defined matrices. In fixed function shaders you just say “sample this texture register” and it applied the matching matrix to it automatically in the hardware.

The first versions of “vertex fragment” shaders still used a lot of the fixed function stuff. In this case to get the texture scale and offset TRANSFORM_UV(0) would have gotten the texture UVs transformed by the first texture matrix.

Modern shaders eschew using the built in fixed function matrices for passing the data to shaders as arbitrary data. Unity does this though the _textureName_ST value.

1 Like