笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

对于游戏中使用的类似喷墨效果,在射击类游戏中经常使用比如玩家射击的子弹会在墙上出现类似喷墨效果,效果如下所示:

在默认情况下,屏幕的整个Alpha通道都是黑色的,直到玩家开始喷射油墨,才会使被油墨溅到区域的Alpha通道变为白色。然后图像效果就是其原有颜色与灰度进行混合。

实现方式如下所示:

从上图可以看出,使用Projector将喷漆绘制到物体表面并创建颜色遮罩。每个Projector都使用程序化动态生成,在子弹(空中飞行的白点)接触到某个表面时进行初始化。Projector带有一个盒式碰撞体,当子弹落在Projector上时,不会初始化新的Projector,而是让原先的Projector变大。这样漆量会变多,而场景中的Projector数量却保持不变。

默认情况下,Unity标准着色器会为所有不透明对象的Alpha通道写入1。所以下面使用自定义着色器来替换Unity标准着色器。新建一个标准表面着色器,将其表面函数替换为如下:

void surf(Input IN, inout SurfaceOutputStandard o)
{//Albedo 来自带颜色的纹理fixed4 c=tex2D(_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;o.Metallic = _Metallic;o.Smoothness = _Glossiness;o.Alpha = 0;  //只添加此行
}

下面这行很重要,用于避免Unity更改自定义的Alpha值。将#pragma那行代码改为如下:

CGPROGRAM
#pragma surface surf Standard fullforwardshadows keepalphs

注意,该技巧不可用于Unity中的延迟渲染管线,因为它重写了G-Buffer中的Alpha通道来存储遮罩数据。

当子弹撞击某个表面时就会在撞击处动态生成Unity Projector。这些Projector带有自定义材质与自定义着色器。材质纹理是一张带有Alpha通道喷溅形状图,本文示例使用的纹理如下图:


注意,纹理导入设置中要将Wrap Mode设为“Clamp”而非“Repeat”。用于Projector材质的着色器从Unity提供的ProjectorLight修改而来,代码如下:

Shader "Projector/ProjectAlpha"
{Properties{_ShadowTex("Cookie", 2D) = "gray"{}}Subshader{Tags{"Queue" = "Transparent"}Pass{ZWrite OffBlend Zero One,One OneOffset -1, -1CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fog#include "UnityCG.cginc"struct Input{float4 vertex : LagPosition;float3 normal : NORMAL;};struct v2f{float4 uvShadow : TEXCOORD0;UNITY_FOG_COORDS(2)float4 pos : SV_POSITION;fixed nv : COLOR0;};float4x4 unity_Projector;float4x4 unity_ProjectorClip;v2f vert(Input v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);o.uvShadow = mul(unity_Projector, v.vertex);UNITY_TRANSFER_FOG(o, o.pos);float3 normView = normalize(float3(unity_Projector[2][0], unity_Projector[2][1], unity_Projector[2][2]));float nv = dot(v.normal, normView);o.nv = nv < 0 ? 1: 0;return o;}sampler2D _ShadowTex;sampler2D _FalloffTex;fixed4 frag(v2f i) : COLOR{fixed4 texS = tex2DProj(_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));fixed4 res = fixed4(1,1,1,texS.a);res.a = i.nv;UNITY_APPLY_FOG_COLOR(i.fogCoord, res, fixed4(1,1,1,1));return res;}EDNCG}}
}

再介绍一下,关于混合的部分:

当着色器计算某个像素的颜色时,该颜色必须作用于屏幕上该点已经存在的像素颜色之上。默认情况下,新的像素会完全覆盖原有像素,但新像素也可以与原有像素进行混合。混合通常用于让对象呈透明或半透明效果,当然也可以实现很多其它的炫酷特效。

关键字Blend可以包含在Subshader或Pass标签中,甚至对同一个着色器的不同Pass进行混合。添加Blend关键字后,必须写入混合因子。混合因子如下:

Src指向着色器用于计算的颜色。Dst指向屏幕上已有的像素颜色。着色器用于计算的颜色会与第一个因子相乘,而屏幕上已有颜色会与第二个因子相乘。将两个结果相加,就是最终写到屏幕的颜色。

所以"Blend SrcAlpha One"会将自身Alpha值与当前着色器计算的颜色相乘,此时屏幕上的颜色暂未改动。然后再将屏幕颜色计算后的结果与前者相加。还可以使用逗号分隔两组因子,逗号前的混合选项用于计算颜色,逗号后的混合选项仅计算Alpha通道。可以查阅Unity文档了解更多关于混合的内容。

用于Projector的着色器就是“Blend Zero One, One One”,“Zero One”移除了飞溅纹理的颜色,使用子弹所飞溅到的表面颜色。“One One”将飞溅物的Alpha值与表面Alpha值相加。

现在使用上面的着色器与材质来生成Projector,应该将场景视图的Alpha通道设为白色。

现在可以随意修改Alpha通道,但还未达到最终效果。下面利用Alpha遮罩来创建游戏所需的图像特效。

首先,创建要使用图像特效的着色器。在Unity中新建默认的Image Effect Shader,然后将片段代码替换为如下:

fixed4 frag(v2f i) : SV_Target
{fixed4 col = tex2D(_MainTex, i.uv);fixed3 bnw = dot(col.rgb, float3(0.3,0.59,0.11));col.rgb = lerp(bnw, col.rgb, col.a);return col;
}

可以随意更改bnw(Black&White)变量以达到理想的混合效果。最后还需要新建脚本来运行该图像特效。脚本非常简单,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityStandardAssets.ImageEffectBase;[ExecuteInEditMode]
[ImageEffectAllowedInSceneView]
public class ALphaColorSwitch : ImageEffectBase{void OnRenderImage(RenderTexture source, RenderTexture destination){Graphics.Blit (source, destination, material);}
}

注意,这里用到了ImageEffectBase,该资源在Unity标准资源库中(Unity 5.5及以上版本推荐使用Post Processing Stack资源库代替ImageEffects)。导入标准资源库后,将脚本绑定到相机(确保将相机的渲染模式设为Forward)上,并将公共的着色器变量设为前面提到的着色器。

到此就可以向场景中喷射油墨啦!

Unity喷墨效果Shader实现相关推荐

  1. unity 半透明效果shader

    Shader "Unlit/半透明" {Properties{_Diffuse("Diffuse",Color) = (1,1,1,1) // 漫反射_Main ...

  2. Unity镜子效果的实现(无需镜子Shader)

    Unity镜子效果制作教程 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分享 ...

  3. Unity从零开始实现一个全息效果Shader

    Unity从零开始实现一个全息效果Shader 前言 开始捣鼓 一.准备阶段 二.先从透明效果开始 三.顶点故障效果 四.扫描线效果 五.菲尼尔反射效果 六.颗粒效果 七.颜色故障效果 CustomE ...

  4. Unity ASE制作彩色流光马赛克 像素风 舞池DJ台效果Shader

    Unity ASE制作彩色流光马赛克 舞池DJ台效果 Shader@TOC 项目需求想写一个舞池DJ台的效果,尝试写了发现制作出好玩的效果. 首先想要得到这种棋盘格的效果,想到了马赛克像素平铺,平铺数 ...

  5. Unity学习之Shader

    Shader 是用来实现图像渲染的,用来替代固定渲染管线的可编辑程序.其中Vertex Shader(顶点着色器)主要负责顶点的几何关系等的运算,Pixel Shader(像素着色器)主要负责片元颜色 ...

  6. Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法颜色、光照与材质

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...

  7. Unity 毛玻璃效果(UGUI)—高斯模糊

    因为Unity 提供了GrabPass,可以在Shader中很方便的拿到Panel下面的图像,即_GrabTexture. 注:添加优化.原本的搞死模糊效果达不到苹果的那种细腻效果,修改参数即可. 修 ...

  8. Unity双面材质Shader

    Unity双面材质Shader. 正面渲染支持漫反射贴图.法线贴图.高光度等.背面渲染支持漫反射贴图. Shader代码如下: Shader "LiangHaoXiangShaders/Do ...

  9. Unity 3D开发--Shader入门基础

    Shader "Unlit/xxShader" {Properties{//基础属性 并可以显示在属性板上_MainTex ("Texture", 2D) = ...

  10. unity自发光透明shader

    unity自发光透明shader 这本来是一个glass的shader,但是我发现也可以用到自发光+透明,这两个脚本都是unity文档里面的.呵呵~~~ [html] view plaincopypr ...

最新文章

  1. 显示乱七八糟图片问题之解决
  2. leetcode算法题--最大加号标志★
  3. 理解Java NIO
  4. 1043 Is It a Binary Search Tree (25 分)【难度: 中 / 知识点: 构造二叉搜索树(BST) 】
  5. python申请内存函数_python进阶用法2 【从帮助函数看python内存申请机制】
  6. js相对路径相关(比如:js中的路径依赖导入该js文件的路径)
  7. 5.13 卡尔曼滤波
  8. 高级会计师计算机考试中级,会计师需要计算机等级考试吗
  9. 对属性可以赋值的位置
  10. 蔚来首座超充站落地苏州蔚来交付中心 已开启试运营
  11. Python使用pandas读取Excel文件数据和预处理小案例
  12. java程序本质,方法学之Java的本质
  13. Linux虚拟文件系统之文件读取(sys_read())
  14. Podfile、Podfile.lock、Manifest.lock、Podspec
  15. 强烈推荐一本MYSQL入门及复习的好书
  16. 计算机硬件维修书,计算机硬件维修手册
  17. 微信小程序之分包加载
  18. 2022年 HSC-1th中MISC的汝闻,人言否
  19. mt,sgd,gd含义
  20. 腾讯云学生服务器购买指南

热门文章

  1. 大学上计算机课要准备笔记本电脑吗,大一新生需要买笔记本电脑吗 有必要吗...
  2. win7下megui压片无声、卡死、音画不同步、无法转码、无法硬解的解决办法!
  3. Java银行账户管理系统实验总结
  4. 常见大学机房的计算机设备,长江大学公共机房管理办法
  5. 电影剪辑软件测试工程师,《剪辑师》职业标准(试运行)一、职业概况
  6. Android中的Drawable(一)
  7. 石灰窑计算机控制上料,石灰窑自动化控制系统
  8. 麻了!35岁奥地利总理辞职当码农
  9. 生活是艰难的,我又划着我的断桨出发了
  10. java获取字符串的最后一个字符_如何获取字符串的最后一个字符