Unity3d Ugui图片上制作点光 、棱形光效果shader,并具有裁切
Unity3d Ugui图片上制作点光 、棱形光效果
实现的效果可以参考如下图所示
通过shader来实现上述的效果,为了大家的适应性,推荐在unity官方的默认ui shader上更改,我用的是2019.2.17版本。以下是链接
unity官方下载
查找对应版本选择built in shaders 下载
可以在路径builtin_shaders-2019.2.21f1\DefaultResourcesExtra\UI 下找到UI-Default.shader
在以此的基础上修改代码
类似点光的实现
点光本质来说形状就是一个圆,首先在Properties中需要定义圆心,和其半径
_CircleParameter("Circle Parameter",Vector)=(0.5,0.5,0.2,1) //xy 为圆心所在位置, z为半径 ,w为光线强度接下来我们需要得到uv坐标下,每个点距离我们定义的圆的距离
float2 centrePoint=_CircleParameter.xy; //圆心 float dis=distance(IN.uv,centrePoint); //uv与圆心的距离很明显,我们只需要 距离dis在圆半径_CircleParameter.z范围内的点,可以通过如下代码获得
float factor= step(dis,_CircleParameter.z);factor 的值为 圆半径小于两点距离(_CircleParameter.z<dis)则为0,否则为1。step函数可以搜索CG 标准函数库查看相关概念。
接下里我们可以通过得到的factor为点光颜色去做裁剪,去掉圆以外的光颜色。很明显在圆以外的factor值都为0,只要将光颜色(_PointColor)的alpha值乘以factor。
_PointColor.a*=factor; //裁剪掉超出圆范围的光有些图片上有透明元素,比如我在上面中使用的图片,显然这些透明的地方不应该显示光颜色,当然如果你想的话也可以。通过采样获取(color)的颜色 判断当前像素上是否透明,不需要显示。
_PointColor.a*=step(0.01,color.a); //裁剪掉透明处的光光是有衰减的,我们可以通过如下一个简单的计算得到。
_PointColor.a*=1.0-(dis/_CircleParameter.z); //光的衰减点距离圆心越近dis/_CircleParameter.z越小,但是很明显衰减是从圆心往外的,可以用去1去减使其相反。
最后只需要混合光的颜色和采样得到的颜色
color.rgb= color.rgb+_PointColor.rgb*_PointColor.a*_CircleParameter.w; //混合颜色 ,_CircleParameter.w为颜色强度有时候我们会希望图片做一些裁剪,比如让它只显示圆的形状。那么我们只需要以上代码的基础上,通过采样颜色的alpha乘以factor就可以去掉范围以外的颜色。代码十分简单
color.a*=factor;棱形光
基本思想与上面的圆类似,简单的来说,就是我们需要判断哪些点在这个棱形范围内。
上图中使用的是四边相等的棱形,并且顶点距离坐标中心为1,很明显此棱形在四边上的点有如下关系式 x+y=1(x和y分布都是x上距离坐标中心的距离,和y上距离坐标中心的距离)。那么在此棱形中的点显然 小于 x+y。只需要将uv坐标转换为上图以棱形为坐标系,可以很容易计算点是否在棱形内。代码如下
最后把所有完整shader附上
Shader "Wjh/2DPoint" {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[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0_PointColor("Point Color",Color)=(1,1,0,1) //点光的颜色_CircleParameter("Circle Parameter",Vector)=(0.5,0.5,0.2,1) //xy 为圆心所在位置, z为半径 ,w为光线强度[Toggle(USE_CLIP_SHAPE)] _UseClipShape("Use Clip Shape",Float)=0.0 //是否开启裁剪-圆[Toggle(USE_DIAMOND)] _UseDiamond("Use Clip Shape",Float)=0.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 OffLighting OffZWrite OffZTest [unity_GUIZTestMode] Blend SrcAlpha OneMinusSrcAlphaColorMask [_ColorMask]Pass{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//自定义裁剪宏#pragma shader_feature_local USE_CLIP_SHAPE //自定义棱形宏#pragma shader_feature_local USE_DIAMOND 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 uv : TEXCOORD0;float4 objPosition : TEXCOORD1;UNITY_VERTEX_OUTPUT_STEREO };sampler2D _MainTex;fixed4 _Color;fixed4 _TextureSampleAdd;float4 _ClipRect;float4 _MainTex_ST;fixed4 _PointColor;fixed4 _CircleParameter;float _UseClipCircle;float _UseClipDiamond;v2f vert(appdata_t v){v2f OUT;//Gpu Instancing 相关UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);OUT.objPosition = v.vertex;OUT.vertex = UnityObjectToClipPos(OUT.objPosition);OUT.uv = TRANSFORM_TEX(v.texcoord, _MainTex);OUT.color = v.color * _Color;return OUT;}float ClipDiamond(float2 uv)//裁剪棱形{float x=abs( uv.x-_CircleParameter.x);float y=abs( uv.y-_CircleParameter.y);return step(x+y,_CircleParameter.z);}fixed4 frag(v2f IN) : SV_Target{fixed4 color = (tex2D(_MainTex, IN.uv) + _TextureSampleAdd) * IN.color;//图片裁剪#ifdef UNITY_UI_CLIP_RECTcolor.a *= UnityGet2DClipping(IN.objPosition.xy, _ClipRect);#endif#ifdef UNITY_UI_ALPHACLIPclip (color.a - 0.001);#endiffloat2 centrePoint=_CircleParameter.xy; //圆心float dis=distance(IN.uv,centrePoint); //uv与圆心的距离//是否开启裁剪棱形,否则圆#ifdef USE_DIAMOND float factor=ClipDiamond(IN.uv);#elsefloat factor= step(dis,_CircleParameter.z); //超出圆范围的因子为0,其余为1#endif_PointColor.a*=step(0.01,color.a); //裁剪掉透明处的光_PointColor.a*=factor; //裁剪掉超出圆范围的光//是否开启裁剪形状#ifdef USE_CLIP_SHAPEcolor.a*=factor; #endif_PointColor.a*=1.0-(dis/_CircleParameter.z); //光的衰减color.rgb= color.rgb+_PointColor.rgb*_PointColor.a*_CircleParameter.w; //混合颜色 ,_CircleParameter.w为颜色强度//color.rgb= (color.rgb*color.a+_PointColor.rgb*_PointColor.a*_CircleParameter.w)*step(0.001,_PointColor.a); //混合颜色 ,_CircleParameter.w为颜色强度return color;}ENDCG}} }谢谢。
总结
以上是生活随笔为你收集整理的Unity3d Ugui图片上制作点光 、棱形光效果shader,并具有裁切的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: hive优化笔记
- 下一篇: 计算机与软件学院辅导员陈伯亨,十年桃李满