unity 透明shadershader 人物走入草丛,草的晃动特效特效怎么做

unity shader 人物走入草丛,草的晃动特效特效怎么做_百度知道Unity3d 人物移动幻影效果怎么实现
[问题点数:100分]
Unity3d 人物移动幻影效果怎么实现
[问题点数:100分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。7827人阅读
Unity Shaders(57)
本系列主要参考一书(感谢原书作者),同时会加上一点个人理解或拓展。是本书所有的插图。是本书所需的代码和资源(当然你也可以从下载)。========================================== 分割线&==========================================写在前面呜呼,这本书最后一篇了有木有!!!想想就有点小激动呢。。。(可是还有很多隔过去了。)技术文章里就不说太多废话了,之后会写一篇总结的,坑也会慢慢补上的(我希望吧。)。好啦!我们本节要学习的特效是一个更加常见的画面特效。在市场上很多的第一人称射击游戏(FPS)中,我们都可以看到夜视效果的身影,比如《使命召唤》、《光晕》等等。这种效果使屏幕蒙上一层非常独特的黄绿色。下面是《使命召唤》中的夜视效果:&为了实现这种夜视效果,我们需要使用Photoshop来分解上述效果的实现。我们可以从网上找一些参考图片,然后和已有图层合并,看看我们需要哪种混合效果,以及我们要怎样组合不同的图层。下面的图像显示了在Photoshop中进行上述过程的最后结果:而最后Shader实现的结果像下面这样:下面,我们开始将Photoshop中的最终图像分解成几个部分,来更好的理解这些资源是如何被整合在一起的。而后,我们会深入讲解实现过程。准备工作之前说过,使用Photoshop可以让我们方便地构分层图像,以便我们可以更好地理解如何得到一个夜视效果。现在,我们就把夜视效果分解成几个组成图层。偏绿色的画面(Tinted green):夜视效果的第一个图层就是它标志性的绿色,几乎所有的夜视图像都是这种色调的。这可以让我们的特效看起来就是明显的夜视效果。扫描线(Scan lines):为了增加夜视效果的真实性,我们在上述着色层的上面添加了一层扫描线。在这里,我们使用了一张用Photoshop创建的纹理,然后让用户选择平铺系数来控制扫描线的宽窄和大小。噪点(Noise):下一个图层是一个简单的噪点图层,它平铺在上述两种图层的上方,用于分解图像为我们的特效添加更多的细节效果。晕影(Vignette):夜视效果的最后一层就是晕影。从上面《使命召唤》的游戏截图可以看出,它使用一个晕影来模拟一个视野效果。我们使用下面的图层来作为晕影纹理。现在,我们把上述各个纹理结合在一起,开始正式创建夜视效果的画面特效。准备好一张晕影纹理、一张噪声纹理和一张扫描线纹理,你可以在本书资源(见本文最上方)中找到对应的纹理。创建一个新的脚本,命名为NightVisionEffect.cs,以及一个新的Shader,命名为NightVisionEffectShader.shader。使用里的代码填充上述新的脚本和Shader。把OldFilmEffect脚本添加到Camera上,并使用OldFilmEffectShader给OldFilmEffect脚本中的Cur Shader赋值。实现现在你的画面特效脚本系统应该已经建立好了,现在我们来实现具体的脚本和Shader。首先,我们来填写NightVisionEffect.cs脚本的主要代码。第一步我们要定义一些需要在面板中显示的变量,以便让用户进行调整。在脚本中添加如下代码: #region Variables
public Shader nightVisionS
public float contrast = 2.0f;
public float brightness = 1.0f;
public Color nightVisionColor = Color.
public Texture2D vignetteT
public Texture2D scanLineT
public float scanLineTileAmount = 4.0f;
public Texture2D nightVisionN
public float noiseXSpeed = 100.0f;
public float noiseYSpeed = 100.0f;
public float distortion = 0.2f;
public float scale = 0.8f;
private Material curM
private float randomValue = 0.0f;
#endregion下面,我们需要填充OnRenderImage函数。在这个函数里,我们将要把上述变量传递给Shader,使得Shader可以使用这些数据来处理render texture: void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture){
if (nightVisionShader != null) {
material.SetFloat(&_Contrast&, contrast);
material.SetFloat(&_Brightness&, brightness);
material.SetColor(&_NightVisionColor&, nightVisionColor);
material.SetFloat(&_RandomValue&, randomValue);
material.SetFloat(&_Distortion&, distortion);
material.SetFloat(&_Scale&, scale);
if (vignetteTexture) {
material.SetTexture(&_VignetteTex&, vignetteTexture);
if (scanLineTexture) {
material.SetTexture(&_ScanLineTex&, scanLineTexture);
material.SetFloat(&_ScanLineTileAmount&, scanLineTileAmount);
if (nightVisionNoise) {
material.SetTexture(&_NoiseTex&, nightVisionNoise);
material.SetFloat(&_NoiseXSpeed&, noiseXSpeed);
material.SetFloat(&_NoiseYSpeed&, noiseYSpeed);
Graphics.Blit(sourceTexture, destTexture, material);
Graphics.Blit(sourceTexture, destTexture);
}最后,我们需要保证一些变量的范围。这些范围可以根据需要后续更改: void Update () {
contrast = Mathf.Clamp(contrast, 0.0f, 4.0f);
brightness = Mathf.Clamp(brightness, 0.0f, 2.0f);
distortion = Mathf.Clamp(distortion, -1.0f, 1.0f);
scale = Mathf.Clamp(scale, 0.0f, 3.0f);
randomValue = Random.Range(-1.0f, 1.0f);
}接下来,我们来实现关键的Shader部分。首先,还是添加一些新的Properties: Properties {
_MainTex (&Base (RGB)&, 2D) = &white& {}
_VignetteTex (&Vignette Texture&, 2D) = &white& {}
_ScanLineTex (&Scan Line Texture&, 2D) = &white& {}
_ScanLineTileAmount (&Scale Line Tile Amount&, Float) = 4.0
_NoiseTex (&Noise Texture&, 2D) = &white& {}
_NoiseXSpeed (&Noise X Speed&, Float) = 100.0
_NoiseYSpeed (&Noise Y Speed&, Float) = 100.0
_NightVisionColor (&Night Vision Color&, Color) = (1, 1, 1, 1)
_Contrast (&Contrast&, Range(0, 4)) = 2
_Brightness (&Brightness&, Range(0, 2)) = 1
_RandomValue (&Random Value&, Float) = 0
_Distortion (&Distortion&, Float) = 0.2
_Scale (&Scale (Zoom)&, Float) = 0.8
}我们还需要在CGPROGRAM块中添加对应的变量,以便Properties块可以和CGPROGRAM块通信: SubShader {
#pragma vertex vert_img
#pragma fragment frag
#include &UnityCG.cginc&
uniform sampler2D _MainT
uniform sampler2D _VignetteT
uniform sampler2D _ScanLineT
fixed _ScanLineTileA
uniform sampler2D _NoiseT
fixed _NoiseXS
fixed _NoiseYS
fixed4 _NightVisionC
fixed _RandomV
fixed _S我们的特效还需要一个透镜变形(lens distortion)效果,来模拟从透镜中观察、图像边界由于透镜度数而发生变形的效果。在变量声明的下方添加如下代码:
float2 barrelDistortion(float2 coord) {
// Lens distortion algorithm
// See /content/lensalg.htm
float2 h = coord.xy - float2(0.5, 0.5);
float r2 = h.x * h.x + h.y * h.y;
float f = 1.0 + r2 * (_Distortion * sqrt(r2));
return f * _Scale * h + 0.5;
}解释:夜视效果实际和之前的老电影效果很像,都是把一些图层组合、模块化起来。最大的不同就是这里使用了一个透镜变形效果。上述算法是由SynthEyes的成员提供的,免费使用哦~第一行代码首先找到纹理的中心——float(0.5, 0.5)。一旦得到了图像中心,我们可以根据像素距离中心的远近对像素应用一个拉伸。具体分析可见本文最下方的相关链接。现在,我们到了整个Shader的关键部分。首先,在frag函数里添加如下代码来得到render texture和晕影纹理:
fixed4 frag(v2f_img i) : COLOR {
// Get the colors from the Render Texture and the uv's
// from the v2f_img struct
half2 distortedUV = barrelDistortion(i.uv);
fixed4 renderTex = tex2D(_MainTex, distortedUV);
fixed4 vignetteTex = tex2D(_VignetteTex, i.uv);解释:这三行代码很简单。在得到了变形后的UV坐标后,采样得到render texture中对应的像素,再按正常的UV得到晕影纹理的对应像素。最后,得到了底层图像像素renderTex和晕影图层的像素vignetteTex。下一步,我们需要处理扫描线和噪点纹理,通过UV坐标为它们添加合适的动画:
// Process
scan lines and noise
half2 scanLinesUV = half2(i.uv.x * _ScanLineTileAmount, i.uv.y * _ScanLineTileAmount);
fixed4 scanLineTex = tex2D(_ScanLineTex, scanLinesUV);
half2 noiseUV = half2(i.uv.x + (_RandomValue * _SinTime.z * _NoiseXSpeed),
i.uv.y + (_Time.x * _NoiseYSpeed));
fixed4 noiseTex = tex2D(_NoiseTex, noiseUV);解释:这里跟之前老电影的纹理动画处理方式类似。对于扫描线纹理,之前我们说过,通过_ScanLineTileAmount可以调整画面上扫描线的宽窄和多少。_ScanLineTileAmount越大,条纹越密越细,反之越宽。对于噪点纹理,我们需要添加一个动态效果。在XY方向上处理方式稍有不同,这是为什么呢?我自己的理解是这样的。。。对于X方向,我们想要模拟的是一个小幅度的类似抖动的效果,因此用_SinTime作为因子。而对于Y方向,我们想要模拟向一个方向不断滚动的效果,因此使用_Time作为因子。最后,根据上述UV坐标可以得到扫描线纹理的像素scanLineTex和噪点纹理的像素noiseTex。最后一层图层是偏绿的颜色效果。我们仅仅需要处理render texture的光度值(Luminance),然后给它添加一个夜视颜色,来得到最终形象的夜视效果:
// Get the luminosity values from the render texture using the YIQ values
fixed lum = dot(fixed3(0.299, 0.587, 0.114), renderTex.rgb);
fixed4 finalColor = (lum * 2) + _NightVisionC解释:最后一层图层是为整个画面添加绿色色调。首先也是通过YIQ得到当前的光度值lum,再加上_Brightness来调整亮度。最后,再加上_NightVisionColor(也就是绿色)。这里lum*2是为了不至于让整个画面太暗。最后,我们把所有的图层结合在一起,返回最终的像素值:
// Final output
finalColor = pow(finalColor, _Contrast);
finalColor *= vignetteT
finalColor *= scanLineTex * noiseT
return finalC
}完整的脚本和Shader如下:NightVisionEffect脚本:using UnityE
using System.C
[ExecuteInEditMode]
public class NightVisionEffect : MonoBehaviour {
#region Variables
public Shader nightVisionS
public float contrast = 2.0f;
public float brightness = 1.0f;
public Color nightVisionColor = Color.
public Texture2D vignetteT
public Texture2D scanLineT
public float scanLineTileAmount = 4.0f;
public Texture2D nightVisionN
public float noiseXSpeed = 100.0f;
public float noiseYSpeed = 100.0f;
public float distortion = 0.2f;
public float scale = 0.8f;
private Material curM
private float randomValue = 0.0f;
#endregion
#region Properties
public Material material {
if (curMaterial == null) {
curMaterial = new Material(nightVisionShader);
curMaterial.hideFlags = HideFlags.HideAndDontS
return curM
#endregion
// Use this for initialization
void Start () {
if (SystemInfo.supportsImageEffects == false) {
if (nightVisionShader != null && nightVisionShader.isSupported == false) {
void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture){
if (nightVisionShader != null) {
material.SetFloat(&_Contrast&, contrast);
material.SetFloat(&_Brightness&, brightness);
material.SetColor(&_NightVisionColor&, nightVisionColor);
material.SetFloat(&_RandomValue&, randomValue);
material.SetFloat(&_Distortion&, distortion);
material.SetFloat(&_Scale&, scale);
if (vignetteTexture) {
material.SetTexture(&_VignetteTex&, vignetteTexture);
if (scanLineTexture) {
material.SetTexture(&_ScanLineTex&, scanLineTexture);
material.SetFloat(&_ScanLineTileAmount&, scanLineTileAmount);
if (nightVisionNoise) {
material.SetTexture(&_NoiseTex&, nightVisionNoise);
material.SetFloat(&_NoiseXSpeed&, noiseXSpeed);
material.SetFloat(&_NoiseYSpeed&, noiseYSpeed);
Graphics.Blit(sourceTexture, destTexture, material);
Graphics.Blit(sourceTexture, destTexture);
// Update is called once per frame
void Update () {
contrast = Mathf.Clamp(contrast, 0.0f, 4.0f);
brightness = Mathf.Clamp(brightness, 0.0f, 2.0f);
distortion = Mathf.Clamp(distortion, -1.0f, 1.0f);
scale = Mathf.Clamp(scale, 0.0f, 3.0f);
randomValue = Random.Range(-1.0f, 1.0f);
void OnDisable () {
if (curMaterial != null) {
DestroyImmediate(curMaterial);
NightVisionEffectShader如下:Shader &Custom/NightVisionEffectShader& {
Properties {
_MainTex (&Base (RGB)&, 2D) = &white& {}
_VignetteTex (&Vignette Texture&, 2D) = &white& {}
_ScanLineTex (&Scan Line Texture&, 2D) = &white& {}
_ScanLineTileAmount (&Scale Line Tile Amount&, Float) = 4.0
_NoiseTex (&Noise Texture&, 2D) = &white& {}
_NoiseXSpeed (&Noise X Speed&, Float) = 100.0
_NoiseYSpeed (&Noise Y Speed&, Float) = 100.0
_NightVisionColor (&Night Vision Color&, Color) = (1, 1, 1, 1)
_Contrast (&Contrast&, Range(0, 4)) = 2
_Brightness (&Brightness&, Range(0, 2)) = 1
_RandomValue (&Random Value&, Float) = 0
_Distortion (&Distortion&, Float) = 0.2
_Scale (&Scale (Zoom)&, Float) = 0.8
SubShader {
#pragma vertex vert_img
#pragma fragment frag
#include &UnityCG.cginc&
uniform sampler2D _MainT
uniform sampler2D _VignetteT
uniform sampler2D _ScanLineT
fixed _ScanLineTileA
uniform sampler2D _NoiseT
fixed _NoiseXS
fixed _NoiseYS
fixed4 _NightVisionC
fixed _RandomV
float2 barrelDistortion(float2 coord) {
// Lens distortion algorithm
// See /content/lensalg.htm
float2 h = coord.xy - float2(0.5, 0.5);
float r2 = h.x * h.x + h.y * h.y;
float f = 1.0 + r2 * (_Distortion * sqrt(r2));
return f * _Scale * h + 0.5;
fixed4 frag(v2f_img i) : COLOR {
// Get the colors from the Render Texture and the uv's
// from the v2f_img struct
half2 distortedUV = barrelDistortion(i.uv);
fixed4 renderTex = tex2D(_MainTex, distortedUV);
fixed4 vignetteTex = tex2D(_VignetteTex, i.uv);
// Process
scan lines and noise
half2 scanLinesUV = half2(i.uv.x * _ScanLineTileAmount, i.uv.y * _ScanLineTileAmount);
fixed4 scanLineTex = tex2D(_ScanLineTex, scanLinesUV);
half2 noiseUV = half2(i.uv.x + (_RandomValue * _SinTime.z * _NoiseXSpeed),
i.uv.y + (_Time.x * _NoiseYSpeed));
fixed4 noiseTex = tex2D(_NoiseTex, noiseUV);
// Get the luminosity values from the render texture using the YIQ values
fixed lum = dot(fixed3(0.299, 0.587, 0.114), renderTex.rgb);
fixed4 finalColor = (lum * 2) + _NightVisionC
// Final output
finalColor = pow(finalColor, _Contrast);
finalColor *= vignetteT
finalColor *= scanLineTex * noiseT
return finalC
FallBack &Diffuse&
完成后返回Unity编辑器查看效果。我们需要在面板中设置对应的图片和属性,像下面这样:扩展链接关于透镜形变效果:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1396220次
积分:13062
积分:13062
排名:第695名
原创:114篇
转载:20篇
译文:21篇
评论:1937条
我叫乐乐,程序媛一枚,就读于上海交通大学软件学院,研究生,数字媒体方向。喜欢用计算机来绘制各种五彩缤纷的画面~欢迎访问我的和 :)
邮件:lelefeng1992 # gmail DOT com
PS:为防止垃圾邮件,请自行转换为正确格式哦~
---------------------
阅读:54913
阅读:26367
文章:45篇
阅读:549063
(2)(1)(3)(1)(2)(2)(1)(1)(2)(2)(4)(2)(3)(6)(3)(8)(5)(6)(3)(6)(5)(7)(1)(2)(8)(1)(4)(5)(4)(3)(15)(2)(3)(27)(5)unity shader 人物走入草丛,草的晃动特效特效怎么做_百度知道

我要回帖

更多关于 口袋妖怪晃动的草丛 的文章

 

随机推荐