UnityShader3实现彩光效果
程序员文章站
2022-06-30 11:13:04
本文实例为大家分享了unityshader3实现彩光效果展示的具体代码,供大家参考,具体内容如下
参考链接: 【opengl】shader实例分析(八)- 彩色光圈
效...
本文实例为大家分享了unityshader3实现彩光效果展示的具体代码,供大家参考,具体内容如下
参考链接: 【opengl】shader实例分析(八)- 彩色光圈
效果图:
这里我把它分三部分实现:1.彩色 2.光圈 3.动画
1.先实现彩色效果。分析一下那张彩色图,它是以中心为原点的,然后颜色分为三部分,如下图。当角度为90度时,蓝色最多;当角度为-150度时,红色最多;当角度为-30度时,绿色最多。然后其他地方就是三色混合。
shader "custom/colors" { properties { _anglerange ("anglerange", range(60, 120)) = 60 } subshader { pass { cgprogram #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" #define pi 3.142 struct appdata { float4 vertex : position; }; struct v2f { float4 vertex : sv_position; float4 scrpos : texcoord0; }; half _anglerange; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.scrpos = computescreenpos(o.vertex); return o; } fixed4 frag (v2f i) : sv_target { //范围在(0, 1) float2 wcoord = i.scrpos.xy / i.scrpos.w; //映射到(-1, 1),即屏幕中心为(0, 0) wcoord = wcoord * 2 - 1; //atan2(y, x):反正切,y/x的反正切范围在[-π, π]内 float radian = atan2(wcoord.y, wcoord.x); //1度(°)=0.017弧度(rad) //1弧度(rad)=57.29578度(°) float angle = radian * 57.3; //映射到(0, 360) if(angle < 0) angle = 360 + angle; fixed b = 1 - saturate(abs(angle - 90) / _anglerange); fixed g; if(angle > 180) g = 1 - saturate(abs(angle - 330) / _anglerange); else g = 1 - saturate((angle + 30) / _anglerange); fixed r = 1 - saturate(abs(angle - 210) / _anglerange); return fixed4(r, g, b, 1); } endcg } } }
2.先说一下1 / (xxx)这个式子的强大,它实现的效果,往往会带有光晕效果。其中第六个就是我们想要实现的光圈效果。
shader "custom/test" { properties { _value ("value", range(1, 50)) = 1 } subshader { pass { cgprogram #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" struct appdata { float4 vertex : position; float2 uv : texcoord0; }; struct v2f { float4 vertex : sv_position; float2 uv : texcoord0; }; half _value; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : sv_target { //映射到(-1, 1),使其中心点为原点 float2 uv = i.uv * 2 - float2(1, 1); float v; //v = 1 / abs(_value * uv.y);//1 //v = 1 / abs(_value * (uv.y + uv.x));//2 //v = 1 / abs(_value * (uv.y + 2 * uv.x));//3 //v = 1 / abs(_value * (abs(uv.y) + abs(uv.x)));//4 //v = 1 / abs(_value * length(uv));//5 //v = 1 / abs(_value * abs(length(uv) - 0.5));//6 v = 1 / abs(_value * abs(uv.x / uv.y));//7 x越小y越大,则越亮 return fixed4(v, v, v, 1); } endcg } } }
3.动画。这里我做的效果是基于角度的光线间隔效果,首先当然就是计算角度了,间隔的实现就是fmod和step的使用。
shader "custom/test" { properties { _width ("width", range(30, 90)) = 45 } subshader { pass { cgprogram #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" struct appdata { float4 vertex : position; float2 uv : texcoord0; }; struct v2f { float4 vertex : sv_position; float2 uv : texcoord0; }; half _width; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : sv_target { //映射到(-1, 1),使其中心点为原点 float2 uv = i.uv * 2 - float2(1, 1); float a = atan2(uv.y, uv.x); a *= 57.3; if(a < 0) a += 360; float b = fmod(a + _time.y * 20, _width); b = step(0.5 * _width, b); return fixed4(b, b, b, 1); } endcg } } }
>
4.最后当然就是将它们揉在一起了。
shader "custom/colors" { properties { _anglerange ("anglerange", range(60, 120)) = 60 _width ("width", range(30, 90)) = 45 } subshader { pass { cgprogram #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" #define pi 3.142 struct appdata { float4 vertex : position; float2 uv : texcoord0; }; struct v2f { float4 vertex : sv_position; float4 scrpos : texcoord0; float2 uv : texcoord1; }; half _anglerange; half _width; v2f vert (appdata v) { v2f o; o.vertex = mul(unity_matrix_mvp, v.vertex); o.scrpos = computescreenpos(o.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : sv_target { //1.彩色 //范围在(0, 1) float2 wcoord = i.scrpos.xy / i.scrpos.w; //映射到(-1, 1),即屏幕中心为(0, 0) wcoord = wcoord * 2 - 1; //atan2(y, x):反正切,y/x的反正切范围在[-π, π]内 float radian = atan2(wcoord.y, wcoord.x); //1度(°)=0.017弧度(rad) //1弧度(rad)=57.29578度(°) float angle = radian * 57.3; //映射到(0, 360) if(angle < 0) angle = 360 + angle; fixed b = 1 - saturate(abs(angle - 90) / _anglerange); fixed g; if(angle > 180) g = 1 - saturate(abs(angle - 330) / _anglerange); else g = 1 - saturate((angle + 30) / _anglerange); fixed r = 1 - saturate(abs(angle - 210) / _anglerange); //2.光圈 //映射到(-1, 1),使其中心点为原点 float2 uv = i.uv * 2 - float2(1, 1); float v = 1 / abs(30 * abs(length(uv) - 0.3)); //3.转动 float a = atan2(uv.y, uv.x); a *= 57.3; if(a < 0) a += 360; float aa = fmod(a + _time.y * 20, _width); aa = step(0.5 * _width, aa); ////////////////////// ////////////////////// if(length(uv) < 0.3) return fixed4(0, 0, 0, 1); return fixed4(r, g, b, 1) * aa + fixed4(v, v, v, 1); } endcg } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Unity常用命令模式详解