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 ...
随机推荐
- Day6------------硬盘分区
1.sda1 sd:串行接口 a:第一块硬盘 1:第一个分区 ls /dev/sd 查看硬盘 fdisk -l /dev/sda 查看分区信息 block------------>8*512 8 ...
- android录音实现不再担心—一个案例帮你解决你的问题
最近有小伙伴经常android的录音怎么实现,有没有相关的案例.今天给大家推荐一个android中实现录音和播放的小案例. 效果图: 一.实现录音的 Service 关键代码: // 开始录音 pub ...
- LeetCode(55): 跳跃游戏
Medium! 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1, ...
- 关系操作符 < > = == <= >= !=
基本类型可以用所有的操作符 对象要用equal eqauls() //用法 System.out.println(v1.equals(v2)); JAVA学习(二) STRING使用EQUALS方法和 ...
- P3660 【[USACO17FEB]Why Did the Cow Cross the Road III G】
题外话:维护区间交集子集的小套路 开两个树状数组,一个维护进入区间,一个维护退出区间 $Query:$ 给定询问区间$l,r$和一些其他区间,求其他区间中与$[l,r]$交集非空的区间个数 用上面维护 ...
- python接口自动化测试九:重定向相关
allow_redirects=False 不重定向 # 获取重定向后的地址 loc = r.headers # 相对地址 host = 'https://i.cnblogs.com/' url = ...
- python爬取百度贴吧帖子
最近偶尔学下爬虫,放上第二个demo吧 #-*- coding: utf-8 -*- import urllib import urllib2 import re #处理页面标签类 class Too ...
- P3331 [ZJOI2011]礼物(GIFT)
题解: 首先转化为平面问题 对于每一个z,f(x,y)的值为它能向上延伸的最大高度 ...莫名其妙想出来的是n^4 以每个点作为右下边界n^3枚举再o(n)枚举左下边界计算z的最大值 然而很显然这种做 ...
- P1019 单词接龙 字符串回溯
题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...
- C++ 冒泡排序、选择排序、快速排序
#include<stdio.h> #define N 10 void swap(int *p1, int *p2); void BubbleSort(int *a); void Sele ...