Unity 的一些机制

操作中的机制

新建一个3d对象,如果其使用了自带的shader,将不会在Assets里面出现其材质,这个自带shader本身不可修改,若使用贴图放到3d对象身上,unity会自动创建一个以贴图为名称的材质(因为一个物体的材质是必须的,当修改默认时,自然需要一个材质)

渲染队列

https://blog.csdn.net/sinat_25415095/article/details/123752904

请注意,渲染队列和深度缓冲不是一回事:

渲染队列是unity特有的,决定shader运行顺序的一种机制,
而深度缓冲是为了不让shader运行顺序影响遮挡关系的一种机制

物体按照渲染队列从小到大开始渲染
当对物体设定特定的渲染队列时,如
Tags {"Queue"="Geometry+1"}
则会在所有的不透明物体渲染后进行渲染

而同一渲染队列的物体,会有特定的渲染顺序
不透明物体:距离相机 从前往后
(由于GPU的EarlyZ技术的存在可以减少Over Draw)
半透明物体:距离相机 从后往前(半透明物会关闭深度写入,这样做才能保证颜色在混合时是正确的)

(这个距离相机的距离具体是怎样测度的暂时不清楚:可能是对象的原点,也可能是对象距离最远/近的顶点)

Early Z



shader运行的机制

逐顶点逐像素

首先对于一个标准shader来说,并不是一个像素执行一次完整的shader的;
而是顶点着色器逐顶点执行完毕后,进行片元着色器逐片元执行

当纹理坐标在顶点中使用时

显然逐顶点计算时,这个纹理坐标就只是对应这一个顶点的坐标,无法覆盖整个对象(当片元着色器里面没有再使用纹理坐标计算);
因此unity内部的机制:顶点的纹理坐标会在整个对象的片元部分中线性插值,映射到所有片元

后处理 和 模板测试

后处理中是不能使用模板测试的,如果使用则会失效,这是因为后处理是在虚拟的渲染纹理中进行的,而这个渲染纹理并没有继承屏幕空间中的各个缓冲(不确定,但应该是这样)

官方API文档中有说 RenderTexture.GetTemporary(rtW, rtH,24); 第三个参数改成24会保留深度模板缓冲,测试无效


一篇文章介绍说再添加一个语句

RenderTexture buffer = RenderTexture.GetTemporary(rtW, rtH,24); 
Graphics.SetRenderTarget(buffer.colorBuffer, src.depthBuffer);

这样会保留缓冲, 但经测试依然无效

目前为止,尚未发现能在后处理中使用模板缓冲的办法,SSSSS的案例考虑采用蒙版
后续发现解决办法再来更新

用来参考


纹理坐标的平台差异化

首先我们知道DirectX和OpenGL的uv坐标不一致:
在这里插入图片描述
Unity使用的是OpenGL的坐标系;对于DirectX平台Unity会自动为我们转化坐标,一般不用考虑平台的纹理坐标差异。

但是一种情况例外:开启抗锯齿 && 一次ImageEffect中使用两张以上的RenderTex

原因(推测):

  • 我们知道抗锯齿也是一种屏幕后处理,并且先于高斯模糊,bloom等BlurEffect(模糊后再抗锯齿没意义)
  • 但是一般抗锯齿算法是用硬件加速的,这要求uv坐标不能动,也就是开启硬件抗锯齿时,Unity并没有转换坐标,在抗拒出结束后,进行Blur时,需要手动翻转uv,否则可能会出错,
  • Unity在后处理中为我们转化uv坐标的步骤内置在**Graphics.Blit( )**函数中,也就是我们调用这个函数时,坐标会自动转化;在只使用一张RenderTex的时候,并不会出问题。需要两张RenderTex时,两张的uv可能相反
  • “可能会出错”的可能应该就在于(1)抗锯齿是否早于ImageEffect(2)是否硬件抗锯齿

(以上都是个人根据《UnityShader入门精要》5.6.1所描述进行的推测,在之后获得其真正原因后,再来更新)

解决办法:

	#if UNITY_UV_STARTS_AT_TOP  //检测是否DirectX
	if (_MainTex_TexelSize.y < 0.0) 
		uv.y = 1.0 - uv.y; //进行纵向翻转
	#endif

当DirectX时,由于_MainTex_TexelSize(纹素大小)的内置计算方法和y轴的反转,纹素大小的y值会小于0

猜你喜欢

转载自blog.csdn.net/dogman_/article/details/129703644