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的参数做偏移,调节参数把牌摆好,设置好角度和相机角度。