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 ...
随机推荐
- compile php with openssl on mac osx error 填坑
从源码手动编译 PHP 时出现如下错误: Default 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Undefined symbols for arch ...
- STM32F412应用开发笔记之七:片上ADC的应用测试
在我们的应用项目中需要采集一些模拟量,这些量使用MCU自带的ADC就可以满足要求.在NUCLEO-F412ZG实验板上的STM32F412ZG有一个16通道的ADC,我们试验用它采集几个数据. 在NU ...
- python之__dict__与dir(转载)
Python下一切皆对象,每个对象都有多个属性(attribute),Python对属性有一套统一的管理方案. __dict__与dir()的区别: dir()是一个函数,返回的是list: __di ...
- linux 搜索文件
https://blog.csdn.net/json_ligege/article/details/72865645 1.find find是最常见和最强大的查找命令,你可以用它找到任何你想找的文 ...
- poj2823 单调队列初步
什么是单调队列:头元素一直是队列当中的最大值,队列中的值按照递减顺序排列,可以从末尾插入一个元素,或从两段删除元素 1.插入元素,为了保证队列的单调性(这里假设为递减性),在插入元素v时要将对位的元素 ...
- hdu3642扫描线 长方体
立方体交,自己写的莫名其妙MLE了,不知道为什么 #include<iostream> #include<cstring> #include<cstdio> #in ...
- Math对象的常用属性和方法
属性 描述 Math.PI 返回π(3.1415926) 方法 描述 Math.round() 将数字四舍五入到离它最近的整数 Math.sart(n) 返回平方根,例如Math.sart(9)返回3 ...
- Ubuntu 16.04 LTS 搭建ftp服务器
其实我之前搭建好了,但是最近我上来看好像跟没搭建一样呢,于是我从新搭建一遍? 我的ubuntu版本: cat /etc/issue Ubuntu 16.04 LTS \n \l 1.安装vsftpd( ...
- [HEOI2016/TJOI2016]序列
题解: 很水的题目 首先容易发现每个位置实际上只有最大值是有用的 然后把条件变成dp[i]=max(dp[j]+1)(j<i,F[i]>G[j],G[i]>H[j]) 然后我研究了一 ...
- 【深入spring】IoC容器的实现
本文乃学习整理参考而来 IoC概述: 在spring中,IoC容器实现了依赖控制反转,它可以再对象生成或初始化时直接将数据注入到对象中,也可以通过将对象引用注入到对象数据域中的方式来注入方法调用的依赖 ...