欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

Unity3d Ugui图片上制作点光 、棱形光效果shader,并具有裁切

发布时间:2023/12/20 编程问答 39 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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坐标转换为上图以棱形为坐标系,可以很容易计算点是否在棱形内。代码如下

float ClipDiamond(float2 uv)//裁剪棱形 {float x=abs( uv.x-_CircleParameter.x);float y=abs( uv.y-_CircleParameter.y);return step(x+y,_CircleParameter.z); }

最后把所有完整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,并具有裁切的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。