回到目录

大家好,我是阿赵。这次来说一下URP渲染管线里面怎样使用后处理效果,还有怎样去自定义后处理效果。

一、使用URP自带的后处理效果

要使用URP自带的后处理效果,方法很简单,和Unity内置渲染管线的PostProcessing后处理很类似的,在一个物体上面添加一个Volume脚本。

这个脚本的整体用法和PostProcessing Volume非常的像,首先它可以选择是Global还是Local,如果选择Global,那么所有摄像机都可以生效。如果勾选了Local,还会出现距离的选项,和添加碰撞体的选项,这时候可以根据范围来控制哪些摄像机接受到后处理的效果。
然后是Priority选项,如果场景里面同时存在多个Volume,那么以Priority值大的那个Volume作为优先显示。
最后是Profile,可以创建一个后处理文件来编辑效果。
在创建和指定了后处理文件之后,就可以添加效果了,点击Add Override,然后选择Post-processing,可以看到很多熟悉的内置后处理效果。
这里我们添加一个Bloom,并且随便调一下参数

然后去摄像机的属性面板里面,把Post Processing选项勾上

这时候可以看到,Bloom后处理生效了,场景有了发光的效果。
自带的后处理效果使用很简单,不是我们这次讨论的重点。

二、自定义后处理效果

URP代码里面已经自带了很多后处理效果,但有时候我们还是想做一些特殊的效果。比如我这里想做一个把画面转成线稿的风格化后处理效果。

接下来我就以这个效果为例子,说明一下在URP里面怎么自定义后处理效果。

1、写一个Shader

首先,我要写一个可以把图片变成线条风格化效果的Shader。
注意一下,这里面我暴露了4个参数
1._MainTex
_MainTex是主贴图,这个命名不要改,因为等一下做后处理的时候,_MainTex是固定作为屏幕画面而输入的。
2.lineStrength
lineStrength是线条的强度,值越大,线条就越粗越明显
3._lineColor
_lineColor是线条的颜色,可以通过这个值来改变线条的颜色
4.baseColor
baseColor是背景的颜色,背景不一定是白色,可以根据需要改成别的颜色
通过调整各种参数,我们可以得到这样的效果

这个例子里面,这个shader我们需要留意的就是这个几个参数而已,后面会需要对他们进行控制。至于这个Shader的实现原理,不是这篇文章需要探讨的内容,如果大家有兴趣可以留意,我可以介绍一下。反正Shader也很简单,各位估计自己也能看得懂。
完整Shader:

Shader "azhao/LineStyle"
{Properties{_MainTex ("Texture", 2D) = "white" {}_lineStrength("lineStrength", Float) = 1.0_lineColor("lineColor", Color) = (0,0,0,0)_baseColor("baseColor", Color) = (1,1,1,0)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{HLSLPROGRAM#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 pos : SV_POSITION;};CBUFFER_START(UnityPerMaterial)float4 _baseColor;float4 _MainTex_ST;float _lineStrength;float4 _lineColor;CBUFFER_ENDTEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);v2f vert (appdata v){v2f o;VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);o.pos = vertexInput.positionCS;o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}half4 frag (v2f i) : SV_Target{// sample the texturehalf4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, i.uv);float grayscale  = col.r * 0.2126729f + col.g * 0.7151522f + col.b * 0.0721750f;float ddVal = (saturate(ddx(grayscale) + ddy(grayscale))*_lineStrength);half3 finalCol = _baseColor.rgb * (1.0 - ddVal) + _lineColor.rgb * ddVal;return half4(finalCol,1);}ENDHLSL}}
}

2、新增VolumeComponent

这一步,我们需要把这个效果作为选项,显示在后处理的Volume的添加列表里面。
新建一个C#脚本,然后输入这些内容:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
[System.Serializable, VolumeComponentMenu("azhao/LineStyle")]
public class LineStyle : VolumeComponent
{public BoolParameter isShow = new BoolParameter(false, true);[Tooltip("Strength of the line.")]public MinFloatParameter lineStrength = new MinFloatParameter(1, 0,true);[Tooltip("The color of the line.")]public ColorParameter lineColor = new ColorParameter(Color.black, true);[Tooltip("The color of the background.")]public ColorParameter baseColor = new ColorParameter(Color.white, true);
}

这时候,就能看到选项了

分析一下需要注意的地方:

1.指定效果的名字

[System.Serializable, VolumeComponentMenu("azhao/LineStyle")]

通过VolumeComponentMenu,可以指定我们选择效果时的名字,比如这里我把这个效果命名为LineStyle,并放在azhao的目录里面

2.继承VolumeComponent

必须继承VolumeComponent,这个选项才能显示在Volume的添加选项里面

3.定义参数

这里我用到了这么几种参数类型:
BoolParameter 、MinFloatParameter 、ColorParameter 。
从字面意思就可以看出来
BoolParameter 是布尔型的参数
MinFloatParameter 是浮点型的参数,但它可以指定一个最小值,输入的值不能小于最小值
ColorParameter 是颜色类型的参数
我们能用的参数类型非常的多,本来想全部列出来的,但实在是太多了,可以看源码的VolumeParameter.cs,里面有各种参数类型的说明。

4.给参数加Tips

通过Tooltip标签可以给参数做tips显示

5.额外说明

可以看得出,这里的几个参数,都是对应着LineStyle这个Shader的暴露参数的,除了一个布尔类型的isShow 。这个问题这里先忽略,这个isShow 并不是必要的,而是我为了解决另外一个问题而加的。后面会有说明。

3、新增ScriptableRenderPass

在上面那一步在Volume里面添加了自己的效果之后,发现并没有生效。这是因为,自定义的后处理,其实是作为一种Feature来使用的,就和前一篇文章介绍的描边实现方式类似。
不过之前的Features是把指定的模型渲染的时候增加一个Pass,但后处理针对的不是每个模型,而是整个屏幕的画面。
这里分成2步,一个是指定一个处理画面的Pass,另外一个是指定一个自定义Feature用于添加到Features。
先说第一步,增加一个ScriptableRenderPass
创建一个C#脚本,然后输入下面的内容

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;public class LineStylePass : ScriptableRenderPass
{static readonly string renderTag = "LineStyle Effects";static readonly int MainTexId = Shader.PropertyToID("_MainTex");static readonly int TempTargetId = Shader.PropertyToID("_TempTargetColorTint");private LineStyle lineStyleVolume;private Material mat;RenderTargetIdentifier currentTarget;public LineStylePass(RenderPassEvent passEvent,Shader lineStyleShader){renderPassEvent = passEvent;if(lineStyleShader == null){Debug.LogError("Shader不存在");return;}mat = CoreUtils.CreateEngineMaterial(lineStyleShader);}public void Setup(in RenderTargetIdentifier currentTarget){this.currentTarget = currentTarget;}public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){if(mat == null){return;}if(!renderingData.cameraData.postProcessEnabled){return;}VolumeStack stack = VolumeManager.instance.stack;lineStyleVolume = stack.GetComponent<LineStyle>();if(lineStyleVolume == null){return;}if (lineStyleVolume.isShow.value == false){return;}CommandBuffer cmd = CommandBufferPool.Get(renderTag);Render(cmd, ref renderingData);context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}private void Render(CommandBuffer cmd,ref RenderingData renderingData){ref CameraData cameraData = ref renderingData.cameraData;Camera camera = cameraData.camera;RenderTargetIdentifier source = currentTarget;int destination = TempTargetId;mat.SetFloat("_lineStrength", lineStyleVolume.lineStrength.value);mat.SetColor("_lineColor", lineStyleVolume.lineColor.value);mat.SetColor("_baseColor", lineStyleVolume.baseColor.value);cmd.SetGlobalTexture(MainTexId, source);cmd.GetTemporaryRT(destination, cameraData.camera.scaledPixelWidth, cameraData.camera.scaledPixelHeight, 0, FilterMode.Trilinear, RenderTextureFormat.Default);cmd.Blit(source, destination);cmd.Blit(destination, source, mat, 0);}
}

从上面的代码可以看出,这个Pass分成了以下的步骤:
1、指定输入输出的贴图

static readonly string renderTag = "LineStyle Effects";
static readonly int MainTexId = Shader.PropertyToID("_MainTex");
static readonly int TempTargetId = Shader.PropertyToID("_TempTargetColorTint");

刚才在写shader的时候,说过主贴图_MainTex的名字不要改,就是因为这一步需要指定一个输入的主贴图。当然,也可以改,和这里对应就可以了

2、构造函数

 public LineStylePass(RenderPassEvent passEvent,Shader lineStyleShader){renderPassEvent = passEvent;if(lineStyleShader == null){Debug.LogError("Shader不存在");return;}mat = CoreUtils.CreateEngineMaterial(lineStyleShader);}

这个会在外部输入,根据自己的需要编写。比如这里我需要知道的是,RenderPass的事件类型,还有需要用哪个shader进行渲染。所以构造函数就包含了这两个参数。如果这两个参数直接写死在代码里面,那么也就不需要传入这两个参数了。然后这里我顺便创建了用于渲染的材质。

3、初始化

 public void Setup(in RenderTargetIdentifier currentTarget){this.currentTarget = currentTarget;
}

这里也是根据自己的需要来定,由于我这里只需要一个渲染输出的目标,所以外部只传入了这个参数。

4、执行
这是一个重写父类的方法,在收到渲染事件的时候,会自己执行。
写在这一部分的方法,首先是做一些过滤,在特定的条件下不需要执行这个Pass的渲染。
当条件全部都满足的时候,就获取CommandBuffer ,并调用渲染方法,最后释放CommandBuffer 。

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){if(mat == null){return;}if(!renderingData.cameraData.postProcessEnabled){return;}VolumeStack stack = VolumeManager.instance.stack;lineStyleVolume = stack.GetComponent<LineStyle>();if(lineStyleVolume == null){return;}if (lineStyleVolume.isShow.value == false){return;}CommandBuffer cmd = CommandBufferPool.Get(renderTag);Render(cmd, ref renderingData);context.ExecuteCommandBuffer(cmd);CommandBufferPool.Release(cmd);}

这里有个很特殊的地方,就是我之前在VolumeComponent里面添加了一个不在shader里面用到的布尔参数isShow。为什么要添加这个参数呢?原因是,当我们真的添加了Features之后,实际上不管我们是否在场景里面添加Volume,这个后处理的Execute方法都会被执行的。区别在于,如果场景里面没有被激活的对应后处理的Volume,那么这里获取到的VolumeStack 对应的参数都是默认值。所以我在VolumeComponent里面加了一个isShow的变量,默认是false的,当场景里面没有Volume的时候,我就可以通过默认值,让Execute停在这一步,不要再走下面的渲染。
这可以说是一个取巧的办法吧,说不定还有其他的方法可以控制,希望各位可以告诉我。

5、渲染

private void Render(CommandBuffer cmd,ref RenderingData renderingData){ref CameraData cameraData = ref renderingData.cameraData;Camera camera = cameraData.camera;RenderTargetIdentifier source = currentTarget;int destination = TempTargetId;mat.SetFloat("_lineStrength", lineStyleVolume.lineStrength.value);mat.SetColor("_lineColor", lineStyleVolume.lineColor.value);mat.SetColor("_baseColor", lineStyleVolume.baseColor.value);cmd.SetGlobalTexture(MainTexId, source);cmd.GetTemporaryRT(destination, cameraData.camera.scaledPixelWidth, cameraData.camera.scaledPixelHeight, 0, FilterMode.Trilinear, RenderTextureFormat.Default);cmd.Blit(source, destination);cmd.Blit(destination, source, mat, 0);}
}

这一步,和传统的内置渲染管线的后处理写法是一样的,这一步里面把lineStyleVolume里面的参数设置给需要渲染的材质球,然后通过CommandBuffer.Blit方法,指定输入和输出贴图,需要渲染的材质,来得到渲染后的结果。
如果熟悉传统内置渲染管线的后处理写法,这一步倒是没什么好说的了。
如果想看看内置效果是怎样实现的,可以去看看源码:PostProcessPass.cs

4、新增ScriptableRendererFeature

有了执行实际渲染的ScriptableRenderPass后, 接下来就是要把这个Pass用上了。
创建一个C#脚本,然后输入以下内容。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.Universal;public class LineStyleRendererFeature : ScriptableRendererFeature
{[System.Serializable]public class Settings{public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;public Shader shader;}public Settings settings = new Settings();LineStylePass pass;public override void Create(){this.name = "LineStylePass";pass = new LineStylePass(RenderPassEvent.BeforeRenderingPostProcessing, settings.shader);}public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){pass.Setup(renderer.cameraColorTarget);renderer.EnqueuePass(pass);}
}

需要注意的地方:
1.Settings是显示在添加的Features里面的选项内容,一定要加上[System.Serializable],不然不会显示出来
2.在Create方法里面可以指定自己显示的名字,并且把Pass创建出来
3.AddRenderPasses方法里面,对pass进行初始化,并且假如到渲染的队列里面。

5、设置Feature

在完成了上面的步骤后,可以看到添加Features的地方,出现了我们自己定义的Feature了

添加之后,指定一下需要渲染的Shader。

添加完Features,然后添加Volume指定的效果,调整一下参数,最后在摄像机里面勾选Post processing,效果就出来了。到这里,这个例子就全部做完了,可以看到屏幕里面所有画面都变成了线条风格化了。

URP自定义屏幕后处理相关推荐

  1. Unity URP管线设置 后处理的使用

    Unity推出通用渲染管线和高清渲染管线有很长一段时间了,但是感觉使用度上不是很高,很多人不愿意尝试新的渲染管线. 我在最开始使用Unity做可视化大屏的时候,也是选择的默认渲染管线,主要是Asset ...

  2. python 描边_在URP实现局部后处理描边

    欢迎参与讨论,转载请注明出处. 前言 最近在Demo开发的过程中,遇到了一个细节问题,场景模型之间的边界感很弱: 这样就会导致玩家难以分辨接下来面对的究竟是可以跳下去的台阶,亦或是要跳过去的台阶了.我 ...

  3. Android 模拟机自定义屏幕的尺寸

    有时候我们在做车载,或者类似电视屏幕的时候就需要自定义屏幕尺寸了,首页需要算出屏幕宽和高,然后在算出对角线多少寸, 这里就不说了,说下创建. 1 点击图中选中的图标 2 点击创建 3 点击New Ha ...

  4. 屏幕后处理——Bloom

    来自于<Unity Shader 入门精要>书本的学习 先上图 代码分3部分 1.PostEffectsBase.cs using System.Collections; using Sy ...

  5. 注销凭证与自定义屏幕

    注意注销凭证FB03    (事务代码SHDB) 自定义屏幕的功能代码与标准程序要对应一致 REPORT ZWGX006. TABLES BKPF. DATA OK_CODE TYPE OKCODE. ...

  6. UnityShader24:最简单的屏幕后处理例子

    一.需要提前了解的 其实关于屏幕后处理(Screen Post-processing Effects)相关的知识,前面已经提过了不少: 这些是 OpenGL 渲染部分: OpenGL基础35:帧缓冲( ...

  7. windows自定义屏幕大小,分辨率大小,自定义电脑屏幕分辨率

    windows 用于自定义屏幕分辨率大小: 桌面新建个txt文件: 第一个:full_screen.bat    (注意后缀改为bat(删除txt)) 打开后(记事本方式打开)写如下代码: " ...

  8. UnityShader入门精要-屏幕后处理效果 亮度饱和度对比度、边缘检测、高斯模糊、bloom效果、运动模糊

    (从这里开始可能会记录的更简略一些,时间紧张想迅速读完这本书的主要内容,可能有的部分不会自己上手做) 屏幕后处理通常指渲染完整个场景得到屏幕图像后,再对图像进行操作,抓取屏幕可以使用OnRenderI ...

  9. Unity Shader入门学习(5):基础屏幕后处理

    1.后处理基类 //屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效. //基类的作用有二:检测平台是否支持后处理效果,及创建一个用于处理渲 ...

最新文章

  1. Silverlight Blend动画设计系列五:故事板(StoryBoards)和动画(Animations)
  2. Java微信公众平台开发(二)--微信服务器post消息体的接收
  3. Android GridView LruCache
  4. 微软人工智能和对话平台--知识商城体验
  5. cfilefind 能找ftp 服务器上的文件夹吗?,将ftp目录映射为本地盘符
  6. 《Greenplum5.0 最佳实践》 内存与资源队列 (四)
  7. Win7 Tortoise SVN安装异常--please install the universal crt first.You can .. windows-update(Kb2999226)
  8. WinRunner:强大的企业级自动化测试工具
  9. cocosBuilder使用总结
  10. 【从零写javaweb框架】(零)前言
  11. deepin安装nginx服务器
  12. Skyline三维地理信息系统软件平台
  13. 华为薪资等级结构表_2019年华为新员工薪酬 华为薪酬等级工资表
  14. 【蓝桥杯】大臣的旅费
  15. 投影仪怎么安装才能得到最大的屏幕?学会这个投影距离公式轻松拿捏
  16. 哈工大计算机科学与技术硕士培养方案,计算机科学与技术学科硕士研究生培养方案哈工大计算机学院[文].pdf...
  17. [C题目]输入整数a和n,计算a+aa+aaa+aaaa+......(共有n项)
  18. 做一个功能比较齐全的小程序商城选择好的系统很重要
  19. Linux C语言实现TCP客户端与服务器
  20. PCIe物理层详细总结-PCIe专题知识(一)

热门文章

  1. 用python控制钉钉软件_Python实现钉钉消息推送
  2. 如何打造云端新零售数字化平台?
  3. 使用正则表达式搜索文本文件
  4. 学习 Linux,101: 使用正则表达式搜索文本文件
  5. 算法学习笔记16:递归树
  6. 新媒体运营面试必问5大问题(内附试题)
  7. delphi XE关于微信公众号支付及微信零钱支付的便捷解决方案
  8. MAC地址与IP地址详解
  9. 膜片钳电生理检测ACSF和电极内液配制
  10. 分享3个免费的AI课程