不用拿原卷,也能摸清这份B卷的底牌。酷家乐2020校园招聘图形图像B卷,本质上不是在考你会不会某个特定的API,而是在考你有没有建立一套完整的图形学知识框架。作为过来人,我按当时的笔试经历、面经复盘和行业通用考点,把这份卷子背后的考察逻辑拆开揉碎讲一遍,顺便把备考路径也整理出来,希望能帮后面准备图形图像岗笔试的同学少走点弯路。
1. 酷家乐图形图像岗笔试到底在考什么
1.1 岗位方向决定了考点权重
酷家乐的主业是云设计平台,核心是WebGL渲染引擎、海量户型数据的实时预览、室内场景的灯光材质模拟,还有后来的BIM能力和AI辅助设计。这些业务场景决定了图形图像岗笔试的考察权重和一般游戏公司、视频处理公司明显不同。
先说权重分布。从我接触到的信息和身边同事的回忆来看,B卷的重点大概集中在几个方向:数学基础(矩阵、向量、几何计算)占比不低,渲染管线和光照模型是重头戏,光线追踪相关的基础概念也会被点到,剩下的就是数据结构和C++基本功。
这和酷家乐的实际业务是吻合的。户型图要实时渲染,就必须吃透光栅化管线和着色器;做全景图和渲染出图,就要理解光照模型和材质系统;处理百万级三角面片的场景,就绕不开空间加速结构。所以笔试不是在为难你,是在提前筛选具备这些底层能力的人。
1.2 难度定位和题型风格
整体难度属于“基础扎实就能过,但想拿高分要靠细节”的类型。B卷不会像ACM那样出特别偏的算法题,更多是把图形学知识点和工程实践结合起来考察。题目形式一般有选择题、简答题和手写代码题,手写代码基本集中在矩阵运算、几何计算这类能用几十行代码说清楚的题目上。
有一点值得注意:笔试题目往往把多个知识点串联起来。比如一道关于视图变换的题,表面上问的是矩阵,实际还要你理解相机坐标系、投影方式、裁剪空间,甚至深挖到Z-fighting问题。这种串联式的考察风格,是需要专门准备的。
2. 数学基础与几何计算:最容易拿分也最容易丢分的部分
2.1 矩阵变换与坐标系:不止会背公式
图形学笔试里,矩阵变换几乎是必考。B卷里常见的问法是给出一个物体在世界坐标系的坐标,要你求它在相机坐标系下的位置,或者反过来。这类题核心就一个:坐标系变换的本质是矩阵乘法,但你要搞清楚变换的顺序。
先记住几个关键点。OpenGL和很多图形引擎里,矩阵变换是右乘的,也就是说变换顺序是先从右往左读,物体先做局部变换,再做世界变换,然后是视图变换,最后是投影变换。写成公式就是:
P_clip = M_proj * M_view * M_model * P_local
这里P_local是物体局部坐标,依次经过模型、视图、投影矩阵,最终得到裁剪空间坐标。笔试中如果在矩阵乘法顺序上出错,整道题就废了。我见过太多同学把顺序搞反,得出的坐标差了好几个数量级。
另一个常考点是法线变换。常规模型矩阵可以直接变换顶点,但不能直接变换法线。因为模型矩阵包含非均匀缩放时,法线会被错误地拉伸。正确的做法是用模型矩阵的逆转置矩阵(inverse transpose)来变换法线。这道题如果考简答,答题思路要完整:解释为什么不能用原矩阵,再给出正确解法,最后提一下如果只做旋转和均匀缩放,原矩阵可以直接用。
实操建议是,复习的时候不要只看公式,要亲手推导几遍。把世界坐标系里的一个点经过平移、旋转、缩放后,再投影到屏幕上,完整地算一遍,比单纯背公式有用得多。笔试时遇到这类题,先在草稿纸上画出坐标系和变换流程,再动手算,能有效避免低级错误。
2.2 四元数与旋转插值:答出“为什么”才能拿高分
B卷如果有涉及旋转的题目,四元数是绕不开的。常见的问法是“为什么在三维旋转中要用四元数而不是欧拉角”。这种题不是让你写定义,而是考察你对问题本质的理解。
标准的答题框架应该是这样:欧拉角有三个问题,一是万向锁(gimbal lock),当两个旋转轴重合时丢失一个自由度;二是插值不自然,直接对欧拉角做线性插值,旋转路径会扭曲;三是拼接复杂,多次旋转的合成需要依赖矩阵乘法,计算量大且容易产生误差累积。四元数用四个分量表示旋转,没有万向锁问题,球面插值(slerp)能给出平滑的旋转路径,而且组合旋转只需要一次四元数乘法,效率很高。
我在实际笔试中遇到过一个变体:给了一个物体绕某个轴旋转一定角度的场景,要求写出四元数构造方式。这个也不难,四元数可以表示为:
q = (cos(θ/2), sin(θ/2) * (x, y, z))
其中(x, y, z)是旋转轴的单位向量。注意旋转轴必须先归一化,否则得到的四元数是错的。笔试时很多人死不瞑目,就是忘了归一化。
如果时间充裕,可以掌握四元数转旋转矩阵的公式。笔试中有些题目会要求你把四元数转换到矩阵表示,方便后续计算。这属于进阶技巧,但掌握了之后,相关题型基本都能秒杀。
2.3 几何相交测试:从原理到边界条件
图形学笔试里,几何相交测试是简答题的常客,最常见的莫过于射线与三角形求交。B卷如果考这个,大概率不会让你背Möller–Trumbore算法,而是让你写一个判断射线是否与三角形相交的函数。
这里有个高频考点:平面方程和重心坐标。一个比较完整的答题思路是:先用射线与三角形所在的平面求交点,然后判断该点是否在三角形内部。判断点在三角形内部有两种方法:一是重心坐标判断,把交点表示为三角形三个顶点的线性组合,如果三个系数都非负,则点在三角形内;二是同向法,通过叉积判断交点是否在三条边的同一侧。
写代码的时候要特别注意边界情况,比如射线与平面平行、交点在三角形顶点上、三角形退化成线段等。笔试和面试官交流时,主动说出边界处理方案,比只写一个完美核心逻辑更显工程素养。
另外一个常考的题目是AABB(轴对齐包围盒)的相交判断。这个看起来简单,但有个进阶版本很值得准备:对BVH(包围体层次结构)做遍历时,怎么用ray-AABB测试来提高效率。关键点是利用SLAB方法,分别计算射线进入和离开各个坐标轴方向包围盒的t值,取进入的最大值和离开的最小值,如果进入值小于离开值且离开值大于0,则相交。这个逻辑是构建加速结构的基础。
3. 渲染核心:光栅化、光照模型与着色器
3.1 光栅化管线的必考点
酷家乐要做实时的云端渲染,光栅化管线是核心。笔试里关于渲染管线的问题,考察重点集中在“每个阶段做了什么”和“数据如何流转”上。
经典流程需要背熟:顶点着色器(Vertex Shader)做坐标变换和顶点属性传递,图元装配(Primitive Assembly)把顶点连成三角形,光栅化(Rasterization)把三角形离散成片段(Fragment),片段着色器(Fragment Shader)计算每个片段的颜色,最后经过深度测试、模板测试、混合(Blending)等阶段,写入帧缓冲。
但只背流程不够,笔试真正想考的往往是流程背后的原理。比如:“深度测试为什么要在片段着色器之后?”答案是,片段的深度值可能在片段着色器中被修改,或者透明物体的混合需要特殊顺序。还有“为什么要做背面剔除?”这涉及三角形绕序(winding order)和性能优化,背面片元本来就不应该看到,提前剔除可以节省大量计算。
我在笔试中遇到过一道跟透视校正相关的题,很多人会栽在这里。光栅化时,纹理坐标、深度值等属性在屏幕上做线性插值是不对的,因为透视投影下空间中的直线在屏幕上并不按线性变化。正确做法是,对每个属性先除以w值,在屏幕空间做插值,再乘回w值,这就是透视校正插值(Perspective-Correct Interpolation)。如果直接线性插值,渲染出来的纹理会有明显的透视扭曲。这个点如果能答出来,会明显加分,因为很多人根本没意识到插值的坐标系问题。
3.2 光照模型:从Phong到PBR的演进逻辑
光照模型在B卷中基本属于必考,而且出题方式越来越倾向于对比分析。我记忆里有一道题是这样的:比较Phong光照模型和Blinn-Phong光照模型的区别,并说明为什么Blinn-Phong更高效。
常规答案是:Phong模型在计算镜面反射时使用反射向量R与视线向量V的点积,而Blinn-Phong使用半程向量H与法线N的点积。半程向量的计算是H = normalize(L + V),比求反射向量R更简单,而且Blinn-Phong的高光效果更柔和,在物理上更接近真实材质。这里要补充一个细节:如果问“为什么半程向量更高效”,你要提到半程向量只需要一次向量加法再归一化,而反射向量需要两次点积和一次向量减法的组合,计算量更高。
如果考PBR(基于物理的渲染),考点一般围绕Cook-Torrance BRDF模型展开。需要记住漫反射项和镜面反射项的组合方式,其中镜面反射项由法线分布函数(NDF)、几何遮蔽函数(Geometry)和菲涅尔项(Fresnel)三部分组成。笔试中可能只问你“菲涅尔项的作用是什么”,但如果在简答题中能主动画出整体公式并解释每一项的物理含义,会给阅卷人留下深刻印象。
这里我提供一个答题模板:
R = (1 - F) * (Diffuse / π) + F * (D * G / (4 * (N·L) * (N·V)))
其中D是法线分布函数,控制高光的形状;G是几何遮蔽函数,控制微表面的自遮蔽;F是菲涅尔项,控制反射率随角度的变化。考场答题时,把这几个名词用一句话解释清楚,再配上一个具体场景(比如金属材质和粗糙材质各自的特点),就非常完整了。
3.3 光线追踪题目怎么答才不丢分
虽然酷家乐主打实时渲染,但离线渲染中的光线追踪算法依然是图形学常识,B卷多多少少会涉及。常见考察点是:光线追踪的基本流程、BVH加速结构、以及光栅化和光线追踪的对比。
光线追踪的基本流程要会画框架:从摄像机出发,对每个像素生成一条光线,光线与场景求交,找到最近的交点,计算该点的直接光照,再递归追踪反射和折射光线,最终把颜色贡献累加起来。笔试中如果让你描述这个过程,一定要提到递归终止条件,比如最大深度限制或能量衰减阈值。
BVH是空间加速结构里的重点。它把场景中的几何体按照包围盒层次组织起来,遍历时先从根节点开始,如果光线与节点的包围盒不相交,就直接跳过整个子树,否则递归进入子节点。这种方式能把求交复杂度从O(n)降低到O(log n)级别。笔试中如果问“为什么用BVH而不是均匀网格”,要从场景适应性和构建成本两个角度答:均匀网格在物体分布不均匀时容易浪费存储空间,BVH则能够自适应地划分场景。
这里面有一个经典的扩展考点:BVH和K-d树的区别。核心区别在于分割方式:BVH是对物体集合按空间包围盒做层次划分,分割的是物体数组;K-d树是对空间本身做轴对齐分割,分割的是空间区域。如果题目让你针对一个稀疏场景设计加速结构,我建议优先选BVH,因为它的构建灵活度和查询效率在高散场景下都更好。
4. 场景管理、加速结构及性能优化
4.1 空间加速结构选型:不是只有BVH
笔试考到场景管理时,通常会出一道“给出一个场景,请你选择合适的加速结构并说明理由”这类开放题。对这类题,不能只答一个名字,要有对比和推理。
常见的加速结构有四种:网格(Grid)、八叉树(Octree)、K-d树、BVH。它们的适用场景各有侧重。网格适合物体分布均匀的场景;八叉树适合地形、体素等室外大场景;K-d树适合静态场景的光线追踪,因为它的构建成本较高,但查询效率高;BVH适合动态场景,因为物体的增删改相对容易,而且GPU友好。
回答这类题,我建议的框架是:先描述场景特征(物体数量、分布、静态还是动态),然后给出候选方案,最后做权衡取舍。比如题目是“一个室内的户型场景,包含大量墙面、家具模型,要在实时渲染中进行遮挡剔除”,就可以这样答:先用AABB粗粒度剔除不可见面,再用BSP树或八叉树管理场景层级,配合视锥体裁剪,最后通过硬件遮挡查询(Occlusion Query)做精确遮挡判断。这样整个逻辑链是完整的,阅卷人一看就知道你有工程实操经验。
4.2 遮挡剔除与LOD:实时渲染的常青考点
酷家乐的户型场景虽然规模不算特别大,但复杂户型加上精细模型,三角面片数量轻松破百万。这时候遮挡剔除和LOD(多层次细节)就是性能的救命稻草。B卷如果考到这类题,通常不是概念填空,而是让你设计一套具体的性能优化方案。
遮挡剔除的常见方案包括:视锥体裁剪、背面剔除、遮挡剔除(Occlusion Culling)和层次遮挡剔除。视锥体裁剪是最基础的,通过判断物体的包围盒与视锥体的六个面的关系,剔除完全在视锥体外的物体。背面剔除是靠三角形绕序判断,只渲染面向摄像机的三角形。遮挡剔除更复杂,它判断一个物体是否被其他物体完全挡住,常用方法有遮挡查询和GPU-driven的Hi-Z剔除。
LOD的核心思想是:根据物体距离摄像机的远近,使用不同精细度的模型。近距离用高模,远距离用低模,甚至直接切换成2D公告板(Billboard)。笔试如果考LOD,很大概率会问“如何避免LOD切换时的跳变”。答案是做过渡(Morph)或者使用连续LOD(如几何渐变、法线贴图混合),让模型在两个层级之间平滑过渡。能把这个问题答出来,说明你真正考虑过渲染质量,而不只是性能。
4.3 性能优化的答题套路
图形学笔试里的性能优化题,本质上是在考察“瓶颈分析”能力。看到这类题,先不要急着堆方案,而是要按“分析瓶颈—定位热点—针对性优化”的顺序展开。
一个比较通用的答题框架是:
- 首先明确渲染瓶颈在CPU还是GPU。如果是Draw Call过多,瓶颈在CPU;如果是像素填充率不足,瓶颈在GPU;如果是显存带宽不够,瓶颈在带宽。
- 然后根据瓶颈类型提方案。Draw Call过多用合批(Batching)和实例化(Instancing)解决;像素填充率不足用降低分辨率或提前深度测试解决;带宽不足用压缩纹理、减少Overdraw解决。
- 最后一定要提数据层面优化。比如使用静态模型合并、动态物体的空间分区管理、材质的Atlas化等。
我记得笔试中有一道题是“如何优化一个包含10万个物体的场景的渲染性能”。这个题没有标准答案,但高分答案一定是分层的:空间管理(八叉树/BVH)+ 视锥剔除 + 遮挡剔除 + LOD + 合批 + 纹理压缩。把这几层串起来,就是一个完整的可落地方案。
5. 数据结构与C++工程能力:图形岗的隐形门槛
5.1 为什么图形岗也要考C++内存
很多同学看到图形岗笔试题里出现C++题目,第一反应是“走错考场了”。但其实图形引擎本来就是C++写的,扎实的C++功底是图形岗的隐形门槛。B卷里C++相关题目一般集中在内存管理、指针与引用、STL使用和并发基础。
一个高频考点是智能指针。笔试可能让你比较shared_ptr、unique_ptr和weak_ptr的区别,并说明在图形引擎中如何选用。正确答案的关键在于理解所有权语义:unique_ptr表示独占所有权,适合不需要共享的对象;shared_ptr表示共享所有权,通过引用计数管理生命周期;weak_ptr是shared_ptr的观察者,不增加引用计数,常用于解决循环引用问题。
在图形引擎中,显存资源(纹理、缓冲)的管理通常不建议直接用shared_ptr,因为GPU资源的释放需要显式调用删除函数(如glDeleteTextures),而shared_ptr默认的析构行为并不适合。更常见的做法是自定义删除器,或者使用资源管理器(ResourceManager)统一管理生命周期。这些属于工程经验,笔试中能提到自定义删除器,就显得很内行。
5.2 手撕代码题:这些算法要提前练熟
图形岗笔试的手撕代码题一般不会太偏,常见的有这几类:矩阵运算(矩阵乘法、求逆、转置)、几何计算(点与三角形关系、线段相交判断、凸包)、图像基础(图像缩放、滤波、直方图均衡化)。
线段相交判断是高频题,代码量适中,适合考察基本功。判断两条线段是否相交,要分两步:先做快速排斥实验,再判断每条线段的端点是否在另一条线段的两侧(通过叉积的符号判断)。笔试时如果时间紧张,先写出快速排斥实验,再写跨立实验,基本就能拿全分。另外要特别注意共线的情况,这是最容易遗漏的边界条件。
凸包算法(Graham扫描或Andrew单调链)也是常考题。如果让你写凸包,优先选Andrew算法,因为实现更简单且不需要处理极角排序的特殊情况。其核心是:先把点按x坐标排序,然后分别构造下凸壳和上凸壳。这个算法复杂度是O(n log n),笔试中完全够用。
对于图像处理类代码题,有一个技巧:先确认图像数据的存储格式(是否连续内存、行对齐),再去处理像素。如果直接假设内存连续而忽略行对齐,在真实场景里很容易踩坑。笔试时虽然不会真的运行代码,但写出能考虑行对齐的代码,会是一个很好的加分项。
5.3 多线程与并发:渲染引擎的心跳
图形引擎普遍使用多线程架构:主线程负责游戏逻辑,渲染线程负责提交渲染命令,工作线程负责剔除、蒙皮、物理计算等。笔试如果考多线程,大概率不会太深,但会涉及数据竞争和同步机制。
一个典型的题目是“多个线程同时生成Draw Call数据,如何保证安全提交到渲染线程”。标准答案是使用命令缓冲区(Command Buffer):每个工作线程把渲染指令写入自己的缓冲区,然后在主线程或渲染线程统一合并并提交。这种方式避免了每帧多次加锁的开销,是引擎中常见的做法。
我在实际项目中用过的一种方案是:帧同步采用栅栏(Fence)机制,确保渲染线程在读取顶点缓冲数据时,工作线程不会覆盖这些数据。笔试中如果能把“避免每帧分配内存”“使用环形缓冲区(Ring Buffer)管理动态数据”这些工程细节写进去,会显得非常有经验。
6. 图像处理与Shader编程:图形图像不分家
6.1 图像滤波与特征检测:笔试的送分题
既然岗位叫图形图像,图像处理的基础概念也会涉及。B卷里图像处理考题的难度一般不大,主要集中在图像滤波、边缘检测和直方图处理上。
图像滤波的考点核心是卷积。均值滤波是简单的卷积窗口求平均,高斯滤波给窗口内的像素施加高斯权重,中值滤波则取窗口内像素的中位数。笔试中常问“高斯滤波和均值滤波的区别”,答题要点是:高斯滤波的权重随距离衰减,能更好地保留边缘信息,减少模糊带来的振铃效应;而均值滤波在边缘处会产生明显的模糊。
边缘检测的必考点是Sobel算子和Canny算子。Sobel通过计算图像在x和y方向的梯度幅值来检测边缘,实现简单但噪声敏感;Canny则通过高斯平滑、梯度计算、非极大值抑制、双阈值检测和边缘连接五个步骤,得到更细、更鲁棒的边缘。笔试中如果问“为什么Canny比Sobel好”,要重点提到非极大值抑制可以细化边缘,双阈值可以区分强边缘和弱边缘,这两个是Canny的核心优势。
直方图均衡化的题目也出现过。它通过累积分布函数重新映射像素值,使图像的对比度增强。答题时要写出核心公式:
s_k = round((L - 1) * CDF(k) / (M * N))
其中L是灰度级数,CDF(k)是灰度值k的累积频数,M*N是图像总像素数。能写出这个公式并解释它的作用,基本就能拿满这道题的分。
6.2 Shader编程题:GLSL和HLSL基本功
B卷中如果出现Shader相关题目,一般有两种形式:一种是让你写出一个简单的顶点/片元着色器;另一种是给你一段Shader代码,让你指出问题或优化建议。
写一个Blinn-Phong的片元着色器是经典题。核心步骤包括:接收法线、视线方向、光源方向,计算漫反射和镜面反射,最后输出颜色。这里要特别注意变换空间的一致性:法线和光线方向要么都在世界空间,要么都在切线空间,不要混用。
GLSL实现的核心代码长这样:
uniform vec3 uLightDir; uniform vec3 uViewDir; uniform vec3 uLightColor; uniform vec3 uBaseColor; in vec3 vNormal; out vec4 fragColor; void main() { vec3 N = normalize(vNormal); vec3 L = normalize(uLightDir); vec3 V = normalize(uViewDir); vec3 H = normalize(L + V); float NdotL = max(dot(N, L), 0.0); float NdotH = max(dot(N, H), 0.0); vec3 diffuse = uBaseColor * NdotL; vec3 specular = uLightColor * pow(NdotH, 32.0); fragColor = vec4(diffuse + specular, 1.0); }笔试中如果能顺手提一句“这里假设所有向量都在世界空间,实际项目中需要在顶点着色器把法线变换到世界空间”,就是切中要害的工程补充。另外要注意,如果考的是延迟渲染(Deferred Rendering),还需要多一个G-Buffer的写入阶段,核心是输出法线、颜色、深度等信息,供后续光照计算使用。
6.3 纹理映射与采样:容易被忽视的细节点
纹理相关的题目容易被忽略,但B卷偶尔会考。最常见的考点是纹理采样时的双线性插值和mipmap。
双线性插值的原理是:取纹理坐标周围四个最近的纹素,做两次线性插值得到最终采样结果。比最近邻采样效果好很多,消除了明显的锯齿块。笔试中如果问“为什么用双线性插值”,答题要点是:最近邻采样在纹理放大时会产生像素块,而双线性插值通过加权平均,让颜色过渡更平滑。
mipmap的考点是“为什么需要mipmap”和“mipmap如何选择层级”。答案有两个层面:一是避免远距离物体上的纹理闪烁(Aliasing),二是提升采样性能,因为缓存命中率更高。mipmap层级的计算公式是:
lod = log2(max(ddx_uv, ddy_uv))
其中ddx和ddy是纹理坐标在屏幕空间x和y方向的导数。这个公式在很多引擎里是自动计算的,但笔试中能写出来,说明你是真懂采样机制。如果题目是OpenGL环境,通常还可以提一句用glGenerateMipmap生成完整的mipmap链。
7. 高频题目类型与答题技巧实录
7.1 选择题和判断题的快速判断法
B卷的选择题和判断题,很大程度上是在考察概念是否“见血”。做题的时候有一个很重要的原则:把每个选项当成一个简答题来做,而不是只找正确选项。这样能逼自己排查概念上的模糊点。
举几个我见过的高频判断陷阱:
- “深度缓冲可以用来实现半透明物体的正确渲染”——这句话是错的。半透明物体需要从远到近排序渲染,深度缓冲只能处理不透明物体的遮挡关系。
- “纹理坐标在光栅化阶段做线性插值即可”——这句话也是错的。需要透视校正插值,不是普通线性插值。
- “欧拉角旋转没有万向锁问题”——错。万向锁正是欧拉角旋转的经典缺陷。
- “BSP树和BVH都可以直接用于动态场景”——不准确。BSP树构建代价很高,动态场景更适合用BVH。
这类判断题的陷阱通常藏在“绝对化”的表述里。看到“一定”“绝对”“完全可以”这类词,先打个问号,再回到图形学原理去验证,准确率会高很多。
7.2 时间分配:1小时笔试,这样安排最稳
图形图像B卷的题量一般不小,题海战术不可取,分配时间很关键。我建议按“简单—中等—困难”三段式答题:先把所有选择题和判断题快速做完,控制在15分钟内,这部分靠的就是平时积累;然后做简答题,每一道控制在5到8分钟,不要在某一道题上死磕超过10分钟,总共控制在30分钟左右;最后留出15到20分钟给手写代码题。
手写代码题有一个技巧:先写框架,再补细节。比如让你实现射线与三角形求交,先写出函数签名、输入输出、算法步骤的注释,再填充具体代码。万一时间不够,阅卷人也能看到你已经掌握了整体思路,能拿到大部分分数。千万别一上来就在细节里纠结,导致最后连框架都没写完整。
7.3 简答题的“金字塔”答题法
简答题是最能拉开差距的题型,给分逻辑通常是:要点分 + 解释分 + 工程经验分。我总结了一套“金字塔”答题法,从底层到高层分三层组织答案。
第一层是把核心概念直接说清楚。比如题目问“什么是法线贴图”,先答“法线贴图是一张存储了法线方向的纹理,用于在低模表面模拟高模细节”,一句话明确主体。
第二层是补充原理和数学关系。法线贴图存储的是切线空间下的法线方向,通过将切线空间的法线变换到世界空间,与光照方向做点积,计算出模拟的明暗变化。这一层能把普通回答和专业回答区分开。
第三层是加分项,加上实际工程经验。比如你可以补充:制作法线贴图时,注意切线空间的右手定则,避免法线方向翻转导致光照错误;也可以提低模的UV展开要连续,否则切线方向不一致,法线贴图会出现接缝。这类细节,通常是做过的项目才写得出来。
如果你能坚持用这套方法练习,把知识点都过成“三层”结构,笔试简答题的得分率会有明显提升。
8. 笔试后的复盘与长期储备
笔试只是第一道门槛,但也是检验知识体系是否完备的一面镜子。我当时考完之后做的第一件事,就是把不会做的题和模糊的选项全部整理成一个清单,逐个对照图形学教材和引擎源码去查。这个过程比单纯刷题有用得多,因为每个模糊点背后都对应一个知识盲区。
长期备考的资料,我比较推荐这几种搭配。理论方面,以《Real-Time Rendering》(第四版)为主线,结合闫令琪老师的GAMES101课程,建立完整的图形学框架;数学方面,把3Blue1Brown的线性代数系列视频过一遍,重点理解矩阵变换的几何意义;工程方面,读一读开源引擎的源码,比如Three.js的WebGLRenderer、OGRE的SceneManager,培养真实项目的代码感觉。
做题方面,不要只看图形学的经典题,还要多关注行业内的技术分享和招聘复盘。很多题目是行业内常规考点的变体,见多了解题速度和准确率自然就上去了。比如“为什么要用实例化绘制大量相同物体”“如何实现软阴影”“SSAO和SSR的原理区别”,这些高频工程题要提前准备好标准答案。
最后说一点我个人的感受。图形图像这个方向,入门有门槛,但越往后越吃底层功底。笔试考的不是死记硬背,而是你有没有把数学、渲染、数据结构和工程能力串成一条完整的链路。如果你在准备笔试时,不止满足于“会做这道题”,而是愿意追问“为什么这么设计”,那你离真正进入这个领域就不远了。希望这篇拆解能帮你少走一些弯路,祝笔试顺利。