Shader "chicai/Circle" { Properties { _Value("Value",float) = 0.5 _Controll("Vector",vector) = (0,0,0,0) } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex:POSITION; fixed2 uv:TEXCOORD0; }; struct v2f { float4 position:SV_POSITION; fixed2 uv:TEXCOORD0; }; float _Value; half4 _Controll; v2f vert(appdata IN) { v2f o = (v2f)0; //初始化 有些平台要求 o.position = UnityObjectToClipPos(IN.vertex); o.uv = IN.uv; return o; } float4 frag(v2f IN):SV_TARGET { //length(IN.uv.xy-0.5) 中心向四周变化 //step 中心为1 以外为0 变成纯色圆形 //return step(length(IN.uv.xy-0.5), _Value); //边缘平滑的中心圆计算 return smoothstep(_Controll.x ,_Controll.y, length(IN.uv.xy - 0.5)); } ENDCG } } }
abs(-1.2) //1.2 绝对值 frac(2.5) //0.5 取小数 floor(0.5) //0 向下取整 ceil(0.5) //1 向上取整 max(0.1,0.3) //0.3 取最大值,用来提亮暗部 min(0.1,0.3) //0.1 取最小值,用来降低亮度 pow(0.1,2) //0.01 幂次方 rcp(0.1) //10 倒数 exp(2) //e的2次方 exp2(2) //4 2的2次方 fmod(0.1,0.2) //0 取余 同0.1%0.2 saturate(x) //限制在0到1范围 clamp(x,min,max) //x限制在min到max范围 sqrt(0.01) //0.1 去平方根 rsqrt(0.01) //10 去平方根的倒数 lerp(a,b,t) //a到b的插值 t(0,1) sin(x) //正弦 cos(x) //余弦 distance(a,b) //a和b之间的距离 length(a) //向量a的长度 step(a,b) //a<=b 返回1,否则0 smoothstep(min,max,x) //平滑过渡 x小于mix为0 x大于max则为1,之间为平滑在0到1
//Properties [Toggle]_DissolveEnable("Dissolve Enable",int) = 0 [MaterialToggle(MASKENABLE)]_MaskEnable("Mask Enable",int) = 0 //Pass #pragma multi_compile _ _DISSOLVEENABLE_ON //对应_DissolveEnable 无论如何都会编译 //#pragma shader_feature _ _DISSOLVEENABLE_ON ////对应_DissolveEnable 根据使用情况编译 #pragma shader_feature _ MASKENABLE////对应MASKENABLE 根据使用情况编译 #if _DISSOLVEENABLE_ON #endif
Unity中相机的捕获宽高会随着目标视口的宽高比率保持一致,所以不会变形。
可以调整Game视图的比例,观察相机的视锥的改变。
Shader "Unlit/Matcap" { Properties { _MainTex ("Texture", 2D) = "white" {} _Matcap("Mapcap",2D) = "white"{} _MatcapPower("MatcapPower", Float) = 2 _MatcapAdd("MapcapAdd",2D) = "white"{} _MatcapAddPower("MatcapAddPower", Float) = 2 _RampTex("RampTex",2D) = "white"{} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal :NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 normal_world:TEXCOORD1; float3 pos_world:TEXCOORD2; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _Matcap; float _MatcapPower; sampler2D _MatcapAdd; float _MatcapAddPower; sampler2D _RampTex; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.normal_world = mul(float4(v.normal,0), unity_WorldToObject); o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag (v2f i) : SV_Target { //主贴图 float4 tex_color = tex2D(_MainTex,i.uv); //Matcap 计算采样的uv 使用 float3 normal_world = normalize(i.normal_world); float3 normal_view = mul(UNITY_MATRIX_V, float4(normal_world,0)); float2 map_cap_uv = (normal_view.xy + float2(1,1)) * 0.5; float4 mapcap_color = tex2D(_Matcap, map_cap_uv) * _MatcapPower; //叠加的 Matcap float4 matcap_add = tex2D(_MatcapAdd, map_cap_uv) * _MatcapAddPower; //用菲涅尔来采样渐变图 1-0 float3 view_world = normalize(_WorldSpaceCameraPos.xyz - i.pos_world); half NdotV = saturate(dot(normal_world,view_world)); half sample = 1 - NdotV; float4 ramp_color = tex2D(_RampTex, float2(sample,sample)); float4 final_color = mapcap_color * tex_color * ramp_color + matcap_add; return final_color; } ENDCG } } }
Matcap贴图
Shader "Unlit/Scan" { Properties { _MainTex ("Texture", 2D) = "white" {} _RimMin("RimMin", Range(-1,1)) = 0.0 _RimMax("RimMax",Range(0,2)) = 0.0 _InnerColor("Inner Color",Color) = (0.0,0.0,0.0,0.0) _RimColor("Rim Color",Color) = (0.0,0.0,0.0,0.0) _RimIntensity("Rim Intensity",Float) = 1.0 _FlowSpeed("Flow Speed",Float) = 1 _Alaph("Alaph", Float) = 0.75 _EmissPower("Emiss Power", Float) = 2 _FlowTex("Flow Texture",2D) = "white"{}//扫光贴图 } SubShader { Tags { "RenderType"="Transparent" } LOD 100 Pass { ZWrite On ColorMask 0 } Pass { ZWrite Off Blend SrcAlpha One CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 texcoord : TEXCOORD0; float3 normal:TEXCOORD1; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 normal_world :TEXCOORD1; float3 pos_world:TEXCOORD2; float3 pivot_world:TEXCOORD3; }; sampler2D _MainTex; float4 _MainTex_ST; float _RimMin; float _RimMax; float4 _InnerColor; float4 _RimColor; float _RimIntensity; float _FlowSpeed; sampler2D _FlowTex; float _Alaph; float _EmissPower; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.normal_world = mul(float4(v.normal,0.0), unity_WorldToObject);//世界法线 o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz; o.pivot_world = mul(unity_ObjectToWorld, float4(0,0,0,1));//模型中心点的世界坐标 o.uv = v.texcoord; return o; } fixed4 frag (v2f i) : SV_Target { //边缘光 half3 normal_world = normalize(i.normal_world); half3 view_world = normalize(_WorldSpaceCameraPos.xyz - i.pos_world); half NdotV = saturate(dot(normal_world, view_world)); half fresnel = 1 - NdotV; fresnel = smoothstep(_RimMin,_RimMax, fresnel); half emiss = tex2D(_MainTex, i.uv).r;//模型贴图的R通道作自发光 emiss = pow(emiss, _EmissPower); half final_fresnel = saturate(fresnel + emiss); half3 final_rim_color = lerp(_InnerColor, _RimColor * _RimIntensity, fresnel); half final_rim_alpha = final_fresnel; //扫光 用xy坐标来取值贴图 减去模型中心点不受自身位置影响 half2 uv_flow = (i.pos_world.xy - i.pivot_world.xy); uv_flow = uv_flow + _Time.y * _FlowSpeed; float4 flow_rgba = tex2D(_FlowTex, uv_flow); float3 final_col = final_rim_color + flow_rgba.xyz; float final_alpha = final_rim_alpha + _Alaph; return fixed4(final_col,final_alpha); } ENDCG } } }
可以用一张渐变图和一张噪声图,一个圆形的模型,通过透明测试制作效果。
Shader "Clip/Bo" { Properties { _MainTex ("Texture", 2D) = "" {} _MainColor("Main Color",Color) = (1,1,1,1) _NoiseMap("NoiseMap", 2D) = "" {} _Cutout("Cutout", Range(0.0,1.1)) = 0.0 _Speed("Speed", Vector) = (.34, .85, .92, 1) } SubShader { Tags { "RenderType"="Opaque" "DisableBatching"="True"} Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; half2 texcoord0 : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float4 uv : TEXCOORD0; }; sampler2D _MainTex; float4 _MainTex_ST; float _Cutout; float4 _Speed; sampler2D _NoiseMap; float4 _NoiseMap_ST; float4 _MainColor; //顶点Shader v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv.xy = TRANSFORM_TEX(v.texcoord0, _MainTex); o.uv.zw = TRANSFORM_TEX(v.texcoord0, _NoiseMap); return o; } //片元Shader half4 frag (v2f i) : SV_Target { half gradient = tex2D(_MainTex, i.uv.xy + _Time.y * 0.1f * _Speed.xy).r * (1.0 - i.uv.y); half noise = 1.0 - tex2D(_NoiseMap, i.uv.zw + _Time.y * 0.1f * _Speed.zw).r; clip(gradient - noise - _Cutout); return _MainColor; } ENDCG } } }
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) Shader "Custom/FlowLightShader" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) _StencilComp ("Stencil Comparison", Float) = 8 _Stencil ("Stencil ID", Float) = 0 _StencilOp ("Stencil Operation", Float) = 0 _StencilWriteMask ("Stencil Write Mask", Float) = 255 _StencilReadMask ("Stencil Read Mask", Float) = 255 _ColorMask ("Color Mask", Float) = 15 //ADD--------- lightTime("Light Time", Float) = 0.6 thick("Light Thick", Float) = 0.3 nextTime("Next Light Time", Float) = 2 angle("Light Angle", int) = 45 //ADD--------- [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Stencil { Ref [_Stencil] Comp [_StencilComp] Pass [_StencilOp] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] } Cull Off Lighting Off ZWrite Off ZTest [unity_GUIZTestMode] Blend SrcAlpha OneMinusSrcAlpha ColorMask [_ColorMask] Pass { Name "Default" CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc" #include "UnityUI.cginc" #pragma multi_compile_local _ UNITY_UI_CLIP_RECT #pragma multi_compile_local _ UNITY_UI_ALPHACLIP struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPosition : TEXCOORD1; float4 mask : TEXCOORD2; UNITY_VERTEX_OUTPUT_STEREO }; sampler2D _MainTex; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; float4 _MainTex_ST; float _UIMaskSoftnessX; float _UIMaskSoftnessY; //ADD--------- half lightTime; int angle; float thick; float nextTime; //ADD--------- v2f vert(appdata_t v) { v2f OUT; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); float4 vPosition = UnityObjectToClipPos(v.vertex); OUT.worldPosition = v.vertex; OUT.vertex = vPosition; float2 pixelSize = vPosition.w; pixelSize /= float2(1, 1) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); float2 maskUV = (v.vertex.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); OUT.texcoord = TRANSFORM_TEX(v.texcoord.xy, _MainTex); OUT.mask = float4(v.vertex.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_UIMaskSoftnessX, _UIMaskSoftnessY) + abs(pixelSize.xy))); OUT.color = v.color * _Color; return OUT; } fixed4 frag(v2f IN) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd); //ADD--------- fixed currentTimePassed = fmod(_Time.y, lightTime + nextTime); fixed x = currentTimePassed / lightTime;//0-1为扫光时间 >1为等待时间 fixed tanx = tan(0.0174*angle);// uv-y/uv-x 0.0174为3.14/180 x += (x-1)/tanx;//保证能从头扫到尾 fixed x1 = IN.texcoord.y /tanx + x;//用uv-y来计算倾斜的uv-x fixed x2 = x1 + thick;//范围 if(IN.texcoord.x > x1 && IN.texcoord.x < x2) { fixed dis = abs(IN.texcoord.x-(x1+x2)/2);//距离扫光当前x中心点的距离 dis = 1-dis*2/thick;//越中心越大 half ca = color.a; color += color*(1.4*dis);//颜色加强 color.a = ca; } //ADD--------- #ifdef UNITY_UI_CLIP_RECT half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); color.a *= m.x * m.y; #endif #ifdef UNITY_UI_ALPHACLIP clip (color.a - 0.001); #endif return color; } ENDCG } } }
在官网对应的unity版本下下载build in shaders,找到UI-Default.shader,添加标志了ADD---------的代码,创建新的材质,赋值给Image的材质就可以了。
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的参数做偏移,调节参数把牌摆好,设置好角度和相机角度。