8、URP自定义屏幕后处理

这篇具有很好参考价值的文章主要介绍了8、URP自定义屏幕后处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

回到目录

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

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

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

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

然后去摄像机的属性面板里面,把Post Processing选项勾上
8、URP自定义屏幕后处理

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

二、自定义后处理效果

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

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

1、写一个Shader

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

这个例子里面,这个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 100

        Pass
        {
            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_END
			TEXTURE2D(_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 texture
				half4 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);
}

这时候,就能看到选项了
8、URP自定义屏幕后处理

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

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显示
8、URP自定义屏幕后处理

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了
8、URP自定义屏幕后处理
8、URP自定义屏幕后处理

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

添加完Features,然后添加Volume指定的效果,调整一下参数,最后在摄像机里面勾选Post processing,效果就出来了。到这里,这个例子就全部做完了,可以看到屏幕里面所有画面都变成了线条风格化了。
8、URP自定义屏幕后处理
8、URP自定义屏幕后处理文章来源地址https://www.toymoban.com/news/detail-459287.html

到了这里,关于8、URP自定义屏幕后处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 《Unity的URP项目中使用自定义shader导致材质消失的解决办法》

            在Unity中使用URP时,会有需求使用自定义的一些shader来实现特殊效果,这时如果我们直接使用新建材质与无光照着色器(Unlit shader),可能会发生一个对于新手而言意料之外的问题—— 物体!消失了!         打开你正在使用的的 通用渲染器(Universal Rendere

    2024年02月06日
    浏览(83)
  • 如何扩展Unity URP的后处理Volume组件

    Unity在更新到Unity2019.4之后,大家或许已经发现,在使用URP(通用渲染管线)的情况下,Unity原来的Post Processing插件好像不起效了。 原来Unity在Unity2019.4之后在URP内部集成了屏幕后处理的功能,使用方法也很简单,直接在Hierachy视图右键,选择Volume/Global Volume,我们就可以在Hie

    2024年02月16日
    浏览(52)
  • unity 建立urp项目并使用后处理技术的方法

    Unity URP是Unity官方提供的轻量级渲染管线,它旨在为移动平台和低端PC提供高效的渲染解决方案。相较于传统的渲染管线,URP使用了一些新的技术和算法来提高渲染效率和质量。URP还支持可编程渲染管线(Shader Graph)和更加直观的后处理效果。在使用URP时,可以通过调整一些参

    2024年02月16日
    浏览(50)
  • 【Unity Shader Graph URP渲染管线下的自定义半透明效果_半透明案例分享】

    URP的渲染管线下 在项目设置里找到“Graphic” 找到URP Asset文件 索引到Renderer List文件——“ForwardRenderer” 在这个“ForwardRenderer”文件里找到“Add Renderer Feature” 添加一个渲染对象,类似下图:Render Object (Experimental) 如图设置,将“Event”设置成 AfterRenderingSkybox ,然后“Layer M

    2024年02月09日
    浏览(59)
  • Unity Shader 学习笔记(4)URP渲染管线带阴影PBR-Shader模板 -- 新增可自定义阴影颜色

    材质面板截图 功能实现(URP渲染管线下): 1、进一步优化Shader结构和算法; 2、包含PBR材质; 3、投射和接收阴影,并升级 支持自定义阴影颜色 ; 4、支持点光源照射(但不支持点光源阴影)。 通用渲染截图 自定义阴影颜色截图 完整代码: 写在最后: 1、在我的上一篇文

    2024年02月12日
    浏览(50)
  • Web3 solidity编写交易所合约 编写ETH和自定义代币存入逻辑 并带着大家手动测试

    上文 Web3 叙述交易所授权置换概念 编写transferFrom与approve函数我们写完一个简单授权交易所的逻辑 但是并没有测试 其实也不是我不想 主要是 交易所也没实例化 现在也测试不了 我们先运行 ganache 启动一个虚拟的区块链环境 先发布 在终端执行 如果你跟着我一步一步来的 那编

    2024年02月13日
    浏览(44)
  • 一些开源革命的幕后人物

    是一本关于开源革命幕后人物的持续摄影记录。该项目由著名或无名英雄的肖像组成,他们致力于创造和推进我们的开源技术。 此项目的链接来源:https://www.facesofopensource.com/ 摄影师 彼得-亚当斯 (Peter Adams)于2014年在硅谷工作室开始了“开源面孔”的活动的。从那时起,他

    2024年01月21日
    浏览(45)
  • 大数据与AI:解析智慧城市的幕后英雄

    🎉欢迎来到AIGC人工智能专栏~大数据与AI:解析智慧城市的幕后英雄 ☆* o(≧▽≦)o *☆嗨~我是IT·陈寒🍹 ✨博客主页:IT·陈寒的博客 🎈该系列文章专栏:AIGC人工智能 📜其他专栏:Java学习路线 Java面试技巧 Java实战项目 AIGC人工智能 数据结构学习 🍹文章作者技术和水平有限

    2024年02月07日
    浏览(32)
  • scss使用自定义函数实现单位像素随屏幕比例动态缩放

    vue中通过变量和scss函数来动态实现动态缩放像素 简单来说就是比例缩小时,像素单位变大,从而字体大小相对不变,以下仅处理比例缩小的状况 自定义一个属性–size,初始值为1px template map为:{100: 1, 90: 1.1, 80: 1.2, 75: 1.3, 67: 1.5, 50: 2, 33: 3, 25: 4 } 屏幕100%时,size=1 = mpx(1) = 1p

    2024年02月07日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包