专栏首页游戏开发之旅Shader实例(流光实现)

Shader实例(流光实现)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/CJB_King/article/details/78869642

Shader实例(流光实现)

流光效果

首先来看一下流光效果。流光效果是一个非常常见的效果,不仅仅是游戏,一些广告之类的也都会有这种效果。流光的原理还是比较简单的:首先就是需要一张流光图,这张流光图的大部分都是黑色,然后有一条亮线,然后我们在采样的时候,最终输出叠加上这张图的采样值,并根据时间调整采样的UV就可以有流光的效果啦。下面是一个比较简单的流光效果实现:

下面看属性参数:

接下来是SubShader中的一些参数定义

顶点函数处理

光照处理

以上是对于2D图像常用的流光实现方式,如果是3D物体用这种方式的话,可能会出现问题,所以对于3D物体,采用按照物体的世界坐标按时间偏移查询纹理贴图就行了

具体参数按需求改下就好了

按照方向消失或重现效果

我们再来看一个用模型空间坐标作为采样的uv的栗子,也是一种比较好玩的效果。比如我们需要一个模型身体按照一定的方向逐渐消失,直至全部消失掉的一个效果。下面说一下思路,与世界空间采样的流光效果一样,我们在vertex阶段记录一下vertex坐标,传递给fragment阶段,在fragment阶段用这个值和一个设定好的阈值进行比较,不满足条件的像素点直接discard,逐渐调整阈值,就可以得到让模型按照某个方向消失的效果了。代码如下:

 //按照方向消失的效果 
 //by:CJB_King 
 //2017.12.23 
 Shader "SelfShader/DissolveEffectX" 
 {  
     Properties  
     {  
         _MainTex("MainTex(RGB)", 2D) = "white" {}  
         _DissolveVector("DissolveVector", Vector) = (0,0,0,0)  
     }  
  
     CGINCLUDE  
     #include "Lighting.cginc" 
     uniform sampler2D _MainTex;  
     uniform float4 _MainTex_ST;  
     uniform float4 _DissolveVector;  
  
  struct v2f   
     {  
         float4 pos : SV_POSITION;  
         float3 worldNormal : NORMAL;  
         float2 uv : TEXCOORD0;  
         float3 worldLight : TEXCOORD1;  
         float4 objPos : TEXCOORD2;  
     };  
  
     v2f vert(appdata_base v)  
     {  
         v2f o;  
         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
         o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);  
  //顶点转化到世界空间 
         o.objPos = v.vertex;  
         o.worldNormal = UnityObjectToWorldNormal(v.normal);  
         o.worldLight = UnityObjectToWorldDir(_WorldSpaceLightPos0.xyz);  
  return o;  
     }  
  
     fixed4 frag(v2f i) : SV_Target  
     {  
         half3 normal = normalize(i.worldNormal);  
         half3 light = normalize(i.worldLight);  
  fixed diff = max(0, dot(normal, light));  
         fixed4 albedo = tex2D(_MainTex, i.uv);  
  //不满足条件的discard 
         clip(i.objPos.xyz - _DissolveVector.xyz);  
         fixed4 c;  
         c.rgb = diff * albedo;  
         c.a = 1;  
  return c;  
     }  
     ENDCG  
  
     SubShader  
     {  
  
         Pass  
         {  
             Tags{ "RenderType" = "Opaque" }  
  
             CGPROGRAM  
             #pragma vertex vert 
             #pragma fragment frag 
             ENDCG     
         }  
     }  
     FallBack "Diffuse" 
 }  

还有一个小问题,其实上图中的例子里面,模型从上到下,理想情况应该是调整Y轴,不过例子里面调整的确实X轴,原因应该与Unity导入之后会绕着X轴旋转90度有关,也就是原本在max里面的Y轴变成Unity里面的X轴。

下面,我们再看一下增加了边缘高亮的消失效果,为了让模消失的型边缘高亮,我们通过将用于clip的factor值与另一个高亮阈值值进行比较,如果factor小于高亮阈值,则返回一个高亮的颜色值,否则正常渲染。这样模型就总共有三种显示状态:clip状态,高亮状态,正常状态。代码如下:

 //消失效果 
 //by:CJB_King
 //2017.12.23 
  
 Shader "SelfShader/DissolveEffectX" 
 {  
     Properties{  
         _Diffuse("Diffuse", Color) = (1,1,1,1)  
         _DissolveColor("Dissolve Color", Color) = (0,0,0,0)  
         _MainTex("Base 2D", 2D) = "white"{}  
         _ColorFactor("ColorFactor", Range(0,1)) = 0.7  
         _DissolveThreshold("DissolveThreshold", Float) = 0    
     }  
  
     CGINCLUDE  
     #include "Lighting.cginc" 
     uniform fixed4 _Diffuse;  
     uniform fixed4 _DissolveColor;  
     uniform sampler2D _MainTex;  
     uniform float4 _MainTex_ST;  
     uniform float _ColorFactor;  
     uniform float _DissolveThreshold;    
  
  struct v2f  
     {  
         float4 pos : SV_POSITION;  
         float3 worldNormal : TEXCOORD0;  
         float2 uv : TEXCOORD1;  
         float4 objPos : TEXCOORD2;   
     };  
  
     v2f vert(appdata_base v)  
     {  
         v2f o;  
         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
         o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);  
         o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);  
         o.objPos = v.vertex;    
  return o;  
     }  
  
     fixed4 frag(v2f i) : SV_Target  
     {  
  float factor = i.objPos.x - _DissolveThreshold;  
         clip(factor);   
  //Diffuse + Ambient光照计算 
         fixed3 worldNormal = normalize(i.worldNormal);  
         fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);  
         fixed3 lambert = saturate(dot(worldNormal, worldLightDir));  
         fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;  
         fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;  
  //等价于下面注释代码的操作 
  fixed lerpFactor = saturate(sign(_ColorFactor - factor));  
  return lerpFactor * _DissolveColor + (1 - lerpFactor) * fixed4(color, 1);  
  /* 
         if (factor < _ColorFactor) 
         { 
             return _DissolveColor; 
         } 
         return fixed4(color, 1);*/ 
     }  
     ENDCG  
  
     SubShader  
     {  
         Tags{ "RenderType" = "Opaque" }  
         Pass  
         {  
  //不让模型穿帮,关掉了背面裁剪 
             Cull Off  
             CGPROGRAM  
             #pragma vertex vert 
             #pragma fragment frag    
             ENDCG  
         }  
     }  
     FallBack "Diffuse" 
 }  

溶解效果进阶版

之前的文章里,我们研究过溶解效果,不过这个效果是基于全身的,我们来尝试一下,把上面按照方向消失的效果与溶解效果结合起来,做成一个按照某个方向逐渐溶解的效果。要得到随机的溶解效果,我们需要采样一张噪声图,然后在原本会直接clip掉的部分根据采样的噪声图进行clip,就能得到按照方向的溶解效果啦。

 //溶解效果 
 //by:CJB_King
 //2017.12.23
  
 Shader "SelfShader/DissolveEffectX" 
 {  
     Properties{  
         _Diffuse("Diffuse", Color) = (1,1,1,1)  
         _DissolveColor("Dissolve Color", Color) = (1,1,1,1)  
         _MainTex("Base 2D", 2D) = "white"{}  
         _DissolveMap("DissolveMap", 2D) = "white"{}  
         _DissolveThreshold("DissolveThreshold", Range(0,1)) = 0  
         _DissolveSpeedFactor("DissolveSpeed", Range(0,5)) = 2  
         _DissolveControl("ColorFactorB", Float) = 0  
     }  
  
     CGINCLUDE  
     #include "Lighting.cginc" 
     uniform fixed4 _Diffuse;  
     uniform fixed4 _DissolveColor;  
     uniform sampler2D _MainTex;  
     uniform float4 _MainTex_ST;  
     uniform sampler2D _DissolveMap;  
     uniform float _DissolveThreshold;  
     uniform float _DissolveSpeedFactor;  
     uniform float _DissolveControl;   
  
  struct v2f  
     {  
         float4 pos : SV_POSITION;  
         float3 worldNormal : TEXCOORD0;  
         float2 uv : TEXCOORD1;  
         float4 objPos : TEXCOORD2;   
     };  
  
     v2f vert(appdata_base v)  
     {  
         v2f o;  
         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
         o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);  
         o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);  
         o.objPos = v.vertex;    
  return o;  
     }  
  
     fixed4 frag(v2f i) : SV_Target  
     {  
         fixed4 dissolve = tex2D(_DissolveMap, i.uv);  
  //Diffuse + Ambient光照计算 
         fixed3 worldNormal = normalize(i.worldNormal);  
         fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);  
         fixed3 lambert = saturate(dot(worldNormal, worldLightDir));  
         fixed3 albedo = lambert * _Diffuse.xyz * _LightColor0.xyz + UNITY_LIGHTMODEL_AMBIENT.xyz;  
         fixed3 color = tex2D(_MainTex, i.uv).rgb * albedo;  
  float factor = i.objPos.x - _DissolveControl;  
  if(factor < 0)  
         {  
             clip(_DissolveThreshold - dissolve.r * abs(factor) * _DissolveSpeedFactor);  
         }  
  return fixed4(color, 1);  
     }  
     ENDCG  
  
     SubShader  
     {  
         Tags{ "RenderType" = "Opaque" }  
         Pass  
         {  
             Cull Off  
             CGPROGRAM  
             #pragma vertex vert 
             #pragma fragment frag    
             ENDCG  
         }  
     }  
     FallBack "Diffuse" 
 }  
Shader "SelfShader/Dissolve"
{
	Properties
	{
		_MainColor("MainColor",COLOR)=(1,1,1,1)
		_MainTex ("Texture", 2D) = "white" {}
		_Noise("Noise",2D)="white"{}
		_Dissolve("Dissolve",Vector)=(0.2,0.5,0.8)
		_DissolveThread("DissolveThread",float)=0.2
		_DissolveColor("DissolveColor",COLOR)=(1,1,1,1)
		_DissolveColFactor("_DissolveColFactor",float)=2
		_FlyFactor("FlyFactor",float)=3
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			struct a2v
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				fixed3 normal:NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 pos : SV_POSITION;
				fixed3 worldNormal:TEXCOORD1;
				fixed3 worldPos:TEXCOORD2;
				fixed3 objPos:TEXCOORD3;
			};
			sampler2D _Noise;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _MainColor;
			fixed4 _Dissolve;
			float _DissolveThread;
			fixed4 _DissolveColor;
			float _DissolveColFactor;
			float _FlyFactor;
			v2f vert (a2v v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.worldPos=mul((float3x3)unity_ObjectToWorld,v.vertex);
				o.worldNormal=UnityObjectToWorldNormal(v.normal);
				o.objPos=v.vertex;
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.pos.xyz+=v.normal*saturate(_DissolveThread-_FlyFactor)*_FlyFactor;
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed3 worldNor=normalize(i.worldNormal);
				fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
				fixed4 albedo = tex2D(_MainTex, i.uv)*_MainColor;
				fixed4 noiseColor=tex2D(_Noise,i.uv);
				float factor=noiseColor.r-_DissolveThread;
				clip(factor);
				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo.rgb;
				fixed3 diffuse=_LightColor0.rgb*albedo.rgb*(0.5*dot(lightDir,worldNor)+0.5);
				float lerpFactor=saturate(sign(_DissolveColFactor-factor));
				return lerp(fixed4(ambient+diffuse,1),_DissolveColor,lerpFactor);
			}
			ENDCG
		}
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Shader屏幕后處理效果

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    bering
  • shader实例(五)GrabPass捕捉屏幕纹理

    注: 2中的确是将屏幕的纹理赋值到样本对象GrabTexture上,所以前面的模型显示整个屏幕的纹理是正常现象。 3中是计算该模型顶点在屏幕坐标的纹理...

    bering
  • Shader经验分享

    流水线 1.应用阶段:(CPU)输出渲染图元,粗粒度剔除等 比如完全不在相机范围内的需要剔除,文件系统的粒子系统实现就用到粗粒度剔除。 2.几何阶段:(GPU...

    bering
  • 7小时上线1个秒杀系统!!!!

    自2020年1月,新型冠状病毒肺炎被证实人传人后,无论是普通民众还是政府部门,都想着怎么去控制病情。而口罩成为防疫病情的第一需求,口罩很多时候一罩难求,是全国人...

    孙玄@奈学教育
  • 08-元组基础

    凯茜的老爸
  • 「自然语言处理(NLP)论文推送」清华大学XQA数据集(含源码)806

    本篇主要给大家介绍两篇文章:一篇是清华大学发表的XQA,该篇文章主要是针对开放式问答构建了一个跨语言的开放式问答数据集,该数据集(训练集、测试集)主要包括九种语...

    ShuYini
  • 计算机操作系统

    计算机系统由硬件系统和软件系统两大部分组成。操作系统(英语:Operating System,缩写:OS)是管理计算机硬件与软件资源的系统软件,同时也是计算机系...

    搬砖俱乐部
  • 鹅厂 TDSQL XA 事务隔离级别的奥秘

    TDSQL XA 全局事务(global transaction)是指用户客户端连接到 TDSQL XA 分布式数据库系统后发起和执行的事务,也就是 TDSQL...

    腾讯技术工程官方号
  • 机器学习加密货币IOTA在机构支持下跃起

    在德国工业巨头博世(Bosch)的风险投资部门宣布购买大量IOTA代币后,IOTA币价在周三大幅上涨。 IOTA的价格阶段 IOTA(MIOTA / USD)上...

    企鹅号小编
  • 什么是IOTA(MIOTA)?

    你有没有听说过物联网?IOTA 的创始人已经采纳了这个想法,并将区块链技术与物联网的想法相结合。IOTA技术上不是在区块链上运行,而是利用它的 Tangle 技...

    Starrier

扫码关注云+社区

领取腾讯云代金券