这里需要注意,有两个部分要做,一步是写脚本和shader,一步是在editor里进行绑定
这里有个概念上需要注意的,他这个pass啊,实际依赖问题都需要你自己在execute处理的,比如你要画N次东西,就要在execute里自己把逻辑梳理清楚,调用Blit进行绘制,然后读取,然后绘制,下面代码会有体现
这是 官方用法
先说第二步,我感觉第二步更加关键,我这里虽然名字是Blur,但是效果不是,我进行了化简,名字是因为我直接从上面的链接copy的代码
最下面这个add renderer feature按钮,当你完整的写完一个render feature组件后,这里是能识别到的,你点击他 下拉列表就有你刚写好的feature,所以关键就是找到你正在使用的renderer,添加你写好的render feature即可
下面说代码怎么写的
流程上,这里已知需要一个render feature,然后他会将PASS添加到渲染流程的执行时间点上
所以,我们需要的物件就是
这个feature的代码可以说是很简单
create就创建pass,指定inject point
dispose就是清理数据
add就是把pass对象加入渲染流程,render就不用你管了,会在对应的时间点执行pass的execute的
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering.Universal;
public class BlurRendererFeature : ScriptableRendererFeature
{
[SerializeField] private Shader shader;
private Material material;
private BlurRenderPass blurRenderPass;
public override void Create()
{
if (shader == null)
{
return;
}
material = new Material(shader);
blurRenderPass = new BlurRenderPass(material);
blurRenderPass.renderPassEvent = RenderPassEvent.AfterRenderingSkybox;
}
public override void AddRenderPasses(ScriptableRenderer renderer,
ref RenderingData renderingData)
{
if (renderingData.cameraData.cameraType == CameraType.Game)
{
renderer.EnqueuePass(blurRenderPass);
}
}
protected override void Dispose(bool disposing)
{
blurRenderPass.Dispose();
#if UNITY_EDITOR
if (EditorApplication.isPlaying)
{
Destroy(material);
}
else
{
DestroyImmediate(material);
}
#else
Destroy(material);
#endif
}
}
下面就是pass了,
需要的成员变量,材质,渲染纹理描述,渲染对象的句柄(这里应该就是对应OpenGL的FBO的ID
唯一一个关联就是这个函数 RenderingUtils.ReAllocateIfNeeded,应该就是函数内部逻辑判断如果需要的话,就创建一个texture然后返回ID
构造函数就给材质赋值,初始化一个FBO纹理的描述
这个configure函数类似窗口resize啥的需要重绘反正就要重新设置一下size类似这种
然后就是Blit函数,前面几个好理解,最后一个参数是你的material的shader里的pass的index
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class BlurRenderPass : ScriptableRenderPass
{
private Material material;
private RenderTextureDescriptor blurTextureDescriptor;
private RTHandle blurTextureHandle;
public BlurRenderPass(Material material)
{
this.material = material;
blurTextureDescriptor = new RenderTextureDescriptor(Screen.width,
Screen.height, RenderTextureFormat.Default, 0);
}
public override void Configure(CommandBuffer cmd,
RenderTextureDescriptor cameraTextureDescriptor)
{
// Set the blur texture size to be the same as the camera target size.
blurTextureDescriptor.width = cameraTextureDescriptor.width;
blurTextureDescriptor.height = cameraTextureDescriptor.height;
// Check if the descriptor has changed, and reallocate the RTHandle if necessary
RenderingUtils.ReAllocateIfNeeded(ref blurTextureHandle, blurTextureDescriptor);
}
public override void Execute(ScriptableRenderContext context,
ref RenderingData renderingData)
{
//Get a CommandBuffer from pool.
CommandBuffer cmd = CommandBufferPool.Get();
RTHandle cameraTargetHandle =
renderingData.cameraData.renderer.cameraColorTargetHandle;
// Blit from the camera target to the temporary render texture,
// using the first shader pass.
Blit(cmd, cameraTargetHandle, blurTextureHandle, material, 0);
// Blit from the temporary render texture to the camera target,
// using the second shader pass.
Blit(cmd, blurTextureHandle, cameraTargetHandle, material, 1);
//Execute the command buffer and release it back to the pool.
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
public void Dispose()
{
#if UNITY_EDITOR
if (EditorApplication.isPlaying)
{
Object.Destroy(material);
}
else
{
Object.DestroyImmediate(material);
}
#else
Object.Destroy(material);
#endif
if (blurTextureHandle != null) blurTextureHandle.Release();
}
}
这是HLSL风格,#pragma指定函数入口,提示说vert函数在blit.hlsl里,不需要写
这里就有俩PASS,Blit的最后一个函数就是指定此次渲染你要使用第几个,我这里第一次叠加蓝色,第二次叠加红色,最终画面呈现紫色
Shader "CustomRenderTexture/Blur"
{
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// The Blit.hlsl file provides the vertex shader (Vert),
// the input structure (Attributes), and the output structure (Varyings)
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
float4 BlurVertical (Varyings input) : SV_Target
{
return SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord) + float4(0.0, 0.0, 1.0, 0.2);
}
float4 BlurHorizontal (Varyings input) : SV_Target
{
return SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, input.texcoord) + float4(1.0, 0.0, 0.0, 0.2);
}
ENDHLSL
SubShader
{
Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
LOD 100
ZWrite Off Cull Off
Pass
{
Name "BlurPassVertical"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment BlurVertical
ENDHLSL
}
Pass
{
Name "BlurPassHorizontal"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment BlurHorizontal
ENDHLSL
}
}
}