目录
Unity 面试题汇总(四)shader 图形学知识点相关
1、标准光照模型
2、灰度函数
3、亮度函数
4、Sobel边缘检测
5、描边实现方式
6、.三大主流的Shader Language
7、前向渲染和后向渲染
8.OpenGL中要用到哪几种Buffer?
9、Unity Shader 中的常用RenderType?
11、Unity的Shader中,Blend SrcAlpha OneMinusSrcAlpha这句话是什么意思?
12、点积和叉积的物理意义
13、2.OpenGL的渲染流程?
漫反射部分:
1.兰伯特
n世界法线,I世界光源的单位向量
2.半兰伯特
高光部分:
Phong光照模型
反射:reflect(-LightDir,normal);
光泽度,一般取64或者32,当然也可以自定义。
Blinn-Phong光照模型
h叫中间向量也叫半程向量,我听过的名字,然后把h当做reflect(反射向量)代入上面公式。
fixed gray(fixed4 color){
return (color.r * 0.299 + color.g * 0.518 + color.b * 0.184);
}
color.r = lerp(color.r, gray, _AmountColor);
fixed luminance(fixed4 color){
return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
}
color.r = lerp(color.r, luminance, _AmountColor);
// 返回值越小说明越接近边
half Sobel(v2f i){
const half Gx[9] = {-1,-2,-1,0,0,0,1,2,1};
const half Gy[9] = {-1,0,1,-2,0,2,-1,0,1};
half texColor;
half edgeX = 0;
half edgeY = 0;
for (int it = 0; it < 9; it++){
texColor = luminance(tex2D(_MainTex, i.uv[it]));
edgeX += texColor * Gx[it];
edgeY += texColor * Gy[it];
}
half edge = 1 - abs(edgeX) - abs(edgeY);
return edge;
}
1.视线法线夹角大于阈值修改颜色
2.后处理边缘检测(Sobel算子和模板缓冲)
3.法线外扩(观察空间为右手坐标系)(Cull front)
UnityViewToClipPos(ViewPos + viewNormal * -ViewPos.z *
_Outline * v.color.a *_zfactor);
在大多数情况下,我们可以通过Edit->Project Settings->Player->Other Settings->Rendering->Path中选择需要渲染的路径,默认是前向渲染路径。
但是我们也可以在Camera中单独设置这个摄像机的渲染路径。
在Shader中,通过指定Pass中的LightMode标签来实现:
Pass{
Tags { "LightMode" = "ForwardBase" }
前向渲染路径
传统且常见的渲染方式。
原理:
Unity将各种光照按逐顶点处理、逐像素处理、球谐函数SH等方法计算出并混合。至于怎么处理:
1. 最多有四个光源按逐顶点处理
2. 场景中最亮的平行光是逐像素处理的
3. 被设置成not important,会按逐顶点或SH处理
4. Important的会逐像素处理
5. 如果逐像素渲染的数量小于Quality Setting中的逐像素数量,则会有更多的光源进行逐像素处理
使用#pragma multi_compile_fwdbase这样的编译指令,可以让Pass生成所有需要的Shader变种。
延迟渲染路径
当场景之中包含大量光源的时候,前向渲染的性能会急速下降。所以需要延迟渲染。
延迟渲染使用了一个叫G-缓冲的缓冲区(G-Buffer)。
延迟渲染主要包含了两个Pass
一、在Pass1中,不进行任何光照计算,而仅仅计算哪些片元是可见的,通过深度缓冲技术,如果发现可见,则把它的相关信息存储到G-缓冲中。
二、在Pass2中,理由G-缓冲中的各种信息来进行真正的光照计算。
在Unity的延迟渲染中,每个光源都可以按照逐像素的方式进行处理,但也有缺点:
1. 不支持真正的抗锯齿功能
2. 不能处理半透明物体
3. 对显卡有一定要求
延迟渲染可以访问的内置变量:
_LightColor float4类型 光源的颜色
_LightMatrix0 float4x4类型 世界空间到光源空间的变换矩阵。可以用于采样cookie和光强衰减原理。
(1)帧缓冲(Frame Buffer)
(2)颜色缓冲(Color Buffer)
(3)模板缓冲(Stencil Buffer)
(4)顶点缓冲(Vertice Buffer)
(5)深度缓冲(Depth Buffer)
(1)Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。
(2)Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。
(3)TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。
(4)Background: Skybox shaders. 天空盒着色器。
(5)Overlay: GUITexture, Halo, Flare shaders. 光晕着色器、闪光着色器。
(6)TreeOpaque: terrain engine tree bark. 地形引擎中的树皮。
(7)TreeTransparentCutout: terrain engine tree leaves. 地形引擎中的树叶。
(8)TreeBillboard: terrain engine billboarded trees. 地形引擎中的广告牌树。
(9)Grass: terrain engine grass. 地形引擎中的草。
(10)GrassBillboard: terrain engine billboarded grass. 地形引擎何中的广告牌草。
修改sharedMaterial将改变所有物体使用这个材质的外观,并且也改变储存在工程里的材质设置。不推荐修改由sharedMaterial返回的材质。如果你想修改渲染器的材质,使用material替代。
作用就是Alpha混合。公式:最终颜色 = 源颜色 x 源透明值 + 目标颜色 x(1 - 源透明值)
两矢量点积,其中一矢量为单位矢量,结果为另一矢量在单位矢量上投影的长度。
两矢量叉积,其结果为一垂直于两矢量的新矢量。
读取顶点数据→执行顶点着色器→组装图元→光栅化图元→光栅化图元→执行片段着色器→写入帧缓冲区→显示在屏幕上。(不同的管线流程应该是有去别的,大体上是这样的)
Unity Shader的详细流程(昨天又有面试官问了,感觉讲详细的话很不错)?
(1)顶点数据
(2)几何阶段:
顶点着色器→曲面细分着色器→几何着色器→裁剪→屏幕映射(→传递数据给光栅化阶段)
(3)光栅化阶段:
三角形设置→三角形遍历→片元着色器→逐片元操作
(4)屏幕图像