在看Unity URP源码时一直忽略了其中一个方法 ProcessRenderRequests,今天查询API文档记录一下对这个方法的使用与理解
先贴一下源码
protected override void ProcessRenderRequests<RequestData>(ScriptableRenderContext context, Camera camera, RequestData renderRequest)
{
StandardRequest standardRequest = renderRequest as StandardRequest;
SingleCameraRequest singleRequest = renderRequest as SingleCameraRequest;
if(standardRequest != null || singleRequest != null)
{
RenderTexture destination = standardRequest != null ? standardRequest.destination : singleRequest.destination;
int mipLevel = standardRequest != null ? standardRequest.mipLevel : singleRequest.mipLevel;
int slice = standardRequest != null ? standardRequest.slice : singleRequest.slice;
int face = standardRequest != null ? (int)standardRequest.face : (int)singleRequest.face;
//store data that will be changed
var orignalTarget = camera.targetTexture;
//set data
RenderTexture temporaryRT = null;
RenderTextureDescriptor RTDesc = destination.descriptor;
//need to set use default constructor of RenderTextureDescriptor which doesn't enable allowVerticalFlip which matters for cubemaps.
if (destination.dimension == TextureDimension.Cube)
RTDesc = new RenderTextureDescriptor();
RTDesc.colorFormat = destination.format;
RTDesc.volumeDepth = 1;
RTDesc.msaaSamples = destination.descriptor.msaaSamples;
RTDesc.dimension = TextureDimension.Tex2D;
RTDesc.width = destination.width / (int)Math.Pow(2, mipLevel);
RTDesc.height = destination.height / (int)Math.Pow(2, mipLevel);
RTDesc.width = Mathf.Max(1, RTDesc.width);
RTDesc.height = Mathf.Max(1, RTDesc.height);
//if mip is 0 and target is Texture2D we can immediately render to the requested destination
if(destination.dimension != TextureDimension.Tex2D || mipLevel != 0)
{
temporaryRT = RenderTexture.GetTemporary(RTDesc);
}
camera.targetTexture = temporaryRT ? temporaryRT : destination;
if (standardRequest != null)
{
Render(context, new Camera[] { camera });
}
else
{
RenderSingleCameraInternal(context, camera);
}
if(temporaryRT)
{
switch(destination.dimension)
{
case TextureDimension.Tex2D:
case TextureDimension.Tex2DArray:
case TextureDimension.Tex3D:
Graphics.CopyTexture(temporaryRT, 0, 0, destination, slice, mipLevel);
break;
case TextureDimension.Cube:
case TextureDimension.CubeArray:
Graphics.CopyTexture(temporaryRT, 0, 0, destination, face + slice * 6, mipLevel);
break;
}
}
//restore data
camera.targetTexture = orignalTarget;
Graphics.SetRenderTarget(orignalTarget);
RenderTexture.ReleaseTemporary(temporaryRT);
}
else
{
Debug.LogWarning("The given RenderRequest type: " + typeof(RequestData).FullName + ", is either invalid or unsupported by the current pipeline");
}
}
在URP管线里面可以看到对这个方法没有任何引用,查询API文档后发现是这样写的
也就是说这个方法是由Camera来触发的 即Camera.SubmitRenderRequests
对于这个方法API文档上说 如果RenderPipeline implement了这个方法Unity会将一个RT进行更新并将其结果储存在请求数据中 在URP源码中我们可以看到 它先是将RenderData强转为两种类型之后声明了一张临时RT 之后进行正常渲染 只不过是将调用摄像机的RenderTarget设置成这张临时RT 之后将结果给Blit到请求数据中的目标RT中
也就是说我们可以利用这一点来简单做一个将游戏运行时的图像给渲染到一张我们想要的RT上
public RenderTexture renderTexture;
// Update is called once per frame
void Update()
{
Camera.main.SubmitRenderRequest(new UnityEngine.Rendering.Universal.UniversalRenderPipeline.SingleCameraRequest
{
destination = renderTexture,
mipLevel = 0,
});
}