Unity3D URP 仿蜘蛛侠风格化BloomAO

Unity3D URP 仿蜘蛛侠风格化Bloom&AO

  • Bloom
    • Bloom效果流程:
    • 制作控制面板VolumeComponent.CS
    • Custom Renderer Feather
    • Custom Renderer Pass
      • Bloom Shader
      • Composite Shader
    • 完善Custom Feather
    • 风格化AO
  • 总结

本篇文章介绍在URP中如何进行风格化后处理,使用Renderer Feather 和自定义 Render Pass 实现。这种做法比起使用PostProcessing具有很大的自由度,能够自由控制渲染时机,减少束缚。

本教程使用Unity2022.3.5f1 版本。较低版本Shader Graph 没有Full Screen Sample Buffer。

以下两张图是蜘蛛侠动画剧照,高光Bloom部分很多是点阵的方式表现,一些AO使用混合平行斜线来表现。
在这里插入图片描述
在这里插入图片描述

类似的卡通渲染方案也被游戏 HiFi Rush 所使用。
在这里插入图片描述

Bloom

Bloom效果流程:

Composite Shader
Bloom
Texture
Screen

先制作Bloom效果,将Bloom渲染到一张Texture上,再将这个Texture通过我们的风格化Shader最后渲染到屏幕上

原始Bloom基本参照Unity的做法,在Packages/com.unity.render-pipelines.core/Runtime 文件夹中可找到相关代码

制作控制面板VolumeComponent.CS

  1. 直接复制Unity Bloom需要的控制参数。
  2. 添加我们风格化点阵需要的控制参数。
[VolumeComponentMenuForRenderPipeline("CustomBloomEffect", typeof(UniversalRenderPipeline))]
public class CustomBloomEffectComponent : VolumeComponent, IPostProcessComponent
{//bloom settings copy from Unity default Bloom[Header("Bloom Settings")]public FloatParameter threshold = new FloatParameter(0.9f,true);public FloatParameter intensity = new FloatParameter(1,true);public ClampedFloatParameter scatter = new ClampedFloatParameter(0.7f,0,1,true);public IntParameter clamp = new IntParameter(65472,true);public ClampedIntParameter maxIterations = new ClampedIntParameter(6,0,10);public NoInterpColorParameter tint = new NoInterpColorParameter(Color.white);//Custom Bloom Dots[Header("Dots")] public IntParameter dotsDensity = new IntParameter(10,true);public ClampedFloatParameter dotsCutoff = new ClampedFloatParameter(0.4f,0,1, true);public Vector2Parameter scrollDirection = new Vector2Parameter(new Vector2());[Header("AOLines")]public ClampedFloatParameter linesWidth = new ClampedFloatParameter(0.001f,0.001f,0.01f, true);public ClampedFloatParameter linesIntensity = new ClampedFloatParameter(0.05f,0,0.05f, true);public ColorParameter linesColor = new ColorParameter(Color.black, true, true, true);public FloatParameter linesAngle = new FloatParameter(30f, true);public bool IsActive(){return true;}public bool IsTileCompatible(){return false;}
}
  1. 将这个脚本挂载到场景中,我们就得到了一个和Unity原生很相识的一个控制面板,并且有新增的Dots控制功能:
    在这里插入图片描述

Custom Renderer Feather

参照Unity自带的Renderer Feather 我们可仿写一个我们自己的Renderer Feather
Unity自带Renderer Feather 目录:
在这里插入图片描述

Custom Renderer Pass

先创建一个简单的自定义Pass,这是渲染Pass,在FrameDebugger中这些根节点都是一个Pass,如图:
在这里插入图片描述
最简代码如下:

[System.Serializable]
public class CustomPostProcessPass : ScriptableRenderPass{public override void Execute(ScriptableRenderContext context,ref RenderingData renderingData)}}
}

然后我们再创建一个Custom Renderer Feather
代码:

[System.Serializable]
public class CustomPostProcessRendererFeature : ScriptableRendererFeature{private CustomPostProcessPass m_customPass;public override void AddRenderPasses(ScriptableRenderer renderer,ref RenderingData renderingData){renderer.EnqueuePass(m_customPass);}public override void Create(m_customPass = new CustomPostProcessPass()}
}

有了这两个后,我们就能在Renderer Data 面板中添加这个新Feather了
在这里插入图片描述

Bloom Shader

这个为了方便直接复制Unity自带的Bloom。地址:Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Bloom.shader

Composite Shader

  1. 使用Shader Graph 制作用于风格化Bloom后的Texture。创建一个FullscreenShaderGraph(Unity 2022以上)
    在这里插入图片描述
  2. 创建SampleTexture2D 节点,并且修改名称,注意Reference名称,我们需要通过这个名称向shader传入bloom texture
    在这里插入图片描述
  3. 使用Voronoi Node输 设置AngleOffset为0, 使用Screen Position 作为UV 得到一组排列整齐的圆点格子,创建Density属性,用于控制格子密度(大小)
    在这里插入图片描述
  4. 再通过一个Comparision Node 这样得到1,0分明的圆点,并创建Cutoff属性进行圆点占据格子比例大小控制
    在这里插入图片描述
  5. 使用URP Sample Buffer(这个就是当前屏幕渲染图像Screen Texture) 和点阵相加。
    在这里插入图片描述
  6. 完整的shader graph:
    在这里插入图片描述

完善Custom Feather

这个主要参考Unity URP的Bloom PostProcession写法。
CustomPostProcessRenderFeature 完整代码:

public class CustomPostProcessRenderFeature : ScriptableRendererFeature
{[SerializeField]private Shader m_bloomShader;[SerializeField]private Shader m_compositeShader;private Material m_bloomMaterial;private Material m_compositeMaterial;private CustomPostProcessPass m_customPass;public override void Create(){m_bloomMaterial = CoreUtils.CreateEngineMaterial(m_bloomShader);m_compositeMaterial = CoreUtils.CreateEngineMaterial(m_compositeShader);m_customPass = new CustomPostProcessPass(m_bloomMaterial, m_compositeMaterial);}public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData){renderer.EnqueuePass(m_customPass);}public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData){if (renderingData.cameraData.cameraType == CameraType.Game){m_customPass.ConfigureInput(ScriptableRenderPassInput.Depth);m_customPass.ConfigureInput(ScriptableRenderPassInput.Color);m_customPass.SetTarget(renderer.cameraColorTargetHandle, renderer.cameraDepthTargetHandle);}}protected override void Dispose(bool disposing){CoreUtils.Destroy(m_bloomMaterial);CoreUtils.Destroy(m_compositeMaterial);}
}

CustomPostProcessingPass 完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.Universal.Internal;public class CustomPostProcessPass : ScriptableRenderPass
{private Material m_bloomMaterial;private Material m_compositeMaterial;//RTHandles 是一种特殊RenderTexture,它可以在运行时动态调整大小,而不是在编辑器中预先分配固定大小的RenderTexture。private RTHandle m_CameraColorTarget;private RTHandle m_CameraDepthTarget;const int k_MaxPyramidSize = 16;private int[] _BloomMipUp;private int[] _BloomMipDown;private RTHandle[] m_BloomMipUp;private RTHandle[] m_BloomMipDown;private GraphicsFormat hdrFormat;private CustomBloomEffectComponent m_BloomEffect;private RenderTextureDescriptor m_Descriptor;private static readonly int ScreenSpaceOcclusionTexture = Shader.PropertyToID("_ScreenSpaceOcclusionTexture");public void SetTarget(RTHandle cameraColorTarget, RTHandle cameraDepthTarget){this.m_CameraColorTarget = cameraColorTarget;this.m_CameraDepthTarget = cameraDepthTarget;}public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData){m_Descriptor = renderingData.cameraData.cameraTargetDescriptor;}public CustomPostProcessPass(Material bloomMaterial, Material compositeMaterial){this.m_bloomMaterial = bloomMaterial;this.m_compositeMaterial = compositeMaterial;renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;_BloomMipUp = new int[k_MaxPyramidSize];_BloomMipDown = new int[k_MaxPyramidSize];m_BloomMipUp = new RTHandle[k_MaxPyramidSize];m_BloomMipDown = new RTHandle[k_MaxPyramidSize];for (int i = 0; i < k_MaxPyramidSize; i++){_BloomMipUp[i] = Shader.PropertyToID("_BloomMipUp" + i);_BloomMipDown[i] = Shader.PropertyToID("_BloomMipDown" + i);m_BloomMipUp[i] = RTHandles.Alloc(_BloomMipUp[i], name: "_BloomMipUp" + i);m_BloomMipDown[i] = RTHandles.Alloc(_BloomMipDown[i], name: "_BloomMipDown" + i);}const FormatUsage usage = FormatUsage.Linear | FormatUsage.Render;if (SystemInfo.IsFormatSupported(GraphicsFormat.B10G11R11_UFloatPack32, usage)) //判断是否支持HDR格式{hdrFormat = GraphicsFormat.B10G11R11_UFloatPack32;}else{hdrFormat = QualitySettings.activeColorSpace == ColorSpace.Linear ? GraphicsFormat.R8G8B8_SRGB : GraphicsFormat.R8G8B8_UNorm;}}public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData){VolumeStack stack = VolumeManager.instance.stack;m_BloomEffect = stack.GetComponent<CustomBloomEffectComponent>();CommandBuffer cmd = CommandBufferPool.Get();//使用ProfilingScope 才能在FrameDebugger中看到using (new ProfilingScope(cmd, new ProfilingSampler("Custom Post Process Effect"))){Texture ssaoTex = Shader.GetGlobalTexture(ScreenSpaceOcclusionTexture);m_compositeMaterial.SetTexture("_SSAOTexture", ssaoTex);//Shader.SetGlobalTexture("_SSAOTexture", ssaoTex);SetupBloom(cmd, m_CameraColorTarget);m_compositeMaterial.SetFloat("_Cutoff", m_BloomEffect.dotsCutoff.value);m_compositeMaterial.SetFloat("_Density", m_BloomEffect.dotsDensity.value);m_compositeMaterial.SetVector("_Direction", m_BloomEffect.scrollDirection.value);m_compositeMaterial.SetFloat("_LineWidth", m_BloomEffect.linesWidth.value);m_compositeMaterial.SetFloat("_LineIntensity", m_BloomEffect.linesIntensity.value);m_compositeMaterial.SetColor("_LineColor", m_BloomEffect.linesColor.value);m_compositeMaterial.SetFloat("_LineAngle", m_BloomEffect.linesAngle.value);Blitter.BlitCameraTexture(cmd, m_CameraColorTarget, m_CameraColorTarget, m_compositeMaterial, 0);}context.ExecuteCommandBuffer(cmd);cmd.Clear();CommandBufferPool.Release(cmd);}private void SetupBloom(CommandBuffer cmd, RTHandle source){// 初始大小减半 降采样int downres = 1;int tw = m_Descriptor.width >> downres;int th = m_Descriptor.height >> downres;//Determine the iteration count based on the size of the pyramidint maxSize = Mathf.Max(tw, th);int iterations = Mathf.FloorToInt(Mathf.Log(maxSize,2f) - 1);int mipCount = Mathf.Clamp(iterations,1, m_BloomEffect.maxIterations.value);// Pre-filtering parametersfloat clamp = m_BloomEffect.clamp.value;float threshold = Mathf.GammaToLinearSpace(m_BloomEffect.threshold.value);float thresholdKnee = threshold * 0.5f;// Hardcoded soft knee// Material setupfloat scatter = Mathf.Lerp(0.05f,0.95f,m_BloomEffect.scatter.value);var bloomMaterial = m_bloomMaterial;bloomMaterial.SetVector("_Params",new Vector4(scatter,clamp,threshold,thresholdKnee));//Prefiltervar desc = GetCompatibleDescriptor(tw,th,hdrFormat);for (int i = 0; i < mipCount; i++){RenderingUtils.ReAllocateIfNeeded(ref m_BloomMipUp[i],desc,FilterMode.Bilinear,TextureWrapMode.Clamp,name: m_BloomMipUp[i].name);RenderingUtils.ReAllocateIfNeeded(ref m_BloomMipDown[i], desc, FilterMode.Bilinear, TextureWrapMode.Clamp,name: m_BloomMipDown[i].name);desc.width = Mathf.Max(1, desc.width >> 1);desc.height = Mathf.Max(i, desc.height >> i);}Blitter.BlitCameraTexture(cmd, source, m_BloomMipDown[0], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 0);//Downsamplevar lastdown = m_BloomMipDown[0];for (int i = 0; i < mipCount - 1; i++){//第一个Pass是 2x 降采样 + 9tap高斯模糊//第二个Pass是 使用5tap过滤的9tap高斯模糊 + 双线性过滤 Blitter.BlitCameraTexture(cmd, lastdown, m_BloomMipUp[i], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 1);Blitter.BlitCameraTexture(cmd, m_BloomMipUp[i], m_BloomMipDown[i], RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 2);lastdown = m_BloomMipDown[i];}// Upsamplefor (int i = mipCount - 2; i >= 0; i--){var lowMip = (i == mipCount - 2)? m_BloomMipDown[i + 1] : m_BloomMipUp[i + 1];var highMip = m_BloomMipDown[i];var dst = m_BloomMipUp[i];cmd.SetGlobalTexture("_SourceTexLowMip", lowMip);Blitter.BlitCameraTexture(cmd, highMip, dst, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, bloomMaterial, 3);}m_compositeMaterial.SetTexture("_Bloom_Texture", m_BloomMipUp[0]);m_compositeMaterial.SetFloat("_BloomIntensity", m_BloomEffect.intensity.value);cmd.SetGlobalFloat("_BloomIntensity", m_BloomEffect.intensity.value);}private RenderTextureDescriptor GetCompatibleDescriptor(){return GetCompatibleDescriptor(m_Descriptor.width, m_Descriptor.height, m_Descriptor.graphicsFormat);}private RenderTextureDescriptor GetCompatibleDescriptor(int tw, int th, GraphicsFormat graphicsFormat, DepthBits depthBufferBits = DepthBits.None){return GetCompatibleDescriptor(m_Descriptor, tw, th, graphicsFormat, depthBufferBits);}internal static RenderTextureDescriptor GetCompatibleDescriptor(RenderTextureDescriptor desc, int tw, int th, GraphicsFormat format, DepthBits depthBufferBits = DepthBits.None){desc.depthBufferBits = (int)depthBufferBits;desc.width = tw;desc.height = th;desc.graphicsFormat = format;desc.msaaSamples = 1;return desc;}}

在Renderer Data上吧Bloom Shader 和Composite Shader 拖拽进去
在这里插入图片描述
成功运行就能看到结果了:

在这里插入图片描述

风格化AO

要点: 添加Screen Space Ambient Occlusion 然后通过_ScreenSpaceOcclusionTexture 获取AO贴图,再把AO贴图作为Mask,在Mask内画斜线。
在这里插入图片描述

private static readonly int ScreenSpaceOcclusionTexture = Shader.PropertyToID("_ScreenSpaceOcclusionTexture");

可以在Composite Shader一起处理
一种效果如下:
在这里插入图片描述

总结

在实际游戏中,这些效果处理要更加复杂一些,这里给大家开个头,发挥想象把效果做得更出彩吧~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/131734.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做题(2)

1.command_execution 题目提示&#xff1a; (这道题的名字就叫命令执行漏洞) 发现ping 先rce一下 127.0.0.1 | ls 发现了东西 尝试访问一下 找到了所有的文件 访问var文件夹 发现在var/www/html目录下没找到 去别的地方找找 在home文件夹下找到flag文件 访问 得到flag cyb…

网络层--IP协议

引入&#xff1a; IP协议主要解决什么问题呢&#xff1f; IP协议提供一种将数据从主机&#xff21; 发送到 主机&#xff22;的能力。&#xff08;有能力不一定能做到&#xff0c;比如小明很聪明&#xff0c;可以考100分&#xff0c;但是他也不是每次搜能考100分&#xff0…

Unity VideoPlayer 指定位置开始播放

如果 source是 videoclip&#xff08;以下两种方式都可以&#xff09;&#xff1a; _videoPlayer.Play();Debug.Log("time: " _videoPlayer.clip.length);_videoPlayer.time 10; [SerializeField] VideoPlayer videoPlayer;public void SetClipWithTime(VideoClip…

23062C++QTday5

将之前定义的栈类和队列类都实现成模板类 栈&#xff1a; #include <iostream> #define MAX 128using namespace std;template<typename T,typename C> class Stack { private:T top; //栈顶元素的下标C *data; //指向堆区空间public:Sta…

【C++】常用排序算法

0.前言 1.sort #include <iostream> using namespace std;// 常用排序算法 sort #include<vector> #include<algorithm>//利用仿函数 打印输出 class myPrint { public:void operator()(int val){cout << val << " ";} };//利用普通函…

界面控件DevExpress WPF TreeMap,轻松可视化复杂的分层结构数据!

DevExpress WPF TreeMap控件允许用户使用嵌套的矩形块可视化复杂的平面或分层结构数据。 P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&a…

接入Websocket,自动接收CSDN短消息

最近在研究Websocket功能&#xff0c;本来想接入抖音和快手的弹幕功能&#xff0c;以及短消息功能。 在了解的过程中&#xff0c;也开发了一些测试项目。 这不是&#xff0c;就把CSDN的短消息项目给弄出来了。 直接上代码&#xff1a; # !/usr/bin python3 # -*- encodingu…

spring boot+redis整合基础入门

文章目录 前言准备依赖项配置文件redis模板类注入设置序列化方式 实施基础字符串操作、超时设置Hash操作hash的使用场景以及优缺点 列表操作列表操作的应用场景以及优缺点 Set的基础操作Set类型的业务场景以及优缺点Demo地址 总结 前言 最近项目中有用到redis进行一些数据的缓…

重构优化第三方查询接口返回大数据量的分页问题

# 问题描述 用户线上查询其上网流量详单数据加载慢&#xff0c;且有时候数据没有响应全~ 1、经排除是调用第三方数据量达10w条响应会超时&#xff0c;数据没正常返回 2、现有线上缓存分页也是加载慢数据不能正常展示 3、第三方接口返回类似报文jsonj&#…

LVS负载均衡群集——LVS-NAT模式搭建和LVS-DR模式搭建

目录 lvs工作模式 1、NAT模式&#xff08;VS-NAT&#xff09; 2、直接路由模式&#xff08;VS-DR&#xff09; 3、IP隧道模式&#xff08;VS-TUN&#xff09; LVS调度算法 LVS群集类型 1&#xff09;负载均衡群集 LB 2&#xff09;高可用群集 HA 3&#xff09;高性能运…

C#获取屏幕的分辨率、工作区分辨率

运行结果如下; 由于屏幕的任务栏在侧面所以屏幕宽度变化。 代码如下 private void Form1_Load(object sender, EventArgs e){int SH Screen.PrimaryScreen.Bounds.Height; //1080int SW Screen.PrimaryScreen.Bounds.Width; //1920System.Drawing.Rectangle rec Screen.Get…

Nginx安装与常见命令

一、Nginx简介 官方文档&#xff1a;https://www.nginx.com/ Nginx中文文档&#xff1a;https://nginx.cn/doc/index.html Nginx由俄罗斯人&#xff08;Igor Sysoev&#xff09;编写的轻量级Web服务器&#xff0c;它的发音为 [ˈendʒɪnks] 。 Nginx 不仅是一款高性能的 HTTP服…

【C语言】找单身狗问题

一.找单身狗问题初阶 1.问题描述 一个数组中只有一个数字是出现一次,其他所有数字都出现了两次.编写一个函数,找出这个只出现一次的数字. 例如: 有数组的元素是:1,2,3,4,5,1,2,3,4 只有5出现了一次,要找出5. 2.解题思路 常规思路: 在常规思路中,我们首先想到的肯定是使用两层…

@DS注解方式springboot多数据源配置及失效场景解决

1.使用教程 导入依赖 <!--多数据源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.0</version></dependency>配置数据源 datasource:…

stu04-快速生成HTML5文档结构

1.直接输入一个英文的感叹号“!”&#xff0c;然后按Tab键&#xff0c;自动生成 2.输入“html:5”&#xff0c;然后按Tab键自动生成 3.直接复制粘贴以下代码&#xff1a; <!doctype html> <html lang"en"> <head><meta charset"UTF-8&q…

“金钥匙”转动!安全狗成功护航第二十三届中国国际投资贸易洽谈会举办

9月8日至9月11日&#xff0c;为期4天的第二十三届中国国际投资贸易洽谈会在厦门顺利举办。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借突出的安全综合实力&#xff0c;受委托并担任此次会议网络安保技术支撑单位。 厦门服云信息科技有限公司&#xff08;品牌名&#xf…

【C语言】每日一题(半月斩)——day1

目录 &#x1f60a;前言 一.选择题 1.执行下面程序&#xff0c;正确的输出是&#xff08;c&#xff09; 2.以下不正确的定义语句是&#xff08; &#xff09; 3.test.c 文件中包括如下语句&#xff0c;文件中定义的四个变量中&#xff0c;是指针类型的变量为【多选】&a…

ARM架构指令集--专用指令

四、状态寄存器专用指令 CPSR寄存器-N Z C V T为0时 为ARM状态 F为0时 为开启FIQ状态 I为0时 为开启IRQ状态 图1 图2 一开始都是SVC指令&#xff0c;因为在操作系统启动的时候&#xff0c;在做一些初始化的操作&#xff0c;不允许被打断 图3 复位后CPSR寄存器为0xD3--…

BUSMASTER使用记录(一):基本收发、报文过滤、报文录制和数据回放

目录 一、概述二、基本收发2.1 连接设备2.2 接收2.3 发送 三、DBC加载和转换DBF文件四、报文过滤4.1 新增过滤器4.2 使能 五、报文录制/回放报文录制数据回放 一、概述 以往使用过的CAN盒虽然厂家不一样&#xff0c;但都兼容周立功的CANPro。这次使用的BusMaster&#xff0c;需…

【Hive SQL 每日一题】统计用户连续下单的日期区间

文章目录 测试数据需求说明需求实现 测试数据 create table test(user_id string,order_date string);INSERT INTO test(user_id, order_date) VALUES(101, 2021-09-21),(101, 2021-09-22),(101, 2021-09-23),(101, 2021-09-27),(101, 2021-09-28),(101, 2021-09-29),(101, 20…