Unity Shader渲染顺序 坐标系 和光照模型

版权声明:本文为博主原创文章,转载请注明出处http://blog.csdn.net/blues1021。 https://blog.csdn.net/Blues1021/article/details/78483884

1.Shader中的渲染顺序

是按照Queue"="Geometry" "RenderType"="Opaque,Queue是一般渲染时候的顺序,RenderType是后处理特效使用的渲染顺序。
Background, Geometry, AlphaTest,Transparent和Overlay,分别对应数值1000,2000,2450,3000和4000。 Shader中,如果要C#访问的uniform变量,还要声明一遍。
记得引擎渲染时候,是先更新物体,再排序,再渲染的,所以渲染为了提高效率做了合并批次(合为一张大图纹理,如果全部是透明的或者不透明的,那么各个网格可以合并尽管有先后),和渲染先后的处理。
渲染时候一帧里面有N个drawcall,每个drawcall会驱动进行一次渲染管线操作,会进行一次blend。

2.C#脚本或Shader中变换和坐标系

都是用向量左乘矩阵,矩阵也是左乘矩阵,从视图->模型的乘法顺序。是右手坐标系,列式存储。
其实世界坐标系是左手坐标系,视图坐标系是标准的右手坐标系。
透视 空间:刚好是D3DXMatrixPerspectiveFovRH中的公式, 得x'=x*xScale, y'=y*yScale,z'=a*z + b=(z + zn)*zf / (zn-zf)。zn,zf都是距离是正数,因为|z| > zn,且z是负数,所以z'是正数。
上面的变换一般用一个ShaderLab 中的MVP坐标系即可,右手坐标系的乘法顺序也要自裁剪矩阵乘以视图矩阵乘以世界矩阵的形式进行。
ndc坐标:左下角为(0,0)点,右上角为(1,1)点,屏幕中心为[0.5,0.5],z值保留了透视投影中的正值但是值的大小是世界坐标系的值。不同于D3D中的[-1,-1,0]到[1,1,1],也不同于OGL中的[-1,-1,-1]到[1,1,1]。NDC坐标系一般由硬件完成。
屏幕坐标:是OGL的左下角是(0,0)右上角是(1,1),DX却是左上角是(0,0)。
UGUI和NGUI都是屏幕坐标系,LinearRender也 类似。
鼠标点击的屏幕坐标:Input.mousePosition也是屏幕坐标系。可以看到U3D表面的世界是用了左手坐标系,实际自视图坐标系后都是右手坐标系的方式。

transform 在世界坐标系中的变换:是左手坐标系的 缩放 旋转 平移方式得到子在父坐标系中的位置。
业务情景处理,多摄像机之间的变换,利用屏幕坐标系和相对变换来处理。
知道将要指定的子节点位置position,需要求取它的世界坐标系,那么节点本身的不用考虑它的旋转和缩放因为只是影响子节点的(如果是节点上的网格那么是需要考虑的),取到该子节点position位置,对该位置进行父节点上的缩放旋转平移得到父节点在上一个节点位置,重复得到世界坐标中的位置。如果是求逆那么,一个节点整体求逆即可。

3.光照模型

surface shader中的:
struct SurfaceOutput{
half3 Albedo;// 反射光
half3 Normal; // 法线
half3 Enission; // 自发光
half Specular; // 高光
half Gloss; // 光泽度
half Alpha; // 透明度
}
half3 h = normalize (light.dir + viewDir);       
fixed diff = max (0, dot (s.Normal, light.dir));     
float nh = max (0, dot (s.Normal, h));  
float spec = pow (nh, s.Specular*128.0) * s.Gloss;// Specular是材料镜面光泽度越小亮斑越大,Gloss是材料镜面反射颜色强度,gloss调整高光更加明显。
surface shader是unity的强项, 可以使用现成的光照模型,多种光源的计算(也是应用了光照模型只是范围不同),衰减,各种阴影选项,自动的向前和延后光照模型 ;UE中内置功能丰富,但是要自己定制要花很多精力。
U3D光照还提供了light probe探针技术,和光照烘培技术。
光照模型如果有FBO的硬件下,可以启用延后光照,延后光照可以渲染复杂场景,但是因为合并FBO结果一次光照计算,不能很好的处理抗锯齿和半透明效果。
同时也不支持Unity3D中的Mesh Renderer组件的Receive Shadows功能,对Culling Masks的支持也不完善,最多能使用四个Culling Mask。
建议还是动态物体使用向前光照,结合Light probe探针效果。场景静态物件烘培。
U3D中的光照,因为是实时光照都是计算直接光照,间接光照用环境关表示。没有Max中的VRay用光线追踪还计算了间接光照。物体内部的光照也没有考虑。类似的间接光照可以用光照烘培表示。
Surface shader中:
E:\Unity3D\unity3D4.7\Editor\Data\CGIncludes\Lighting.cginc下的光照模型文件:
漫反射模型,LightingLambert 是向前光照模型,LightingLambert_PrePass是延后光照模型。
inline fixed4 LightingLambert (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
fixed diff = max (0, dot (s.Normal, lightDir));
fixed4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2);// atten是衰减
c.a = s.Alpha;
return c;
}
inline fixed4 LightingLambert_PrePass (SurfaceOutput s, half4 light)
{
fixed4 c;
c.rgb = s.Albedo * light.rgb;
c.a = s.Alpha;
return c;
}
镜面高光反射模型,LightingBlinnPhong 是向前光照,LightingBlinnPhong_PrePass是延后光照。
inline fixed4 LightingBlinnPhong (SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
half3 h = normalize (lightDir + viewDir);
fixed diff = max (0, dot (s.Normal, lightDir));
// 使用nh 当视点距离物体较远时候,viewDir被当做常量,相比Phong少了reflect计算入射光线在变化的n下的反射光线。可以提高性能。
float nh = max (0, dot (s.Normal, h));
float spec = pow (nh, s.Specular*128.0) * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);
c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;
return c;
}

inline fixed4 LightingBlinnPhong_PrePass (SurfaceOutput s, half4 light)
{
fixed spec = light.a * s.Gloss;
fixed4 c;
c.rgb = (s.Albedo * light.rgb + light.rgb * _SpecColor.rgb * spec);
c.a = s.Alpha + spec * _SpecColor.a;
return c;
}

猜你喜欢

转载自blog.csdn.net/Blues1021/article/details/78483884