展览网站模板,网站稳定期怎么做,网站建设 的类型有哪些,ui中国网站一句话描述#xff0c;我们可以把SRP分解成两个部分#xff0c;分别是SRP Asset#xff0c;SRP Instance。SRP AssetSRP Asset是一个Unity Asset文件#xff0c;用来存储渲染管线的特定配置信息#xff0c;包含的信息有#xff1a;游戏物体是否应该投射阴影#xff1b;使…一句话描述我们可以把SRP分解成两个部分分别是SRP AssetSRP Instance。SRP AssetSRP Asset是一个Unity Asset文件用来存储渲染管线的特定配置信息包含的信息有游戏物体是否应该投射阴影使用什么样的着色器质量级别影子距离默认材质配置。此外还可以保存所有像在配置中保存和控制的信息和unity需要序列化的数据。SRP Asset定义了SRP的类型和所有配置数据的设置。SRP InstanceSRP Instance是实际执行渲染的类当unity发现工程使用SRP的时候就会寻找当前使用的SRP Asset并请求一个渲染实例该实例必须包含一个Render函数渲染实例表示管道配置。在渲染调用中Unity可以执行如下操作:清理framebuffer。执行场景清理。渲染游戏对象集。从一个帧缓冲区到另一个帧缓冲区执行位块传输渲染阴影。应用后处理效果。第一个SRP Asset案例SRP Asset实际是一个继承RenderPipelineAsset接口的类需要实现CreatePipeline接口。当unity首次执行渲染命令的时候则会调用这个接口并返回一个可用的渲染实例。下面所展示的就是一个简单的SRP Asset类。using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;[CreateAssetMenu(menuName Rendering/Custom Render Pipeline)]
public class CustomRenderPipelineAsset : RenderPipelineAsset
{protected override RenderPipeline CreatePipeline(){return new CustomRenderPipeline();}
}
SRP Instance在上面的叙述中CustomRenderPipelineAsset类重写了CreatePipeline方法并返回了一个CustomRenderPipeline实例对象该对象则是unity SRP渲染的入口。CustomRenderPipeline是一个继承RenderPipeline的类而且必须实现虚函数Render该函数包含了两个参数ScriptableRenderContext context是一个command buffer对象可以向其输入您想执行的渲染指令。Camera[] cameras一系列用于渲染的相机。先介绍一个简单的例子using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;public class CustomRenderPipeline : RenderPipeline
{public CameraRender cameraRender new CameraRender();public CustomRenderPipeline(){}protected override void Render(ScriptableRenderContext context, Camera[] cameras){foreach(var camera in cameras){cameraRender.Render(context, camera);}}
}
如上所示我们把渲染的处理逻辑封装到CameraRender类里对每一个场景中的活动相机进行单独处理。下一步先定义CameraRender类using UnityEngine;
using UnityEngine.Rendering;public class CameraRenderer {ScriptableRenderContext context;Camera camera;public void Render (ScriptableRenderContext context, Camera camera) {this.context context;this.camera camera;}
}
然后正式定义Render函数实现我们的自定义渲染管线。绘制天空盒在Render函数中是要绘制所有Camera可见的几何体我们声明一个函数DrawVisibleGeometry用于处理一些特殊的工作绘制天空盒也是在这个方法中处理不过我们还另外声明了一个方法来完成这个工作。代码如下public void Render (ScriptableRenderContext context, Camera camera) {this.context context;this.camera camera;DrawVisibleGeometry();}void DrawVisibleGeometry () {context.DrawSkybox(camera);}
然而这样仍不能显示天空盒这是因为我们调用DrawSkybox只是把命令添加到context的缓存队列里还需要调用context.Submit()方法才会正式执行缓存队列里面的命令。public void Render (ScriptableRenderContext context, Camera camera) {this.context context;this.camera camera;DrawVisibleGeometry();Submit();}void Submit () {context.Submit();}
最后我们可以看到下面的效果。但是这个渲染结果还是有问题当我们调整相机的角度或位置时渲染结果并没有发生变化这是因为我们并没有将视角投影矩阵传递给Command Buffer。这个变换矩阵在Unity Shader中是unity_MatrixVP。当我们打开frame debugger面板选择一个draw call这个变量就会显示在右侧的监视板上。当前不管我们怎么调整相机的姿态这个变量都会保持不变通过调用SetupCameraProperties方法可以构建这个矩阵。如下所示但是这个渲染结果还是有问题当我们调整相机的角度或位置时渲染结果并没有发生变化这是因为我们并没有将视角投影矩阵传递给Command Buffer。这个变换矩阵在Unity Shader中是unity_MatrixVP。当我们打开frame debugger面板选择一个draw call这个变量就会显示在右侧的监视板上。当前不管我们怎么调整相机的姿态这个变量都会保持不变通过调用SetupCameraProperties方法可以构建这个矩阵。如下所示public void Render (ScriptableRenderContext context, Camera camera) {this.context context;this.camera camera;Setup();DrawVisibleGeometry();Submit();
}void Setup () {context.SetupCameraProperties(camera);
}
2. Command buffer前面已经提到context只有在调用Submit方法时才会执行渲染指令在这之前都是将指令添加到渲染队列中。像天空盒可以通过专业的方法添加指令但是像其他任务则不能通过这样添加需要通过一个单独的command buffer间接添加。因此我们需要另建一个buffer用来绘制其他的几何对象。const string bufferName Render Camera;CommandBuffer buffer new CommandBuffer {name bufferName
};
在项目开发中profiler是一个非常强大和有用的工具这里我们可以把我们的Command Buffer加入到profiler样例中这个样例可以同时显示在profiler和frame debugger面板方法是在适当的位置调用BeginSample和EndSample方法在我们的案例中将会分别放在Setup()方法和Submit()方法的开头位置。BeginSample和EndSample方法必须使用相同的字符串参数作为样例的名字这里使用的是buffer的名字。void Setup () {buffer.BeginSample(bufferName);context.SetupCameraProperties(camera);
}void Submit () {buffer.EndSample(bufferName);context.Submit();
}
执行Command Buffer中的命令只需要调用context的ExecuteCommandBuffer方法并把buffer作为参数传递进去。void Setup () {buffer.BeginSample(bufferName);ExecuteBuffer();context.SetupCameraProperties(camera);
}void Submit () {buffer.EndSample(bufferName);ExecuteBuffer();context.Submit();
}void ExecuteBuffer () {context.ExecuteCommandBuffer(buffer);buffer.Clear();
}
这时候打开frame debugger我们就可以看到渲染的案例如下3. 清除渲染目标不管我们想要绘制什么东西最终都会渲染到相机的渲染目标中。相机的渲染目标一般是帧缓存区也可以是渲染纹理。渲染目标一般不会自动清除也就是说之前渲染的结果会一直保存在渲染目标中这样会干扰我们渲染新的图像。为了保证正确的渲染我们必须清除渲染目标以摆脱其旧的内容。通过调用ClearRenderTarget方法可以实现这个目的。ClearRenderTarget函数需要至少三个参数前两个参数指定是否清理颜色缓存和深度缓存一般都设为true第三个参数指定清理缓存的颜色这里使用Color.clear。void Setup () {buffer.BeginSample(bufferName);buffer.ClearRenderTarget(true, true, Color.clear);ExecuteBuffer();context.SetupCameraProperties(camera);
}
打开frame debugger可以看到清理渲染目标活动对应了一个叫DrawGL的样例。而且这个案例被镶嵌在另一个Render Camera样例中这是因为 ClearRenderTarget将清除任务包装在了一个使用Command buffer的名字命名的样例中。为了避免这种情况可以调整一下清除目标的代码的位置。void Setup () {context.SetupCameraProperties(camera);buffer.ClearRenderTarget(true, true, Color.clear);buffer.BeginSample(bufferName);ExecuteBuffer();//context.SetupCameraProperties(camera);
}
现在我们可以看到Clear(colorZstencil)这表明颜色跟深度缓冲都没清除了stencil数据是同一缓存区的一部分。