1
\$\begingroup\$

I've written a custom shader (with help) and I'm not sure why it does not have tiling & offset capabilities. What is the simplest way to add that feature to my shader?

current shader code

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/RadarTile"
{
    Properties {
        _MainTex ("Base (RGB) Trans (A)", 2D) = "black" {}
    }
    
    SubShader {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        //LOD 100 // todo: may need to go up after bump map added @jkr
        
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        // Blend One SrcAlpha
         

        Pass {  
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                // #pragma multi_compile_fog
                
                #include "UnityCG.cginc"

                uniform float2 _Tiling;
                uniform float2 _Offset;

                float _EdgeUVEpsilon;
    
                sampler2D _MainTex;
                sampler2D _RadarFrame2;
                sampler2D _ReflectivityLUT;
                float _FrameInterpolationAmount;
                float4 _ShadowColor;


                sampler2D _NextTex;
                float _PlaybackTime;
                float _PlaybackPosition;
                int _TotalFrames;
                int _FirstFrameIndex;
                int _LastFrameIndex;

                #include "inc/TileBender.cginc"

                v2f vert(appdata v)
                {
                    // v2f output = vertBender(v, _EdgeUVEpsilon);
                    // return output;

                    // v.texcoord *= _Tiling;    // Apply tiling
                    // v.texcoord += _Offset;    // Apply offset

                    return vertBender(v, _EdgeUVEpsilon);
                }
                
                float4 frag (v2f i) : SV_Target
                {
                    fixed4 col = lerp(tex2D(_MainTex, i.uv), tex2D(_RadarFrame2, i.uv), _FrameInterpolationAmount);
                    col = saturate(pow(col, 1.0/2.2));
                    col = tex2D(_ReflectivityLUT, float2(col.r, 0));

                    if (col.a > 0) return _ShadowColor; // comment out to disable shadows @jacksonkr_
                    return 0;
                    // return col.a > 0 ? _ShadowColor : 0;

                }
            ENDCG
        }

        Pass {  
            CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                // #pragma multi_compile_fog
                
                #include "UnityCG.cginc"

                float _ReflectivityHeightMultiplier;
                float _EdgeUVEpsilon;
    
                sampler2D _MainTex;
                sampler2D _RadarFrame2;
                sampler2D _ReflectivityLUT;
                float _FrameInterpolationAmount;

                float3 _LightDirection;
                float3 _LightColor;
                float _NdotlEffect;
                float _RadarLightAttenuation;
                float _Roughness;
                float _Vibrance;

                #include "inc/TileBender.cginc"


                v2f vert(appdata v)//appdata_tan_ v)
                {
                    v2f output = vertBender(v, _EdgeUVEpsilon);

                    //this is a bit of a roundabout way to get here, but I have to work around the tile bending code so we're going with it -BH
                    float reflectivity = tex2Dlod(_MainTex, float4(output.uv, 0, 0)).r;
                    float4 offsetWorldPosition = float4(output.worldPos + output.norm * reflectivity * _ReflectivityHeightMultiplier, 1);
                    output.pos = UnityObjectToClipPos(mul(unity_WorldToObject, offsetWorldPosition));

                    //normal calculation
                    const float e = 1.0 / 129.0;
                    if(output.uv.x <= _EdgeUVEpsilon + e || output.uv.x >= 1 - _EdgeUVEpsilon - e || output.uv.y <= _EdgeUVEpsilon + e || output.uv.y >= 1 - _EdgeUVEpsilon - e)
                    {
                        return output;
                    }

                    /*
                    //tangent
                    float2 tangentUV  = v.uv + float2(e,0);
                    float3 tangentSamplePoint = v.position + v.tangent * e;
                    float3 tangentWorldPosition = mul(unity_ObjectToWorld, tangentUV);
                    float3 tangentNormal = normalize(tangentWorldPosition);
                    reflectivity = tex2Dlod(_MainTex, float4(tangentUV, 0, 0)).r;
                    tangentWorldPosition = tangentWorldPosition + tangentNormal * reflectivity * _ReflectivityHeightMultiplier;
                    float3 tangent = normalize(tangentWorldPosition - offsetWorldPosition);
                    //binormal
                    tangentUV = v.uv + float2(0, e);
                    tangentSamplePoint = v.position + cross(v.normal, tangent) * e;
                    tangentWorldPosition = mul(unity_ObjectToWorld, tangentUV);
                    reflectivity = tex2Dlod(_MainTex, float4(tangentUV, 0, 0)).r;
                    tangentWorldPosition = tangentWorldPosition + tangentNormal * reflectivity * _ReflectivityHeightMultiplier;
                    float3 binormal = normalize(tangentWorldPosition - offsetWorldPosition);
                    //final calc
                    output.norm = -cross(tangent, binormal);
*/


                    return output;
                }
                
                float4 frag (v2f i) : SV_Target
                {

                    fixed4 col = lerp(tex2D(_MainTex, i.uv), tex2D(_RadarFrame2, i.uv), _FrameInterpolationAmount);
                    col = saturate(pow(col, 1.0/2.2));

                    const float3 precipitationTypeThresholds = saturate(pow((float3(255, 200, 150) - 0.5)/ 255.0, 1.0/2.2));

                    float v = 0;
                    if( col.a > precipitationTypeThresholds.x)
                    {
                        v = .67;
                    }
                    else if(col.a > precipitationTypeThresholds.y)
                    {
                        v = .34;
                    }
                    else if(col.a > precipitationTypeThresholds.z)
                    {
                        v = 0;
                    }
                    col = tex2D(_ReflectivityLUT, float2(col.r, v));

                    
                    //minnaert shading implementation
                    float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.norm * _EarthRadius);
                    float3 cameraSpaceLightDirection = mul(unity_CameraToWorld, normalize(_LightDirection));

                    float NdotL = max((1 - _NdotlEffect), dot( i.norm, cameraSpaceLightDirection));
                    float NdotV = max(0, dot( i.norm, viewDirection ));

                    float3 minnaert = saturate(NdotL * pow(NdotL * NdotV, _Roughness));

                    float3 lightingModel =  minnaert * col.xyz;
                    float3 attenColor = _RadarLightAttenuation;
                    col = float4(lightingModel * attenColor, col.a);

                    //vibrance
                    half average = (col.r + col.g + col.b) / 3.0;
                    half maximum = max(col.r, max(col.g, col.b));
                    half vibrance = (maximum - average) * (-_Vibrance * 3.0);
                    col.rgb = lerp(col.rgb, half3(maximum, maximum, maximum), vibrance);

                    // float4 blend = tileblend(i, col);
                    // return blend;

                    return col;

                }
            ENDCG
        }
    }
}

TileBender.cginc

/**
// Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members worldPos)
#pragma exclude_renderers d3d11
 * this cginc helps bend shaders to a sphere
 */

// #define PI_5 1.5707963267948966192313216916398f
// #define PI 3.1415926535897932384626433832795f
// #define PI2 6.283185307179586476925286766559f
// #define QUARTER_PI 0.7853981634


// float _TileOverlap;
// float _TileBlendFactor;
float _ShadowOffset;

    
struct appdata {
    float4 pos: POSITION;
    float2 uv     : TEXCOORD0;
    float4 normal : NORMAL;
};

// struct appdata_tan_ {
//     float4 position: POSITION;
//     float2 uv    : TEXCOORD1;
//     float4 normal : NORMAL;
//     float4 tangent : TANGENT;
// };


struct v2f {
    float4 pos : SV_POSITION;
    float3 norm : NORMAL;
    half2 uv : TEXCOORD0;
    float3 worldPos : COLOR0;
    // UNITY_FOG_COORDS(1)
};

float _EarthRadius;

// #pragma distance from earth

void procDistFromEarth(inout v2f o) {
    float4 offsetWorldPosition = float4(o.worldPos - _ShadowOffset * o.norm, 1);
    o.pos = UnityObjectToClipPos(mul(unity_WorldToObject, offsetWorldPosition));
}

// #pragma vertbender

// v2f vert(appdata v)
/**
 * bends the vertices to fit a sphere shape @jacksonkr_
 */
v2f vertBender(appdata v, float _EdgeUVEpsilon)
{
    v2f o;

    o.pos = UnityObjectToClipPos(v.pos);
    o.uv = clamp(v.uv, _EdgeUVEpsilon, 1-_EdgeUVEpsilon);
    o.norm = v.normal;
    o.worldPos = mul(unity_ObjectToWorld, v.pos);

    procDistFromEarth(o);

    return o;
}
```
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I felt silly posting this question because I knew the answer would be simple.

Here's what was missing

First Pass:

  • float4 _MainTex_ST;
  • v2f vert: output.uv = TRANSFORM_TEX(v.uv, _MainTex);

Now tiling & offset work as expected.

citation: https://forum.unity.com/threads/undeclared-identifier-_maintex_st.468626/

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .