Unity Shader-后处理:Bloom全屏泛光
一.简介
二.原理介绍
1.HDR
2.Bloom
三.代码实现
- using UnityEngine;
- using System.Collections;
- [ExecuteInEditMode]
- public class BloomEffect : PostEffectBase
- {
- //分辨率
- public int downSample = 1;
- //采样率
- public int samplerScale = 1;
- //高亮部分提取阈值
- public Color colorThreshold = Color.gray;
- //Bloom泛光颜色
- public Color bloomColor = Color.white;
- //Bloom权值
- [Range(0.0f, 1.0f)]
- public float bloomFactor = 0.5f;
- void OnRenderImage(RenderTexture source, RenderTexture destination)
- {
- if (_Material)
- {
- //申请两块RT,并且分辨率按照downSameple降低
- RenderTexture temp1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
- RenderTexture temp2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
- //直接将场景图拷贝到低分辨率的RT上达到降分辨率的效果
- Graphics.Blit(source, temp1);
- //根据阈值提取高亮部分,使用pass0进行高亮提取
- _Material.SetVector("_colorThreshold", colorThreshold);
- Graphics.Blit(temp1, temp2, _Material, 0);
- //高斯模糊,两次模糊,横向纵向,使用pass1进行高斯模糊
- _Material.SetVector("_offsets", new Vector4(0, samplerScale, 0, 0));
- Graphics.Blit(temp2, temp1, _Material, 1);
- _Material.SetVector("_offsets", new Vector4(samplerScale, 0, 0, 0));
- Graphics.Blit(temp1, temp2, _Material, 1);
- //Bloom,将模糊后的图作为Material的Blur图参数
- _Material.SetTexture("_BlurTex", temp2);
- _Material.SetVector("_bloomColor", bloomColor);
- _Material.SetFloat("_bloomFactor", bloomFactor);
- //使用pass2进行景深效果计算,清晰场景图直接从source输入到shader的_MainTex中
- Graphics.Blit(source, destination, _Material, 2);
- //释放申请的RT
- RenderTexture.ReleaseTemporary(temp1);
- RenderTexture.ReleaseTemporary(temp2);
- }
- }
- }
- Shader "Custom/BloomEffect" {
- Properties{
- _MainTex("Base (RGB)", 2D) = "white" {}
- _BlurTex("Blur", 2D) = "white"{}
- }
- CGINCLUDE
- #include "UnityCG.cginc"
- //用于阈值提取高亮部分
- struct v2f_threshold
- {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- };
- //用于blur
- struct v2f_blur
- {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- float4 uv01 : TEXCOORD1;
- float4 uv23 : TEXCOORD2;
- float4 uv45 : TEXCOORD3;
- };
- //用于bloom
- struct v2f_bloom
- {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- float2 uv1 : TEXCOORD1;
- };
- sampler2D _MainTex;
- float4 _MainTex_TexelSize;
- sampler2D _BlurTex;
- float4 _BlurTex_TexelSize;
- float4 _offsets;
- float4 _colorThreshold;
- float4 _bloomColor;
- float _bloomFactor;
- //高亮部分提取shader
- v2f_threshold vert_threshold(appdata_img v)
- {
- v2f_threshold o;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- o.uv = v.texcoord.xy;
- //dx中纹理从左上角为初始坐标,需要反向
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- o.uv.y = 1 - o.uv.y;
- #endif
- return o;
- }
- fixed4 frag_threshold(v2f_threshold i) : SV_Target
- {
- fixed4 color = tex2D(_MainTex, i.uv);
- //仅当color大于设置的阈值的时候才输出
- return saturate(color - _colorThreshold);
- }
- //高斯模糊 vert shader(上一篇文章有详细注释)
- v2f_blur vert_blur(appdata_img v)
- {
- v2f_blur o;
- _offsets *= _MainTex_TexelSize.xyxy;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- o.uv = v.texcoord.xy;
- o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);
- o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;
- o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;
- return o;
- }
- //高斯模糊 pixel shader(上一篇文章有详细注释)
- fixed4 frag_blur(v2f_blur i) : SV_Target
- {
- fixed4 color = fixed4(0,0,0,0);
- color += 0.40 * tex2D(_MainTex, i.uv);
- color += 0.15 * tex2D(_MainTex, i.uv01.xy);
- color += 0.15 * tex2D(_MainTex, i.uv01.zw);
- color += 0.10 * tex2D(_MainTex, i.uv23.xy);
- color += 0.10 * tex2D(_MainTex, i.uv23.zw);
- color += 0.05 * tex2D(_MainTex, i.uv45.xy);
- color += 0.05 * tex2D(_MainTex, i.uv45.zw);
- return color;
- }
- //Bloom效果 vertex shader
- v2f_bloom vert_bloom(appdata_img v)
- {
- v2f_bloom o;
- //mvp矩阵变换
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- //uv坐标传递
- o.uv.xy = v.texcoord.xy;
- o.uv1.xy = o.uv.xy;
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- o.uv.y = 1 - o.uv.y;
- #endif
- return o;
- }
- fixed4 frag_bloom(v2f_bloom i) : SV_Target
- {
- //取原始清晰图片进行uv采样
- fixed4 ori = tex2D(_MainTex, i.uv1);
- //取模糊普片进行uv采样
- fixed4 blur = tex2D(_BlurTex, i.uv);
- //输出= 原始图像,叠加bloom权值*bloom颜色*泛光颜色
- fixed4 final = ori + _bloomFactor * blur * _bloomColor;
- return final;
- }
- ENDCG
- SubShader
- {
- //pass 0: 提取高亮部分
- Pass
- {
- ZTest Off
- Cull Off
- ZWrite Off
- Fog{ Mode Off }
- CGPROGRAM
- #pragma vertex vert_threshold
- #pragma fragment frag_threshold
- ENDCG
- }
- //pass 1: 高斯模糊
- Pass
- {
- ZTest Off
- Cull Off
- ZWrite Off
- Fog{ Mode Off }
- CGPROGRAM
- #pragma vertex vert_blur
- #pragma fragment frag_blur
- ENDCG
- }
- //pass 2: Bloom效果
- Pass
- {
- ZTest Off
- Cull Off
- ZWrite Off
- Fog{ Mode Off }
- CGPROGRAM
- #pragma vertex vert_bloom
- #pragma fragment frag_bloom
- ENDCG
- }
- }
- }
注:PostEffectBase类是后处理类的基类,在前面的文章已有详细介绍,这里不再贴出。
四.效果展示
本篇文章介绍的主要是全屏泛光的实现方式,也就是泛光的部分只是通过一个全屏的颜色阈值来进行设定,超过这一阈值的颜色就进行泛光操作,否则不会泛光。这样做效率较高,但是没办法控制单独的物体进行泛光。网上也有这种针对单独对象的bloom操作,可以实现更加细致的Bloom效果,这篇文章可以进行参考。
Unity Shader-后处理:Bloom全屏泛光的更多相关文章
- Unity Shader后处理-搜索灰度效果
如U3D中Hierarchy面板下的搜索效果: 讲解分析: 1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法.顾名思义屏幕后处理就是指在渲染完 ...
- Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果
建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...
- Unity Shader 屏幕后效果——Bloom外发光
Bloom的原理很简单,主要是提取渲染图像中的亮部区域,并对亮部区域进行模糊处理,再与原始图像混合而成. 一般对亮部进行模糊处理的部分采用高斯模糊,关于高斯模糊,详见之前的另一篇博客: https:/ ...
- Unity shader学习之屏幕后期处理效果之Bloom效果
Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...
- 【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)
写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shad ...
- 【我的书】Unity Shader的书 — 目录(2016.5.19最后一次更新)
写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shad ...
- Unity Shader 入门精要学习 (冯乐乐 著)
第1篇 基础篇 第1章 欢迎来到Shader的世界 第2章 渲染流水线 第3章 Unity Shader 基础 第4章 学习Shader所需的数学基础 第2篇 初级篇 第5章 开始Unity Shad ...
- 【转】《Unity Shader入门精要》冯乐乐著 书中彩图
为方便个人手机学习时候查阅,从网上转来这些彩图. 如属过当行为,联系本人删除. 勘错表 http://candycat1992.github.io/unity_shaders_book/unity_s ...
- Unity Shader 知识点总结(二)
紧接着上一篇文章的shader入门知识的总结,本文主要总结shader中的纹理贴图.透明度混合.顶点动画.后期特效处理等操作.如果有什么地方有错,请指出更正,谢谢.本文的代码主要来自开源书:unity ...
- 小强学渲染之Unity Shader噪声应用
之前玩Tencent的仙剑4手游时,杀死boss会看到boss有“消融”的效果,就是身体上有多个洞洞然后往四周扩散直至尸体完全消失,但效果是没有关闭背面剔除的“穿帮”效果,可能也是考虑性能因素. em ...
随机推荐
- mac安装RabbitMQ
1 下载 地址 http://www.rabbitmq.com/install-standalone-mac.html 2 rabbitmq的安装目录: /Users/ysyc1/rabbitmq_s ...
- CCF2015122消除类游戏(C语言版)
问题描述 消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消 ...
- Laravel attribute casting 导致的 Indirect modification of overloaded property
在 Laravel model 中,设置了某个属性做 array casting. protected $casts = [ 'rounds' => 'array', ]; 但是在 contro ...
- Python 索引迭代
1.使用enumerate函数 L = ['Adam', 'Lisa', 'Bart', 'Paul'] for index, name in enumerate(L): print inde ...
- python 全栈开发,Day99(作业讲解,DRF版本,DRF分页,DRF序列化进阶)
昨日内容回顾 1. 为什么要做前后端分离? - 前后端交给不同的人来编写,职责划分明确. - API (IOS,安卓,PC,微信小程序...) - vue.js等框架编写前端时,会比之前写jQuery ...
- python 全栈开发,Day32(知识回顾,网络编程基础)
一.知识回顾 正则模块 正则表达式 元字符 : . 匹配除了回车以外的所有字符 \w 数字字母下划线 \d 数字 \n \s \t 回车 空格 和 tab ^ 必须出现在一个正则表达式的最开始,匹配开 ...
- 向集合中添加自定义类型--建议在自定义类型的时候要重写equals方法
package com.bjpowernode.t01list; import java.util.ArrayList; /* * 向集合中添加自定义类型 */public class TestLis ...
- poj 1751 输出MST中新加入的边
给出结点的坐标 以及已建好的边 要输出MST中加入的边(已建好的边就不用输出了)结点的编号从1开始注意这题只有一组数据 不能用多组输入 否则就超时(在这被坑惨了Orz) Sample Input 91 ...
- hdu 4549 M斐波拉契 (矩阵快速幂 + 费马小定理)
Problem DescriptionM斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = aF[1] = bF[n] = F[n-1] * F[n-2] ( n > 1 ) 现在 ...
- 【Restful】三分钟彻底了解Restful最佳实践
REST是英文representational state transfer(表象性状态转变)或者表述性状态转移;Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,HTML等 ...