Unity&Shader案例篇—膨胀效果
2017-01-16 17:47
405 查看
原文:http://www.manew.com/thread-99195-1-1.html
这个效果要使得摄像机的Clear Flags为Solid Color模式,如果为其他模式可能会看不到外部那一圈光环。
●第一个Pass块:这个Pass块顶点和片段程序都比较简单,代码如下:
只需将模型的顶点和预设的颜色输出就可以了。
●第二个Pass块:这个pass块相对复杂一点,顶点程序主要的计算内容就是顶点的法线方向和相机观察方向的向量,这两个的点积就是膨胀的强度Strength。通过指数函数缩放对Strength和透明度opacity进行计算就会得到膨胀的效果。计算的代码部分为:
而片段程序也是简单的输出最终的颜色就可以,完整的代码如下:
在第二个Pass块中使用到了ZWrite Off命令,也即关闭遮挡,模型所有的面和通道都会被渲染,如果使用了ZWrite On命令,你会发现好像并没有什么变化,还是可以正常运行得到前面的效果。这是因为,Cull命令,默认的是Cull Back,即提出背面,不渲染模型的背面。如果使用Cull Front命令,即不渲染模型的前面,渲染的是模型的背面,得到的效果图如图所示,当然最终的选择就看你想要实现什么样的效果吧。
完整的Shader代码:
2、控制脚本部分C#代码:
就是一个简单控制强度随着时间变换的代码。
三、总结
这个小小的案例我们学习到了怎么使用多个Pass块来渲染同一个物体,以及在多个Pass块中使用透明度混合。我个人认为是一个非常不错的学习案例,不只是因为
它的代码部分非常简洁明了,更重要的是这个案例在很多应用中也是非常有用的。祝好好学习,慢慢变牛。
每天进步一点点。
一、前言
首先,来看一下效果图,如图所示:这个效果要使得摄像机的Clear Flags为Solid Color模式,如果为其他模式可能会看不到外部那一圈光环。
二、实现原理
1、Shader部分:将需要使用两个Pass块,两个Pass块里输出的颜色不同,并最终使用透明度混合得到最后输出的像素颜色。●第一个Pass块:这个Pass块顶点和片段程序都比较简单,代码如下:
Pass{ Tags{ "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag float4 _Color; float4 vert(float4 vertexPos : POSITION) : SV_POSITION{ return mul(UNITY_MATRIX_MVP, vertexPos); } float4 frag(void) : COLOR{ return _Color; } ENDCG }
只需将模型的顶点和预设的颜色输出就可以了。
●第二个Pass块:这个pass块相对复杂一点,顶点程序主要的计算内容就是顶点的法线方向和相机观察方向的向量,这两个的点积就是膨胀的强度Strength。通过指数函数缩放对Strength和透明度opacity进行计算就会得到膨胀的效果。计算的代码部分为:
float3 normalDirectionT = normalize(normalDirection); float3 viewDirectionT = normalize(viewDirection); float strength = abs(dot(viewDirectionT, normalDirectionT)); float opacity = pow(strength, _Strength);
而片段程序也是简单的输出最终的颜色就可以,完整的代码如下:
Pass{
Tags{"LightMode" = "ForwardBase" "Queue" = "Transparent" "RenderType" = "Transparent"}
// Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pra
4000
gma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _GlowColor;
float _Strength;;
float _GlowRange;
struct vInput {
float4 vertex : POSITION;
float4 normal : NORMAL;
};
struct v2f {
float4 position : SV_POSITION;
float4 col:COLOR;
};
v2f vert(vInput i) {
v2f o;
float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
float3 normalDirection = normalize(mul(i.normal, modelMatrixInverse)).xyz;
float3 viewDirection = normalize(_WorldSpaceCameraPos - mul(modelMatrix, i.vertex).xyz);
float4 pos = i.vertex + (i.normal * _GlowRange);
o.position = mul(UNITY_MATRIX_MVP, pos);
float3 normalDirectionT = normalize(normalDirection); float3 viewDirectionT = normalize(viewDirection); float strength = abs(dot(viewDirectionT, normalDirectionT)); float opacity = pow(strength, _Strength);
float4 col = float4(_GlowColor.xyz, opacity);
o.col = col;
return o;
}
float4 frag(v2f i) : COLOR{
return i.col;
}
ENDCG
}
在第二个Pass块中使用到了ZWrite Off命令,也即关闭遮挡,模型所有的面和通道都会被渲染,如果使用了ZWrite On命令,你会发现好像并没有什么变化,还是可以正常运行得到前面的效果。这是因为,Cull命令,默认的是Cull Back,即提出背面,不渲染模型的背面。如果使用Cull Front命令,即不渲染模型的前面,渲染的是模型的背面,得到的效果图如图所示,当然最终的选择就看你想要实现什么样的效果吧。
完整的Shader代码:
Shader "CgInUnity/Glow"
{
Properties{
_Color("Object's Color", Color) = (0, 1, 0, 1)
_GlowColor("Glow's Color", Color) = (1, 0, 0, 0)
_Strength("Glow Strength", Range(5.0, 1.0)) = 2.0
_GlowRange("GlowRange",Range(0.1,1))=0.3
}
SubShader{
Pass{ Tags{ "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag float4 _Color; float4 vert(float4 vertexPos : POSITION) : SV_POSITION{ return mul(UNITY_MATRIX_MVP, vertexPos); } float4 frag(void) : COLOR{ return _Color; } ENDCG }
Pass{
Tags{"LightMode" = "ForwardBase" "Queue" = "Transparent" "RenderType" = "Transparent"}
// Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float4 _GlowColor;
float _Strength;;
float _GlowRange;
struct vInput {
float4 vertex : POSITION;
float4 normal : NORMAL;
};
struct v2f {
float4 position : SV_POSITION;
float4 col:COLOR;
};
v2f vert(vInput i) {
v2f o;
float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
float3 normalDirection = normalize(mul(i.normal, modelMatrixInverse)).xyz;
float3 viewDirection = normalize(_WorldSpaceCameraPos - mul(modelMatrix, i.vertex).xyz);
float4 pos = i.vertex + (i.normal * _GlowRange);
o.position = mul(UNITY_MATRIX_MVP, pos);
float3 normalDirectionT = normalize(normalDirection); float3 viewDirectionT = normalize(viewDirection); float strength = abs(dot(viewDirectionT, normalDirectionT)); float opacity = pow(strength, _Strength);
float4 col = float4(_GlowColor.xyz, opacity);
o.col = col;
return o;
}
float4 frag(v2f i) : COLOR{
return i.col;
}
ENDCG
}
}
}
2、控制脚本部分C#代码:
using UnityEngine; using System.Collections; public class GlowControl : MonoBehaviour { private Material mat; private float value; [SerializeField] float speed=1; // Use this for initialization void Start () { mat = GetComponent<MeshRenderer>().sharedMaterial; } // Update is called once per frame void Update () { value = Mathf.PingPong(Time.time * speed, 5); /// Debug.Log(value); mat.SetFloat("_Strength", value); } }
就是一个简单控制强度随着时间变换的代码。
三、总结
这个小小的案例我们学习到了怎么使用多个Pass块来渲染同一个物体,以及在多个Pass块中使用透明度混合。我个人认为是一个非常不错的学习案例,不只是因为
它的代码部分非常简洁明了,更重要的是这个案例在很多应用中也是非常有用的。祝好好学习,慢慢变牛。
每天进步一点点。
相关文章推荐
- Unity3D占用内存太大的解决方法
- 设计模式深入学习--State 状态模式(行为型模式)
- 设计模式之一:单例模式
- unity, Animator.ResetTrigger
- 支付宝Unity
- Unity3D -- 常用函数和变量(Shader学习之一)
- 设计模式深入学习--Observer 观察者模式(行为型模式)
- 设计模式深入学习--Template Method模板方法模式(行为型模式)
- 设计模式深入学习--Mediator 中介者模式(行为型模式)
- Unity3D-代码控制粒子移动或者按照预定的路径移动(ParticleSystem)
- 设计模式深入学习--Interpreter 解释器模式(行为型模式)
- 设计模式深入学习--Command 命令模式(行为型模式)
- 设计模式深入学习---Adapter 适配器模式(结构型模式)
- 设计模式深入学习--Proxy 代理模式(结构型模式)
- IOC容器Unity的使用及独立配置文件Unity.Config
- iOS整合Unity项目加入SceneKit报错Undefined symbols for architecture arm64: "_OBJC_CLASS_$_SCNLight"
- Unity3D研究院之游戏对象的访问绘制线与绘制面详解(十七)
- unity版本控制
- Unity原生UGUI之Scroll View坑的地方
- 设计模式深入学习-抽象工厂模式