Unity Shader 一 激光特效Shader

学习Shader已经有几个月的时间了,Shader作为一门GPU编程语言来说确实比较的难学。主要原因经过我的思考还是本人自己的计算机图形学和美术基础不扎实。好无奈,作为一个之前单纯手写代码的程序员真的是感觉好蛋疼。

学习期间,我也向多名Shader大神请教学习经验,得到的回应大多是让我好好去学习计算机图形学。哈哈,于是乎,本人又跑去看了一个多月的计算机图形学。接着再次回来学习Shader,但是虽然比之前看的时候要好,但是在大部分的情况之下还是两眼一抹黑。

于是乎,我又想到了一位伟人的名言:实践是得到真理的唯一途径。哈哈,大家不要打我,我不是故意说废话的(其实是有意的。。。。。来打我啊)。那么怎么样才能在基础不是很扎实的情况下学习Shader呢?我想了好久,看完CSDN Shader博客大神吃西瓜的小女孩(不要打我,实在是该大神的名字太长了。。。。。)"妈妈说女孩子要自立自强"的博客之后,我似乎找到了一点灵感。我决定从Unity的内置Shader开始入手,详细的介绍一些我看到的效果不错而且比较实用的Shader。我也希望各位大神能对我写的东西提出批评和指导,让我们这些新手一起得到提高和进步,哈哈。

暂时因为工作的原因,我准备以每周一篇的速度来进行更新,具体的看日后的安排吧,我会加油的。。。。。

这次就来先来看我最近做一个项目练手的时候用到的一个shader:

效果见下图:

这是我之前做的一个激光特效Shader,用来练手。

shader的主要代码如下:

Shader "Particles/Additive" {
Properties {
	_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
	_MainTex ("Particle Texture", 2D) = "white" {}
	_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0
}

Category {
	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
	Blend SrcAlpha One
	ColorMask RGB
	Cull Off Lighting Off ZWrite Off

	SubShader {
		Pass {

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_particles
			#pragma multi_compile_fog

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			fixed4 _TintColor;

			struct appdata_t {
				float4 vertex : POSITION;
				fixed4 color : COLOR;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				fixed4 color : COLOR;
				float2 texcoord : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				#ifdef SOFTPARTICLES_ON
				float4 projPos : TEXCOORD2;
				#endif
			};

			float4 _MainTex_ST;

			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				#ifdef SOFTPARTICLES_ON
				o.projPos = ComputeScreenPos (o.vertex);
				COMPUTE_EYEDEPTH(o.projPos.z);
				#endif
				o.color = v.color;
				o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}

			sampler2D_float _CameraDepthTexture;
			float _InvFade;

			fixed4 frag (v2f i) : SV_Target
			{
				#ifdef SOFTPARTICLES_ON
				float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
				float partZ = i.projPos.z;
				float fade = saturate (_InvFade * (sceneZ-partZ));
				i.color.a *= fade;
				#endif

				fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
				UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); // fog towards black due to our blend mode
				return col;
			}
			ENDCG
		}
	}
}
}

这个Shader各位大神一眼就能够看出来了,我就不装这个逼说是我写的,不然估计回头得被各种啪啪啪啪啪啪啪无情打脸,哈哈哈哈哈哈。这是Unity自带的一个Shader,主要的功能有颜色混合,开启雾效,外加透明效果。不得不说Unity自带的shader确实厉害,这么多的功能能够这么简洁的就写出来确实不简单。

我就不说闲话不多说了,不然估计要被人给打死,哈哈哈哈哈。因为我也是想要写一篇巩固基础的文章,所以大家就不要嫌弃我啰嗦,那我就多讲一些了。

_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)这句话是在Shader面板中设置来进行混合的颜色,这里面设置了一个RGBA的默认值。

_MainTex ("Particle Texture", 2D) = "white" {} 这是在Shader面板中设置进行颜色混合的图片。

_InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0 这是设定一个范围的值,用来最后让别人调节最终效果的时候用,因为有些效果还是让一些专业的人来进行调节会比较的好。

Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }  "Queue"="Transparent"这句话的意思是开启透明道,"IgnoreProjector"="True"

的意思是开启阴影的效果,"RenderType"="Transparent"是开启渲染的类别。

Blend SrcAlpha One     只得是用这种类型的alphaa混合模式,其实这就是一个拿你得到的颜色值和alpha进行混合的公式而已,这只是简写而已。

ColorMask RGB         颜色通道遮罩,意思是最后输出的颜色通道是RGB通道

Cull Off Lighting Off ZWrite Off     关闭剔除的效果  关闭灯光的效果   关闭深度缓存(这种操作其实会导致一些问题)

struct appdata_t {

float4 vertex : POSITION;

fixed4 color : COLOR;

float2 texcoord : TEXCOORD0;

};

struct v2f {

float4 vertex : SV_POSITION;

fixed4 color : COLOR;

float2 texcoord : TEXCOORD0;

UNITY_FOG_COORDS(1)

#ifdef SOFTPARTICLES_ON

float4 projPos : TEXCOORD2;

#endif

};

上面这些其实都是定义的一些属性值,我就不一一列举了,哈哈。

float4 _MainTex_ST;       别看这就只有这一小句,其实里面的名堂真的不少。

indeed for any texture property, Unity provides value for float4 with "_ST" suffix. The x,y contains texture scale, and z,w contains translation (offset).

  _ST变量有4个值,xy是texture scale,zw是offset。

  

  在Material中可以设置的Tiling就是xy,Offset就是zw。

通过这个可以看出,虽然Unity自带的Shader代码十分的简洁,比起那些动不动就上千行的代码看起来简单多了,但是里面其实偷偷帮我们封装了很多的东西,这也让我们学习unity 自带shader的难度加大了不少。所以,这也是我想写这篇博客的原因所在。

v2f vert (appdata_t v)   这句话的意思是定点着色器,返回的值是前面我们定义的v2f属性,说道这里我忍不住要吐槽一下。前段时间使用unity自带的surface shader,我脑残定义了一个属性,结果没有在定点着色器,也就是vert里面给他赋初值,因此shader一直在报错,我的天。还好最后,我们英明神武的大神过来帮我解决了这个问题。。。。。

o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);  这是一个MVP变换矩阵,意思是将定点坐标从世界坐标系,变换成为屏幕坐标系,这里面的包含了至少三个变换矩阵,代码写起来会非常的长,感谢万能的Unity帮我们封装好了。(虽然我并不确定是Unity封装的还是CG这门语言封装的,但就让我在这里稍微装个逼吧。。。。。。想起我一个朋友说的名言:人不装逼跟咸鱼有什么区别     哈哈哈哈哈哈哈哈)。

#ifdef SOFTPARTICLES_ON

o.projPos = ComputeScreenPos (o.vertex);

COMPUTE_EYEDEPTH(o.projPos.z);

#endif

o.color = v.color;

o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);

UNITY_TRANSFER_FOG(o,o.vertex);

这句代码的意思是根据z的深度场景来控制特效的缩放和旋转,这是Unity 5.0里面包含的新的shader,里面封装了很多的东西,我们看到的只是自己传入方法中的参数而已。详细可以看我们超级厉害的雨松MOMO的博客,这里面有讲解http://www.xuanyusong.com/?p=3486(无情甩锅 哈哈哈哈哈哈哈)

float _InvFade;     直接看代码_InvFade,这个就是一个参数控制透明度(配合距离屏幕远近粒子的深度和场景深度的差来呈现效果)  用一个美术大神专业一点的讲解来说就是类似unreal 的alpha bias材质节点,用于粒子片面和实体交接处柔化,避免出现面片穿插的交接线。

#ifdef SOFTPARTICLES_ON

float sceneZ = LinearEyeDepth (SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));

float partZ = i.projPos.z;

float fade = saturate (_InvFade * (sceneZ-partZ));

i.color.a *= fade;

#endif

这句话就是展现特效呈现跟场景深度和距离屏幕远近差效果影响的一个方法。从这里大家也都看出来了吧,这个Shader其实就是一个专门用来做特效的Shader,类似于激光或者是2D游戏里面的刀光特效都是可以使用这个方法来制作,告诉大家一个小秘密了,很多Unity上面的特效插件都是使用这个Shader制作的,哈哈哈哈哈哈哈哈哈。

fixed4 col = 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);  这句话的意思就是将之前那一系列处理得到的i.color来进行简单的颜色混合的处理,至于那个2.0f,其实也就是写这个shader的大神自己在调节颜色的时候定义的。计算机图形学其实很大的程度上来说就是一门欺骗人眼睛的学科,哈哈哈哈哈哈哈。

UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0));  这句话的意思是设置雾的朝向和颜色,其实这也是Unity自带的一个封装好的雾的方法。

写到这里本篇博客也就接近尾声了,欢迎各位大神对我提出批评,让我能有提升的空间。如果大家有兴趣的话也可以来这个群里面找我:  344682050  ,我们可以一起在这里互相交流,共同提高shader编程能力。哈哈哈哈哈哈哈哈



时间: 2024-10-05 06:43:55

Unity Shader 一 激光特效Shader的相关文章

【Unity Shaders】初探Surface Shader背后的机制

转载请注明出处:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的机制一直是刚開始学习的人为之困惑的地方. Unity Surface Shader在Unity 3.0的时候被开放给公众使用.其宣传手段也是号称让所有人都能够轻松地写shader.但因为资料缺乏,非常多人知其然不知其所以然,无法理解Unity Surface Shader在背后为我们做了哪些事情.

解读Unity中的CG编写Shader系列一

CG=C for Graphics  用于计算机图形编程的C语言超集 前提知识点: 1.CG代码必须用 CGPROGRAM ... ENDCG括起来 2.顶点着色器与片段着色器的主函数名称可随意,但需要再#pragma vert 与#pragma fragment中声明并且与主函数名完全匹配,shader才会找到入口 3.float4是一种压缩数组,float4 vert与float vert[4]严格意义上讲不同,虽然都是存放4个float,但float4作为向量类型做点乘.内积等处理更快速

解读Unity中的CG编写Shader系列四——unity中的圆角矩形shader

上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做成圆角矩形 例3:圆角矩形Shader 好吧我承认在做这个例子的时候走了不少弯路,由于本人对矩阵的知识掌握已经悉数还给老师,所以一开始用了一些笨办法计算圆角矩形区域. 我们知道TEXTCOORD0是一个以对象为坐标系的坐标,并且范围在该坐标的第一象限,取值为(0,0)到(1,1) 那么我们把每一张图片都看做一张1X1大小的矩形 我们要在1X1大小的矩形中擦除4个角,应该是这样: 以左上角

【Unity Shaders】Vertex & Fragment Shader入门

写在前面 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效.这是因为我们是依赖法线和视角的点乘结果来进行描边判断的,因此,对于那些平整的表面,它们的法线通常是一个常量或者会发生突变(例如立方体的每个面),这样就会导致最后的效果并非如我们所愿.如下图所示: 因此,我们有一个更好的方法来实现描边效果,也就是通过两个pass进行渲染--首先渲染对象的背面,用黑色略微向外扩展一点,就是我们的描边效果:然后正常渲染正

unity给子物体添加Shader

分享两个自制Shader:http://pan.baidu.com/s/1nuRcF2L Shader存放路径:\Assets\Resources\Shader\ 定义Shader类型: public enum EnumFbxType { Default, TouMing, GaoLiang, } 加载指定Shader: private static Shader myTouMing = Shader.Find("My/TouMing"); private static Shader

【浅墨Unity3D Shader编程】之十三 单色透明Shader & 标准镜面高光Shader

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/50878538 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 本文工程使用的Unity3D版本: 5.2.1  本次更新放出的Shader为透明系列的3个Shader和标准的镜面高光Shader的两个Shader.由易到难,由入门级到应用级,难度梯度合理. 依然是先放出游戏场景的exe

UnityShader之Shader分类篇【Shader资料2】

关于ShaderLab,从我个人的理解上来看应该是分为三种类型. 1.Fixed function shader 固定渲染管线Shader,基于用于高级Shader在老显卡无法显示时的Fallback,使用的是ShaderLab语言,属于真正的ShaderLab语言,和我们平时看到的shader的区别后面细说. 2.Vertex and Fragment Shader 可编程渲染管线,这种Shader包含Vertex Shader和Fragment Shader,也就是顶点着色器和片段着色器.顶

UnityShader之Shader格式篇【Shader资料1】

关于Shader,在Unity里面我们一般叫做ShaderLab,只要你的职业是与渲染搭边,Unity就与ShaderLab有着直接的关联,你都应该试着去学会它,其实我们在新手未有入门的时候,我们总是认为这是个很遥远的东西,只要我们有一次理解了,我们就会发现ShaderLab其实并不难. 每一个Shader,我们从最简单的方式去着手理解,你只需要把它想象成一个无限循环执行的函数即可.可能这样也有部分同学还是很难理解.那我写个代码我们试着来理解它. public void ShaderLab(ob

shader开发_4.Surface shader初探

可编程渲染管线 unity shader==>>Surface shader Surface shader是 unity 对于顶点和片段着色器的一种封装 下面这是一个unity 默认生成的Surface shader Shader "Custom/myshader01" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) =