96SEO 2026-02-20 09:38 18
。

而且可以指定在相机渲染的某个点执行本身的拓展渲染。
Command
CommandBuffer携带一系列的渲染命令依赖相机用来拓展渲染管线的渲染效果。
而且可以指定在相机渲染的某个点执行本身的拓展渲染。
Command
简单来说就是可以在渲染流程中插入一些自定义操作开发者得到了更多的权限。
左图绿点处就是可以让开发者进行操作的地方右图蓝色是蓝色线框部分。
1.在unity里首先创建一个C#脚本和一个Shader脚本还有一个默认材质球。
UnityEngine.Rendering;[ExecuteInEditMode]
CommandBuffer();//设置渲染tBuffer.DrawRenderer(render,
Material(shader));//不透明物体渲染完后执行Camera.main.AddCommandBuffer(cameraEvent,tBuffer);}private
OnDisable(){Camera.main.RemoveAllCommandBuffers();}
相机在渲染完不透明物体后又渲染了一遍我们自己添加Buffer。
导致Game窗口下物体为Shader中返回的颜色。
System.Collections.Generic;[ExecuteInEditMode]
DictionaryCamera,CommandBuffer();//
(cam.Key){cam.Key.RemoveCommandBuffer
cam.Value);}}m_Cameras.Clear();Object.DestroyImmediate
(m_Cameras.ContainsKey(cam))return;if
Material(m_BlurShader);m_Material.hideFlags
Shader.PropertyToID(_ScreenCopyTexture);//用screenCopyID标识获取一个模板纹理。
buf.GetTemporaryRT
FilterMode.Bilinear);//BuiltinRenderTextureType.CurrentActive也就是当前屏幕的纹理标识将其赋值进screenCopyID标识的纹理。
buf.Blit
(BuiltinRenderTextureType.CurrentActive,
Shader.PropertyToID(_Temp1);int
Shader.PropertyToID(_Temp2);buf.GetTemporaryRT
FilterMode.Bilinear);buf.GetTemporaryRT
RT//将抓屏纹理_ScreenCopyTexture采样填充到_Temp1后释放。
buf.Blit
blurredID);buf.ReleaseTemporaryRT
blur//修改SeparableBlur.shader的全局参数offsets使其产生各个方向的模糊效果来叠加增强效果。
//如果着色器不在
Properties模块中暴露某个参数将使用全局属性buf.SetGlobalVector(offsets,
Vector4(2.0f/Screen.width,0,0,0));//使用m_Material渲染blurredID结果赋值给blurredID2。
buf.Blit
blurbuf.SetGlobalVector(offsets,
Vector4(0,2.0f/Screen.height,0,0));buf.Blit
blurbuf.SetGlobalVector(offsets,
Vector4(4.0f/Screen.width,0,0,0));buf.Blit
blurbuf.SetGlobalVector(offsets,
Vector4(0,4.0f/Screen.height,0,0));buf.Blit
m_Material);//得到透明效果纹理后赋值给GlassWithoutGrab.shader的_GrabBlurTexture混合得出模糊透明。
buf.SetGlobalTexture(_GrabBlurTexture,
blurredID);cam.AddCommandBuffer
_MainTex;//偏移定点uv使其读取到周围颜色值进行混合。
v2f
UnityObjectToClipPos(v.vertex);o.uv.xy
ARB_precision_hint_fastest#pragma
TEXCOORD2;UNITY_FOG_COORDS(3)};float
UnityObjectToClipPos(v.vertex);#if
1.0;#endif//将顶点裁剪空间下的坐标计算NDC空间上的位置后映射到模糊纹理的uv。
o.uvgrab.xy
);UNITY_TRANSFER_FOG(o,o.vertex);return
o;}//抓屏得到的模糊纹理会赋值到此。
(因为Properties没有定义_GrabBlurTexture所以默认使用全局的参数)sampler2D
_GrabBlurTexture_TexelSize;sampler2D
_GrabBlurTexture_TexelSize.xy;i.uvgrab.xy
UNITY_PROJ_COORD(i.uvgrab));half4
i.uvmain);//模糊纹理与主纹理混合得出模糊透明效果col
_TintAmt);UNITY_APPLY_FOG(i.fogCoord,
虽然Shader.PropertyToID返回的是一个int类型但是Blit操作用到的ID会强转成RenderTargetIdentifier以供Blit需要。
Buffer相关的代码进行一个梳理只列举一些关键、常用的变量和函数。
在3D计算机图形领域渲染目标是现代图形处理单元GPU的一个特征它允许将3D场景渲染到中间存储缓冲区或渲染目标纹理RTT而不是帧缓冲区或后缓冲区。
然后可以通过像素着色器操纵此RTT
以便在显示最终图像之前将其他效果应用于最终图像。
渲染目标就是一个缓冲区除了back
buffer之外的缓冲区用来记录渲染后的输出的结果而不直接将帧缓冲绘制到屏幕。
而是将其应用到别处。
渲染纹理是指可以被渲染的纹理。
RTRenderTarget可以用来实现基于图像的渲染效果动态阴影反射监控相机【cs1.6里的assault仓库】。
渲染纹理的经典用法是将RenderTexture设置为相机的“TargetTexture”Camera.targetTexture这将会使得相机渲染的结果渲染到RenderTexture上而不是直接渲染到屏幕上。
需要记住的是渲染纹理的像素内容可能会在某些事件中丢失比如加载新关卡屏幕进入保护模式全屏进入当这种情况发生时你的RenderTexture将会再次变成“尚未创建”遇到这种情况需要用IsCreate函数进行检测。
和其他“原生引擎对象”的类型一样需要关注RenderTexture的生命周期并在使用完成之后使用Release函数进行释放因为RenderTexture不会像普通托管类型那样会被GC垃圾回收。
这个结构体主要描述绑定的RenderTexture如何应用到RenderTarget上使用哪个Mip使用哪个CubeMap的Face。
对于Texture3D/Texture2DArray还能够指定使用哪个depthSlice进行写入。
将对应的Pass框选出来方便在Profile里进行分析。
但是在URP的源码里经常会出现其他的写法使用using(newProfilingScope(CommandBuffer
设置渲染目标添加一个激活渲染目标的指令到CommandBuffer中。
指定一张RenderTexture作为RenderTarget可以使用好几种方法
2.GetTemporaryRT申请的RT的Id(int)类型
3.在渲染周期内生成的内置Built-InRenderTexture[BuiltinRenderTextureType]
这些全部都会被隐式转换成RenderTargetIdentifier这个结构体。
Load当RenderBuffer被激活时载入原本已保存的内容这个加载读取的操作对Tile
Clear当RenderBuffer被激活时会清理掉原本Buffer里的内容。
目前不能直接使用需要使用CommandBuffer.CleanRenderTarget作为代替。
DontCare当RenderBuffer被激活时GPU不会把RenderBuffer的内容加载进内存从而减少带宽传输压力。
CommandBuffer.SetTarget()几个重载都是用的Load
跟RenderBufferLoadAction类似但这个枚举类型参数主要是控制RenderBuffer存储时的策略。
StoreRenderBuffer的内容需要存储到RAM中。
如果启用了MSAA这是就会存储未Resolvenon-resolved的着色结果。
data重新解析resolve为每像素一个采样点并将数据存储到RenderTexture中丢弃了多采样数据。
目前不能直接设置只能调用API进行Resolve
data重新解析resolve为每像素一个采样点并将数据存储到RenderTexture中并且存储多重采样数据。
目前不能直接使用只能调用API进行Resolve。
DontCareRenderBuffer的内容是不需要的可以被丢弃。
Tile-base架构的GPU将完全跳过存储阶段有次减少带宽压力提高性能。
[RenderTextureMemoryless需要设置对象的模式]
CommandBuffer.SetTarget()几个重载都是用的Resolve
把一个或者多个ColorBuffer以及一个深度/模板缓冲[8/16/24/32bit]如何绑定到RenderTarget上并且他们各自Load和Store的策略。
shaderPassMaterial对应的shader使用Pass的索引值默认为-1渲染所有Pass
propertiesMaterialPropertyBlock不需要额外创建材质实例就可以覆写当前绘制时的材质属性值。
CommandBuffer.DrawMeshInstanced
使用实例化绘制多个相同Mesh看到matrices和count这两个参数说明绘制时需要提供模型空间矩阵M数组以及绘制的数量。
需要注意的是绘制时的Material对应的shader一定得是支持Instance绘制。
绘制Instance时的InstancePath是Instance
跟之前的DrawMeshInstanced相比区别就是不支持LightMap和LightProbe需要手动在Procedural的函数实现从Instance和CBuffer中通过InstanceID获取每个实例所对应的的LightMapSTLightMapIndexLightProbe的SHOcclusion数值。
绘制Instance时除了需要提供绘制Instance的Mesh之外还需要通过MaterialPropertyBlock设置绘制时所需要用到的Compute
另外需要用BufferArgs控制绘制的顶点数以及实例数量绘制时开始的Index位置开始绘制时的Instance位置。
可以看到BufferArgs的可控性更强了但是一般而言是会配合着Compute
Shader进行控制BufferArgs的数值然后再通过BufferArgs绘制Instance。
一般来说DrawMeshInstanceIndirect会用来制作视锥裁剪的四叉树地形草地等等。
选择绘制的拓扑结构进行绘制Mesh不需要用vertex/index
shader生成顶点数据然后再调用DrawProcedural的时候用Vertex
DrawMeshInstanceIndirect一样需要提供BufferArgs控制实例化的过程参数。
最为常用的用法还是写在Gameloop里用脚本获取常经理的Renderer在管线里new一个Renderer来渲染貌似不是一个好主意。
在实际使用的时候为了以防万一尽量使用CommandBuffer.SetGlobalTexture配合Shader.PropertyToID设置参数。
另外最好还是得手动SetRenderTarget设置下LoadAction以及StoreAction节省带宽
此处开始全是在URP下进行我用的版本Unity2020.3f1c1
这个UniversalRP-HighQuality就是我们以后要替换的URPAsset。
点击这个Asset可以在Inspector面板上看到RendererList。
Renderer会创建两个默认的配置文件就是上面流程梳理里面的两个文件。
首先创建两个脚本分别叫做CustomRenderPipline和CustomRenderPiplineAsset。
分别继承RenderPipeline和RenderPipelineAsset如下。
UnityEngine.Rendering;[CreateAssetMenu(menuName
创建一个新的自定义相机渲染脚本CustomCameraRenderer.cs
CustomCameraRenderer();protected
cameras){_renderer.Render(context,camera);
这种方法能让每个相机在未来更容易支持不同的渲染方法。
例如一个渲染第一人称视图一个渲染三维地图或前向和延迟渲染的区别。
但现在我们会用同样的方式渲染所有的摄像机。
ScriptableRenderContext包含了一些渲染相关的数据具体可以查看源码。
--------------------------------后续借用Catlike里面的截图----------------------------------
在CustomCameraRenderer中对可见物体进行绘制Context.DrawSkybox(camera)
上下文会延迟实际的渲染直到我们提交它为止。
在此之前我们对其进行配置并向其添加命令以供后续的执行。
某些任务例如绘制天空盒提供了专属方法但其他命令则必须通过单独的命令缓冲区command
buffer间接执行。
我们需要用这样的缓冲区来绘制场景中的其他几何图形。
为了获得缓冲区我们必须创建一个新的CommandBuffer对象实例。
一般只需要一个缓冲区因此默认情况下为CameraRenderer创建一个缓冲区并将对它的引用存储在字段中。
给缓冲区起一个名字以便我们在frame
CustomCameraRenderer里添加CommandBuffer如下图所示。
我们可以使用命令缓冲区注入给Profiler样本这些样本将同时显示在Profiler和frame
debugger中。
通过在适当的位置插入BeginSample和EndSample就可以完成。
在本例中在Setup和Submit的开头添加。
注意两个方法必须提供相同的样本名称为此我们直接使用缓冲区的名称。
要执行缓冲区在上下文中调用ExecuteCommandBuffer并把缓冲区作为一个参数。
这是从缓冲区中复制命令但并不清除它如果我们想重新使用它我们必须在事后明确地这样做。
因为执行和清除总是一起进行的所以添加一个方法来做这两件事是很方便的。
简单来说就是我们可以手动控制渲染顺序并且在Profiler和Frame
我们画的东西最终会被渲染到摄像机的渲染目标上默认情况下是帧缓冲区但也可以是渲染纹理。
之前绘制到该目标上的东西仍然存在这可能会干扰我们现在正在渲染的图像。
为了保证正常的渲染我们必须清除渲染目标以摆脱它的旧内容。
这可以通过在命令缓冲区上调用ClearRenderTarget来实现它属于Setup方法。
Camera的一个额外层次中。
这是因为ClearRenderTarget用命令缓冲区的名字将清除动作包裹在一个样本中。
我们可以通过在开始我们自己的样本之前进行清除来摆脱多余的嵌套。
这导致了两个相邻的Render
GL条目表示用Hidden/InternalClear着色器绘制全屏四边形该着色器会写入渲染目标这并不是最有效的清除方式。
使用这种方法是因为我们是在设置摄像机属性之前进行清除。
如果我们把这两个步骤的顺序对调一下就可以得到快速的清除方式。
现在我们看到ClearcolorZstencil这表明颜色和深度缓冲区都被清除了。
Z深度缓冲区和模版数据是整个缓冲区的一部分。
剔除这部分就是要剔除相机看不到的地方为此我们可以使用ScriptableCullingParameters结构。
我们可以在摄像机上调用TryGetCullingParameters用它来返回一个bool值用作后续的渲染。
实际的剔除是通过在上下文中调用Cull来完成的它会产生一个CullingResults结构。
如果成功的话就在Cull中进行并将结果存储在一个字段中。
在这种情况下我们必须把剔除参数作为一个引用参数来传递在它前面写上ref。
一旦我们知道什么是可见的我们就可以继续渲染这些东西了。
这可以通过在上下文中调用DrawRenderers来完成并将剔除结果作为一个参数告诉它要使用哪些渲染器。
除此之外我们还必须提供绘制设置和过滤设置。
两者都是结构体--绘图设置DrawingSettings和过滤设置FilteringSettings我们最初会使用它们的默认构造函数。
两者都必须通过引用来传递。
在绘制天空盒之前在DrawVisibleGeometry中这样做。
我们还没有看到任何东西因为我们还必须指出哪种着色器通道是允许的。
由于我们在本教程中只支持非亮光着色器我们必须为SRPDefaultUnlit通道获取着色器标签ID我们可以做一次并将其缓存在一个静态字段中。
将其作为DrawingSettings构造函数的第一个参数同时提供一个新的SortingSettings结构值。
将相机传递给排序设置的构造函数因为它被用来确定是否适用正交或基于距离的排序。
除此之外我们还必须指出哪些渲染队列是允许的。
将RenderQueueRange.all传递给FilteringSettings构造函数这样我们就包括了所有的东西。
可以看到现在透明与不透明物体的渲染顺序杂乱无章下面要再对排序进行处理。
目前天空盒会遮挡住透明物体因此我们需要调整不透明物体与天空盒绘制的顺序。
我们可以通过切换到RenderQueueRange.opaque来消除初始DrawRenderers调用中的透明对象。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback