Unity Shader后处理-搜索灰度效果
如U3D中Hierarchy面板下的搜索效果:

讲解分析:
1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法。顾名思义屏幕后处理就是指在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效。
2.要实现这种屏幕后处理的基础在于得到渲染后的屏幕图像,即抓取屏幕,Unity中提供给我们一个方便接口——OnRenderImage函数。
3.OnRenderImage函数定义为MonoBehaviour.OnRenderImage (RenderTexture src, RenderTexture dest); Unity会把当前渲染得到的图像存储在第一个参数对应的源渲染纹理中,通过该函数一系列操作后,再把目标渲染纹理,即第二个参数对应的渲染纹理显示到屏幕上。在OnRenderImage函数中,通常利用Graphics.Blit函数来完成对渲染纹理的处理。(若dest为null,就会直接将结果显示到屏幕上)。

src纹理是源纹理,在屏幕后处理技术中,该参数就是当前屏幕的渲染纹理或者是上一步处理后得到的渲染纹理。参数mat是材质,此材质使用的Unity Shader将会进行各种屏幕后处理操作,而src纹理将会被传递给材质的shader中名为_MainTex的纹理属性。参数pass的默认值为-1,即依次执行shader中的所有Pass,否则 仅会调用给定索引的Pass。
4.整个过程如下:
首先在摄像机中添加一个用于屏幕后处理的脚本。在该脚本中,我们会实现OnRenderImage函数来获取当前屏幕的渲染纹理。其次,再调用Graphics.Blit函数使用特定的Unity Shader来对当前图像进行处理,再把返回的渲染纹理显示到屏幕上。对于一些复杂的屏幕特效,可能多次调用Graphics.Blit函数对上一步输出结果进行下一步处理。
详细代码:
PostEffect.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering; [ExecuteInEditMode]
public class PostEffect : MonoBehaviour
{ #region Variables
public float grayScaleAmout = 1.0f; //主相机
public Camera sourceCamera; //操作相机(为了结合另一个PostEffect,(OutlineEffect操作的相机))
public Camera outlineCamera; //渲染纹理
RenderTexture renderTexture; //开始灰色渲染效果标志
public bool isStart = false; //材质
Material material = null; #endregion void Start()
{
if (material == null)
{
material = new Material(Resources.Load<Shader>("NewUnlitShader"));
}
} void OnPreRender()
{
if (renderTexture == null || renderTexture.width != sourceCamera.pixelWidth || renderTexture.height != sourceCamera.pixelHeight)
{
renderTexture = new RenderTexture(sourceCamera.pixelWidth, sourceCamera.pixelHeight, , RenderTextureFormat.Default);
outlineCamera.targetTexture = renderTexture;
}
outlineCamera.Render();
} void OnRenderImage(RenderTexture source, RenderTexture target)
{
if (isStart)
{
if (material != null)
{
material.SetTexture("_OutLine", outlineCamera.targetTexture);
material.SetFloat("_LuminosityAmount", grayScaleAmout);
Graphics.Blit(source, target, material);
}
}
else
{
Graphics.Blit(source, target);
}
} void OnDisable()
{
if (material)
{
DestroyImmediate(material);
}
}
}
shader部分:
Shader "Custom/GrayScale" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_LuminosityAmount ("GrayScale Amount", Range(0.0, )) = 1.0
}
SubShader {
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
fixed _LuminosityAmount;
uniform sampler2D _OutLine;
fixed _NumPixelH;
fixed _NumPixelV;
fixed4 frag(v2f_img i) : COLOR
{
fixed4 outlineTex = tex2D(_OutLine, i.uv);
fixed4 renderTex = tex2D(_MainTex, i.uv);
if((outlineTex.r+outlineTex.b+outlineTex.g+outlineTex.a)<0.1f)
{
float luminosity = 0.299 * renderTex.r + 0.587 * renderTex.g + 0.114 * renderTex.b;
fixed4 finalColor = lerp(renderTex, luminosity, _LuminosityAmount);
return finalColor;
}
else
{
return renderTex;
}
}
ENDCG
}
}
FallBack "Diffuse"
}
注释:

判断纹理顶点色值,我的源纹理初始色为黑色,所以搜索的物体附上色值,判断rgba的和是否为0,0为黑色,1为白色,黑色部分置灰(没选中的物体及场景其他部分),有色差的部分为选中部分返回当前color。
这效果结合上一篇的Outline效果,源纹理为上一篇处理的纹理,即_OutLine ,_MainTex为主纹理,即当前屏幕纹理。
测试代码:
using cakeslice;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI; public class test : MonoBehaviour
{
public InputField Txt; GameObject go = null; public void OnClick()
{
var chr = Txt.text.ToCharArray();
StringBuilder stringBuilder = new StringBuilder();
for (int i = ; i < chr.Length; i++)
{
if (i == )
{
stringBuilder.Append(chr[].ToString().ToUpper());
}
else
{
stringBuilder.Append(chr[i].ToString().ToLower());
}
}
Debug.Log(stringBuilder.ToString()); go = GameObject.Find(stringBuilder.ToString());
if (go != null)
{
go.GetComponent<cakeslice.Outline>().Add();
Camera.main.GetComponent<PostEffect>().isStart = true;
}
else
{
Debug.Log("根据 "+ Txt.text + " 未找到搜索物体,请查看是否输入错误");
}
} public void UnDo()
{
if (go!=null)
{
go.GetComponent<cakeslice.Outline>().Remove();
Camera.main.GetComponent<PostEffect>().isStart = false;
go = null;
}
}
}
实现效果如下:

Unity Shader后处理-搜索灰度效果的更多相关文章
- Unity shader UI的3D效果
原创,转载请标明出处 1.效果 scene视图中的效果: game视图中效果: 2.核心思想:改变UI的顶点坐标 3.好处:可以用正交相机来实现3D效果. 4.Shader 实现 // Unity b ...
- Unity shader学习之轮廓效果
将物体描一层边可以使游戏看起来具有卡通风格,一种简单的实现方法如下: 将物体渲染2次,即使用2个通道. 第一个通道将顶点沿法线(或中心点到顶点的方向)做一个偏移,即将模型扩大一点,并将颜色渲染成轮廓的 ...
- Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果
建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...
- Unity Shader实现描边效果
http://gad.qq.com/article/detail/28346 描边效果是游戏里面非常常用的一种效果,一般是为了凸显游戏中的某个对象,会给对象增加一个描边效果.本篇文章和大家介绍下利用S ...
- Unity Shader - 消融效果原理与变体
基本原理与实现 主要使用噪声和透明度测试,从噪声图中读取某个通道的值,然后使用该值进行透明度测试. 主要代码如下: fixed cutout = tex2D(_NoiseTex, i.uvNoiseT ...
- Unity3D学习(八):《Unity Shader入门精要》——透明效果
前言 在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道. Unity中通常使用两种方法来实现透明 :(1)透明度测试(AlphaTest)(2)透明度混合(AlphaBlend).前者往 ...
- Unity shader学习之屏幕后期处理效果之高斯模糊
高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...
- 【Unity Shader】(五) ------ 透明效果之半透明效果的实现及原理
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题 [Unity Shader学习笔记](三) -- ...
- 【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
随机推荐
- Java.math.BigDecimal.abs()方法
java.math.BigDecimal.abs()返回一个BigDecimal,其值是此BigDecimal的绝对值,其标度是this.scale(). 声明 以下是java.math.BigDec ...
- 20140923 cin.get() getline cin
#include<iostream> #include<string> using namespace std; int main() { string title; ...
- ollvm 使用——“Cannot open /dev/random”错误的解决方法
找到 \obfuscator-llvm-4.0\lib\Transforms\Obfuscation\CryptoUtils.cpp 这个文件, 新增两个头文件 #include <window ...
- OpenGL学习——绘制矩形
接下来稍微扩展一步,绘制矩形,即两个拼在一起的三角形. 引入一个概念, EBO Element Buffer Object 元素缓冲对象, EBO用于存放描述“顶点绘制顺序”的对象. 外注:创建VS ...
- 【LeetCode】水题(刚开始重新刷题找感觉用的)
[9] Palindrome Number [Easy] 给一个数字,用不转化成字符串的方式判断它是否是回文. 先求数字长度,然后把数字的后半段做翻转(就是不断地取模,除10这种方式),然后判断前后半 ...
- static变量与普通变量的异同
1.static局部变量与普通局部变量的异同 相同点:都是局部变量,在函数内部定义,仅能被该模块内部的语句所访问. 不同点: 1)内存分配与释放: static修饰的局部变量在内存中存放在静态存储区, ...
- koa 的 Context
context上下文对象: 该对象类似原生http中的 req + res - 该对象的req,res属性也存在,就是原生没有包装过的req,res - 简单说: context 对象就是从请求到响应 ...
- SpringCloud---分布式服务跟踪---Spring Cloud Sleuth
1.概述 1.1 为什么要用到服务跟踪? 随着业务的发展,系统规模也会变得越来越大,各服务之间的调用关系也变得越来越错综复杂: 通常一个由客户端发起的请求 在后端系统中会经过多个不同的微服务调用 ...
- PHP ftp_get() 函数
定义和用法 ftp_get() 函数从 FTP 服务器上下载一个文件并保存到本地一个文件中. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_get(ftp_connec ...
- Android中的Handler,Looper,Message机制
Android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...