unity 背景模糊_unity 抓帧 背景模糊-程序员宅基地

技术标签: unity  背景模糊  景深  

shader代码

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'


Shader "Unlit/DoFShader"
{
//-----------------------------------【属性 || Properties】------------------------------------------    
    Properties  
    {  
        //主纹理  
        _MainTex("Base (RGB)", 2D) = "white" {}  
    }  
  
    //----------------------------------【子着色器 || SubShader】---------------------------------------    
    SubShader  
    {  
        ZWrite Off  
        Blend Off  
  
        //---------------------------------------【通道0 || Pass 0】------------------------------------  
        //通道0:降采样通道 ||Pass 0: Down Sample Pass  
        Pass  
        {  
            ZTest Off  
            Cull Off  
  
            CGPROGRAM  
  
            //指定此通道的顶点着色器为vert_DownSmpl  
            #pragma vertex vert_DownSmpl  
            //指定此通道的像素着色器为frag_DownSmpl  
            #pragma fragment frag_DownSmpl  
  
            ENDCG  
  
        }  
  
        //---------------------------------------【通道1 || Pass 1】------------------------------------  
        //通道1:垂直方向模糊处理通道 ||Pass 1: Vertical Pass  
        Pass  
        {  
            ZTest Always  
            Cull Off  
  
            CGPROGRAM  
  
            //指定此通道的顶点着色器为vert_BlurVertical  
            #pragma vertex vert_BlurVertical  
            //指定此通道的像素着色器为frag_Blur  
            #pragma fragment frag_Blur  
  
            ENDCG  
        }  
  
        //---------------------------------------【通道2 || Pass 2】------------------------------------  
        //通道2:水平方向模糊处理通道 ||Pass 2: Horizontal Pass  
        Pass  
        {  
            ZTest Always  
            Cull Off  
  
            CGPROGRAM  
  
            //指定此通道的顶点着色器为vert_BlurHorizontal  
            #pragma vertex vert_BlurHorizontal  
            //指定此通道的像素着色器为frag_Blur  
            #pragma fragment frag_Blur  
  
            ENDCG  
        }  
    }  
  
  
    //-------------------------CG着色语言声明部分 || Begin CG Include Part----------------------    
    CGINCLUDE  
  
    //【1】头文件包含 || include  
    #include "UnityCG.cginc"  
  
    //【2】变量声明 || Variable Declaration  
    sampler2D _MainTex;  
    //UnityCG.cginc中内置的变量,纹理中的单像素尺寸|| it is the size of a texel of the texture  
    uniform half4 _MainTex_TexelSize;  
    //C#脚本控制的变量 || Parameter  
    uniform half _DownSampleValue;  
  
    //【3】顶点输入结构体 || Vertex Input Struct  
    struct VertexInput  
    {  
        //顶点位置坐标  
        float4 vertex : POSITION;  
        //一级纹理坐标  
        half2 texcoord : TEXCOORD0;  
    };  
  
    //【4】降采样输出结构体 || Vertex Input Struct  
    struct VertexOutput_DownSmpl  
    {  
        //像素位置坐标  
        float4 pos : SV_POSITION;  
        //一级纹理坐标(右上)  
        half2 uv20 : TEXCOORD0;  
        //二级纹理坐标(左下)  
        half2 uv21 : TEXCOORD1;  
        //三级纹理坐标(右下)  
        half2 uv22 : TEXCOORD2;  
        //四级纹理坐标(左上)  
        half2 uv23 : TEXCOORD3;  
    };  
  
  
    //【5】准备高斯模糊权重矩阵参数7x4的矩阵 ||  Gauss Weight  
    static const half4 GaussWeight[7] =  
    {  
        half4(0.0205,0.0205,0.0205,0),  
        half4(0.0855,0.0855,0.0855,0),  
        half4(0.232,0.232,0.232,0),  
        half4(0.324,0.324,0.324,1),  
        half4(0.232,0.232,0.232,0),  
        half4(0.0855,0.0855,0.0855,0),  
        half4(0.0205,0.0205,0.0205,0)  
    };  
  
  
    //【6】顶点着色函数 || Vertex Shader Function  
    VertexOutput_DownSmpl vert_DownSmpl(VertexInput v)  
    {  
        //【6.1】实例化一个降采样输出结构  
        VertexOutput_DownSmpl o;  
  
        //【6.2】填充输出结构  
        //将三维空间中的坐标投影到二维窗口    
        o.pos = UnityObjectToClipPos(v.vertex);  
        //对图像的降采样:取像素上下左右周围的点,分别存于四级纹理坐标中  
        o.uv20 = v.texcoord + _MainTex_TexelSize.xy* half2(0.5h, 0.5h);;  
        o.uv21 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h, -0.5h);  
        o.uv22 = v.texcoord + _MainTex_TexelSize.xy * half2(0.5h, -0.5h);  
        o.uv23 = v.texcoord + _MainTex_TexelSize.xy * half2(-0.5h, 0.5h);  
  
        //【6.3】返回最终的输出结果  
        return o;  
    }  
  
    //【7】片段着色函数 || Fragment Shader Function  
    fixed4 frag_DownSmpl(VertexOutput_DownSmpl i) : SV_Target  
    {  
        //【7.1】定义一个临时的颜色值  
        fixed4 color = (0,0,0,0);  
  
        //【7.2】四个相邻像素点处的纹理值相加  
        color += tex2D(_MainTex, i.uv20);  
        color += tex2D(_MainTex, i.uv21);  
        color += tex2D(_MainTex, i.uv22);  
        color += tex2D(_MainTex, i.uv23);  
  
        //【7.3】返回最终的平均值  
        return color / 4;  
    }  
  
    //【8】顶点输入结构体 || Vertex Input Struct  
    struct VertexOutput_Blur  
    {  
        //像素坐标  
        float4 pos : SV_POSITION;  
        //一级纹理(纹理坐标)  
        half4 uv : TEXCOORD0;  
        //二级纹理(偏移量)  
        half2 offset : TEXCOORD1;  
    };  
  
    //【9】顶点着色函数 || Vertex Shader Function  
    VertexOutput_Blur vert_BlurHorizontal(VertexInput v)  
    {  
        //【9.1】实例化一个输出结构  
        VertexOutput_Blur o;  
  
        //【9.2】填充输出结构  
        //将三维空间中的坐标投影到二维窗口    
        o.pos = UnityObjectToClipPos(v.vertex);  
        //纹理坐标  
        o.uv = half4(v.texcoord.xy, 1, 1);  
        //计算X方向的偏移量  
        o.offset = _MainTex_TexelSize.xy * half2(1.0, 0.0) * _DownSampleValue;  
  
        //【9.3】返回最终的输出结果  
        return o;  
    }  
  
    //【10】顶点着色函数 || Vertex Shader Function  
    VertexOutput_Blur vert_BlurVertical(VertexInput v)  
    {  
        //【10.1】实例化一个输出结构  
        VertexOutput_Blur o;  
  
        //【10.2】填充输出结构  
        //将三维空间中的坐标投影到二维窗口    
        o.pos = UnityObjectToClipPos(v.vertex);  
        //纹理坐标  
        o.uv = half4(v.texcoord.xy, 1, 1);  
        //计算Y方向的偏移量  
        o.offset = _MainTex_TexelSize.xy * half2(0.0, 1.0) * _DownSampleValue;  
  
        //【10.3】返回最终的输出结果  
        return o;  
    }  
  
    //【11】片段着色函数 || Fragment Shader Function  
    half4 frag_Blur(VertexOutput_Blur i) : SV_Target  
    {  
        //【11.1】获取原始的uv坐标  
        half2 uv = i.uv.xy;  
  
        //【11.2】获取偏移量  
        half2 OffsetWidth = i.offset;  
        //从中心点偏移3个间隔,从最左或最上开始加权累加  
        half2 uv_withOffset = uv - OffsetWidth * 3.0;  
  
        //【11.3】循环获取加权后的颜色值  
        half4 color = 0;  
        for (int j = 0; j< 7; j++)  
        {  
            //偏移后的像素纹理值  
            half4 texCol = tex2D(_MainTex, uv_withOffset);  
            //待输出颜色值+=偏移后的像素纹理值 x 高斯权重  
            color += texCol * GaussWeight[j];  
            //移到下一个像素处,准备下一次循环加权  
            uv_withOffset += OffsetWidth;  
        }  
  
        //【11.4】返回最终的颜色值  
        return color;  
    }  
  
    //-------------------结束CG着色语言声明部分  || End CG Programming Part------------------               
    ENDCG  
  
    FallBack Off  

}


c#代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


//设置在编辑模式下也执行该脚本  
[ExecuteInEditMode]
//添加选项到菜单中  
[AddComponentMenu("Unlit/DoFShader")]  
public class MyDepthOfField : MonoBehaviour {


//-------------------变量声明部分-------------------  
#region Variables


//指定Shader名称  
private string ShaderName = "Unlit/DoFShader";


//着色器和材质实例  
public Shader CurShader;
private Material CurMaterial;


//几个用于调节参数的中间变量  
public static int ChangeValue;
public static float ChangeValue2;
public static int ChangeValue3;


//降采样次数  
[Range(0, 6), Tooltip("[降采样次数]向下采样的次数。此值越大,则采样间隔越大,需要处理的像素点越少,运行速度越快。")]
public int DownSampleNum = 2;
//模糊扩散度  
[Range(0.0f, 20.0f), Tooltip("[模糊扩散度]进行高斯模糊时,相邻像素点的间隔。此值越大相邻像素间隔越远,图像越模糊。但过大的值会导致失真。")]
public float BlurSpreadSize = 3.0f;
//迭代次数  
[Range(0, 8), Tooltip("[迭代次数]此值越大,则模糊操作的迭代次数越多,模糊效果越好,但消耗越大。")]
public int BlurIterations = 3;


#endregion


//-------------------------材质的get&set----------------------------  
#region MaterialGetAndSet
Material material
{
get
{
if (CurMaterial == null)
{
CurMaterial = new Material(CurShader);
CurMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return CurMaterial;
}
}
#endregion


#region Functions
//-----------------------------------------【Start()函数】---------------------------------------------    
// 说明:此函数仅在Update函数第一次被调用前被调用  
//--------------------------------------------------------------------------------------------------------  
void Start()
{
//依次赋值  
ChangeValue = DownSampleNum;
ChangeValue2 = BlurSpreadSize;
ChangeValue3 = BlurIterations;


//找到当前的Shader文件  
CurShader = Shader.Find(ShaderName);


//判断当前设备是否支持屏幕特效  
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
}


//-------------------------------------【OnRenderImage()函数】------------------------------------    
// 说明:此函数在当完成所有渲染图片后被调用,用来渲染图片后期效果  
//--------------------------------------------------------------------------------------------------------  
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
//着色器实例不为空,就进行参数设置  
if (CurShader != null)
{
//【0】参数准备  
//根据向下采样的次数确定宽度系数。用于控制降采样后相邻像素的间隔  
float widthMod = 1.0f / (1.0f * (1 << DownSampleNum));
//Shader的降采样参数赋值  
material.SetFloat("_DownSampleValue", BlurSpreadSize * widthMod);
//设置渲染模式:双线性  
sourceTexture.filterMode = FilterMode.Bilinear;
//通过右移,准备长、宽参数值  
int renderWidth = sourceTexture.width >> DownSampleNum;
int renderHeight = sourceTexture.height >> DownSampleNum;


// 【1】处理Shader的通道0,用于降采样 ||Pass 0,for down sample  
//准备一个缓存renderBuffer,用于准备存放最终数据  
RenderTexture renderBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
//设置渲染模式:双线性  
renderBuffer.filterMode = FilterMode.Bilinear;
//拷贝sourceTexture中的渲染数据到renderBuffer,并仅绘制指定的pass0的纹理数据  
Graphics.Blit(sourceTexture, renderBuffer, material, 0);


//【2】根据BlurIterations(迭代次数),来进行指定次数的迭代操作  
for (int i = 0; i < BlurIterations; i++)
{
//【2.1】Shader参数赋值  
//迭代偏移量参数  
float iterationOffs = (i * 1.0f);
//Shader的降采样参数赋值  
material.SetFloat("_DownSampleValue", BlurSpreadSize * widthMod + iterationOffs);


// 【2.2】处理Shader的通道1,垂直方向模糊处理 || Pass1,for vertical blur  
// 定义一个临时渲染的缓存tempBuffer  
RenderTexture tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
// 拷贝renderBuffer中的渲染数据到tempBuffer,并仅绘制指定的pass1的纹理数据  
Graphics.Blit(renderBuffer, tempBuffer, material, 1);
//  清空renderBuffer  
RenderTexture.ReleaseTemporary(renderBuffer);
// 将tempBuffer赋给renderBuffer,此时renderBuffer里面pass0和pass1的数据已经准备好  
renderBuffer = tempBuffer;


// 【2.3】处理Shader的通道2,竖直方向模糊处理 || Pass2,for horizontal blur  
// 获取临时渲染纹理  
tempBuffer = RenderTexture.GetTemporary(renderWidth, renderHeight, 0, sourceTexture.format);
// 拷贝renderBuffer中的渲染数据到tempBuffer,并仅绘制指定的pass2的纹理数据  
Graphics.Blit(renderBuffer, tempBuffer, CurMaterial, 2);


//【2.4】得到pass0、pass1和pass2的数据都已经准备好的renderBuffer  
// 再次清空renderBuffer  
RenderTexture.ReleaseTemporary(renderBuffer);
// 再次将tempBuffer赋给renderBuffer,此时renderBuffer里面pass0、pass1和pass2的数据都已经准备好  
renderBuffer = tempBuffer;
}


//拷贝最终的renderBuffer到目标纹理,并绘制所有通道的纹理到屏幕  
Graphics.Blit(renderBuffer, destTexture);
//清空renderBuffer  
RenderTexture.ReleaseTemporary(renderBuffer);


}


//着色器实例为空,直接拷贝屏幕上的效果。此情况下是没有实现屏幕特效的  
else
{
//直接拷贝源纹理到目标渲染纹理  
Graphics.Blit(sourceTexture, destTexture);
}
}




//-----------------------------------------【OnValidate()函数】--------------------------------------    
// 说明:此函数在编辑器中该脚本的某个值发生了改变后被调用  
//--------------------------------------------------------------------------------------------------------  
void OnValidate()
{
//将编辑器中的值赋值回来,确保在编辑器中值的改变立刻让结果生效  
ChangeValue = DownSampleNum;
ChangeValue2 = BlurSpreadSize;
ChangeValue3 = BlurIterations;
}


//-----------------------------------------【Update()函数】--------------------------------------    
// 说明:此函数每帧都会被调用  
//--------------------------------------------------------------------------------------------------------  
void Update()
{
//若程序在运行,进行赋值  
if (Application.isPlaying)
{
//赋值  
DownSampleNum = ChangeValue;
BlurSpreadSize = ChangeValue2;
BlurIterations = ChangeValue3;
}
//若程序没有在运行,去寻找对应的Shader文件  
#if UNITY_EDITOR
if (Application.isPlaying != true)
{
CurShader = Shader.Find(ShaderName);
}
#endif


}


//-----------------------------------------【OnDisable()函数】---------------------------------------    
// 说明:当对象变为不可用或非激活状态时此函数便被调用    
//--------------------------------------------------------------------------------------------------------  
void OnDisable()
{
if (CurMaterial)
{
//立即销毁材质实例  
DestroyImmediate(CurMaterial);
}


}


#endregion  

}


效果图



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_18638761/article/details/79472124

智能推荐

go上传文件-程序员宅基地

文章浏览阅读102次。【代码】go上传文件。

【转】目前常用AD/DA芯片简介_分辨率0.5的ad芯片-程序员宅基地

文章浏览阅读2.9k次。_分辨率0.5的ad芯片

一个简单的dw网页制作作业,学生个人html静态网页制作成品代码——怪盗基德动漫主题网页成品(15页)_dw简单网页制作成品-程序员宅基地

文章浏览阅读6.9k次,点赞6次,收藏57次。精彩专栏推荐 【作者主页——获取更多优质源码】 【web前端期末大作业——毕设项目精品实战案例(1000套)】1 网页简介:此作品为学生个人主页网页设计题材,HTML+CSS 布局制作,web前端期末大作业,大学生网页设计作业源码,这是一个不错的网页制作,画面精明,代码为简单学生水平, 非常适合初学者学习使用。2.网页编辑:网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Web..._dw简单网页制作成品

Android TBS X5内核 64位手机无法加载x5(libmttwebview.so is 32-bit instead of 64-bit)_libmtttrace.so-程序员宅基地

文章浏览阅读3k次。前言这个问题之前出现过但是稀里糊涂的解决了 没有记录详细的解决方案今天又碰到了 自己研究了一天刚刚找到解决方案错误提示dlopen failed: "/system/app/googlewebview85/lib/arm/libwebviewchromium.so“ is 32-bit instead of 64在使用tbs x5内核时 一直崩溃说没有64位的.so包腾讯官方TBS的文档也有这方面的知识点 但是没有解决方案需要靠自己摸索 你说气人不?新版本SDK已支持64位,请更新至官网_libmtttrace.so

java玫瑰花代码_java程序员不一样浪漫,表白玫瑰花送给你的那个她-程序员宅基地

文章浏览阅读3k次。原标题:java程序员不一样浪漫,表白玫瑰花送给你的那个她这篇文章主要讲解了Java版给爱人表白的玫瑰花程序代码,具有很好的参考价值,希望对大家有所帮助,一起跟随小编过来看看吧 小编推荐一个学Java的学习裙【二零二,二五零,一九四】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有很多干货和技术分享!1 书写表白语句的frame(渐入功能)?1234567891011..._java玫瑰花代码

Hibernate(映射继承关系、 Hibernate 检索策略、Hibernate 检索方式HQL (迫切)左外连接HQL (迫切)内连接QBC 检索和本地 SQL 检索二级缓存,管理session_hql 非空约束-程序员宅基地

文章浏览阅读203次。上一篇映射继承关系Hibernate支持三种继承映射策略:使用 subclass 进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。使用 joined-subclass 进行映射: 对于继承关系中的子类使用同一个表,这就需要在数据库表中增加额外的区分子类类型的字段。使用 union-subclass 进行映射:域模型中的每个类映射到一个表,通过关系数据模型中的外键来描述表之间的继承关系。这也就相当于按照域模型的结构来建立数据库中的_hql 非空约束

随便推点

成为JavaGC专家Part II:如何监控Java垃圾回收机制-程序员宅基地

文章浏览阅读215次。 成为JavaGC专家Part II :如何监控Java垃圾回收机制 本文是成为Java GC专家系列文章的第二篇。在第一篇《深入浅出Java垃圾回收机制》中我们学习了不同GC算法的执行过程,GC是如何工作的,什么是新生代和老年代,你应该了解的JDK7中的5种GC类型,以及这5种类型对于应用性能的影响。 在本文中,我将解释JVM到底是如何执行垃圾回收处理..._成为javagc专家part ii — 如何监控java垃圾回收机制。

python学习导航线_python点线导航-程序员宅基地

文章浏览阅读122次。文章目录python学习导航线一、seleniumpython-selenium二、python基础知识python的聊天室python学习导航线一、seleniumpython-selenium二、python基础知识python的聊天室_python点线导航

静态成员-静态成员变量-程序员宅基地

文章浏览阅读3.4k次,点赞4次,收藏22次。静态成员静态成员都是用static修饰,它的特点是不论创建多少个对象,程序都只创建一个静态成员。最主要的特点:共享什么是共享呢?例如:统计超市中所有商品数量的总和,商品数量的总和是随着每一个数量的变化而变化的,这是我们就可以用静态成员处理。(代码下面有写)静态成员又分为静态成员变量和静态成员函数。(一)静态成员变量特点:1、所有对象共享一份数据。 2、在编译阶段分配内存。 3、类内声明,类外初始化。#include<io..._静态成员变量

HTML5七夕情人节表白网页制作【情人节满屏爱心HTML5特效】HTML+CSS+JavaScript html生日快乐祝福网页制作_html 满屏爱心-程序员宅基地

文章浏览阅读879次,点赞21次,收藏20次。1 网页简介:基于HTML+CSS+JavaScript 制作七夕情人节表白网页、生日祝福、七夕告白、 求婚、浪漫爱情3D相册、炫酷代码,快来制作一款高端的表白网页送(他/她)浪漫的告白,制作修改简单,可自行更换背景音乐,文字和图片即可使用等任意html编辑软件进行运行及修改编辑等操作)。_html 满屏爱心

【易飞】易飞ERP自动审核程序功能_易飞单据审批设置-程序员宅基地

文章浏览阅读492次,点赞9次,收藏5次。【代码】【易飞】易飞ERP自动审核程序功能。_易飞单据审批设置

青少年CTF擂台挑战赛 2024 #Round 1_xyctf高校新生联合赛 2024-程序员宅基地

文章浏览阅读1.6k次,点赞15次,收藏30次。文件打开是一个print数组v4的地址和read函数,并且nx好像可写,输入长度可以利用,进行一个栈上写好自己的shell,然后在构造一个回到v4的地址,这样子就可以重新读取到写buf段上的shell,这里要注意shell的隔断用/00截断然后构造好栈上数据。一个sql注入题目,尝试使用二分查找,但只能爆出表名和列名,值一直出不来,后来采用布尔盲注,fuzz测试后发现没有加任何过滤,直接写脚本。第二题:为了求解方程 (5 + sqrt{x} = 8),我们可以分离平方根项,然后求解 (x)。_xyctf高校新生联合赛 2024

推荐文章

热门文章

相关标签