Shader "Custom/RubCard" { Properties { _Color ("Main Color", Color) = (1,1,1,1)//Tint Color _MainTex ("Base (RGB)", 2D) = "white" {} _MainTex_2 ("Base (RGB)", 2D) = "white" {} ratioY ("ratioY", Float) = 0 radius ("radius", Float) = 0 height ("height", Float) = 0 anchorY ("anchorY", Float) = 0 rubOffset ("rubOffset", Float) = 0 maxRubAngle ("maxRubAngle", Float) = 0 _ZOffsetOne("ZOffsetOne",Float)=0 _ZOffsetTwo("ZOffsetTwo",Float)=0 _Move("Move",Float)=0 } SubShader { Tags {"Queue"="Geometry" "RenderType"="Opaque" } LOD 100 Pass { Name "ONE" Tags{"LightMode" = "UniversalForward"} Cull Front Lighting Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" sampler2D _MainTex; float4 _MainTex_ST; fixed4 _Color; float ratioY; float radius; float height; float anchorY; float rubOffset; float maxRubAngle; float _ZOffsetOne; float _Move; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; float4 tmp_pos = v.vertex; float tempAngle = 1.0; tmp_pos.xyz = mul(unity_ObjectToWorld,float4(tmp_pos.xyz,0)).xyz; float pi = 3.14159; float halfPeri = radius * pi * maxRubAngle; float rubLenght = height * (ratioY - anchorY); tmp_pos.y += height*rubOffset; float tempPosY = tmp_pos.y; if(tmp_pos.y < rubLenght) { float dy = (rubLenght - tmp_pos.y); if(rubLenght - halfPeri < tmp_pos.y) { float angle = dy/radius; tmp_pos.y = rubLenght - sin(angle)*radius; tmp_pos.z = radius * (1.0- cos(angle)); } else { float tempY = rubLenght - halfPeri - tmp_pos.y; float tempAngle = pi * (1.0-maxRubAngle); tmp_pos.y = rubLenght - radius*sin(tempAngle) + tempY * cos(tempAngle); tmp_pos.z = radius + radius*cos(tempAngle) + tempY * sin(tempAngle); } } tmp_pos.x += unity_ObjectToWorld[3][0]; tmp_pos.y += unity_ObjectToWorld[3][1]; tmp_pos.z += unity_ObjectToWorld[3][2]; float4 pos = mul(UNITY_MATRIX_VP, tmp_pos); float tempOffset = _ZOffsetOne * pos.w; if (tempPosY < rubLenght ) { float dy = (rubLenght - tempPosY); if( dy > pi * radius) { tempOffset = -tempOffset*2.0; } } pos.z = pos.z + tempOffset; pos.x += _Move; o.vertex = pos; o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.uv.x = 1 - o.uv.x;//对uv的x取反 return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); clip (col.a - 0.5); return col * _Color; } ENDCG } Pass { Name "TWO" Cull Back Lighting Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" sampler2D _MainTex_2; float4 _MainTex_2_ST; fixed4 _Color; float ratioY; float radius; float height; float anchorY; float rubOffset; float maxRubAngle; float _ZOffsetTwo; float _Move; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; float4 tmp_pos = v.vertex; float tempAngle = 1.0; tmp_pos.xyz = mul(unity_ObjectToWorld,float4(tmp_pos.xyz,0)).xyz; //tmp_pos.xyz = (modelMatrix * vec4(tmp_pos.xyz, 0.0)).xyz; float pi = 3.14159; float halfPeri = radius * pi * maxRubAngle; float rubLenght = height * (ratioY - anchorY); tmp_pos.y += height*rubOffset; float tempPosY = tmp_pos.y; if(tmp_pos.y < rubLenght) { float dy = (rubLenght - tmp_pos.y); if(rubLenght - halfPeri < tmp_pos.y) { float angle = dy/radius; tmp_pos.y = rubLenght - sin(angle)*radius; tmp_pos.z = radius * (1.0- cos(angle)); } else { float tempY = rubLenght - halfPeri - tmp_pos.y; float tempAngle = pi * (1.0-maxRubAngle); tmp_pos.y = rubLenght - radius*sin(tempAngle) + tempY * cos(tempAngle); tmp_pos.z = radius + radius*cos(tempAngle) + tempY * sin(tempAngle); } } tmp_pos.x += unity_ObjectToWorld[3][0]; tmp_pos.y += unity_ObjectToWorld[3][1]; tmp_pos.z += unity_ObjectToWorld[3][2]; float4 pos = mul(UNITY_MATRIX_VP, tmp_pos); float tempOffset = _ZOffsetTwo * pos.w; if (tempPosY < rubLenght ) { float dy = (rubLenght - tempPosY); if( dy > pi* radius) { tempOffset = -tempOffset * 2.0; } } pos.z = pos.z + tempOffset; pos.x += _Move; o.vertex = pos; o.uv = TRANSFORM_TEX(v.uv, _MainTex_2); o.uv.x = 1 - o.uv.x;//对uv的x取反 o.uv.y = 1 - o.uv.y;//对uv的y取反 return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex_2, i.uv); clip (col.a - 0.5); return col * _Color; } ENDCG } } }
注意:URP要渲染多通道的shader,需要确保有个pass打上UniversalForward的tag,其余pass有SRPDefaultUnlit的tag也行,没有也行
shader将模型坐标转换为世界坐标,所以普通的移动不会影响位置,需要调节shader的参数做偏移,调节参数把牌摆好,设置好角度和相机角度。