
图形图像方向的校招笔试岗位不同考察的侧重点差异非常大。有的公司偏应用考OpenCV、图像滤波、特征匹配有的公司偏引擎考OpenGL、渲染管线而像酷家乐这种以云设计和渲染引擎为核心业务的公司图形图像A卷几乎把重点全压在了底层数学、几何算法和渲染基础上。这套卷子我印象很深它不算偏门但覆盖面广不少题目看似简单实际隐藏了很深的坑。我身边当时好几个基础不错的朋友都栽在没有真正吃透坐标系变换和光栅化流程上。这篇就按我的理解把这张卷子背后的出题逻辑、核心考点、典型解法以及备考时容易踩的坑完整拆开聊一遍想投酷家乐图形图像岗位的应届生可以拿去参考。1. 从岗位定位反推试卷构成为什么图形图像岗位要考这些1.1 酷家乐的技术栈决定了笔试风格酷家乐的主业务是云端室内装修设计用户拖拽模型、改材质、调灯光所有操作都需要实时渲染预览最终还要输出效果图。这背后是一整套自研的渲染引擎和几何内核不是简单调一下Three.js就能搞定的。所以图形图像岗位招人第一个要求就是你得真的懂图形学底层而不是只会用引擎。笔试试卷往往就是岗位的一天先考察数学推导能力再考渲染流程的熟悉程度最后通过编程题看代码功底和空间想象力。A卷整体就是这个节奏。它不会考你某个API怎么调而是直接给你一个几何问题或者渲染场景让你从原理层面推演。如果光刷LeetCode而不涉猎图形学基础遇到这套卷子会非常难受。它考的不是“算法熟练度”而是“图形学直觉”。这种笔试风格本质上是在筛选有图形学知识体系的人而非纯代码选手。1.2 试卷模块的大致分布根据我看到的题目回顾和面试复盘A卷内容大致可以分为四个模块数学基础、几何算法、渲染基础、编程实现。数学基础部分主要考向量运算、矩阵变换、四元数几何算法部分偏重多边形处理、空间查询渲染基础考的是光照模型和管线流程编程实现则是以C或伪代码完成特定几何计算。这个分布其实很合理。酷家乐内部大量工作都围绕这几个方向展开显卡渲染需要扎实的数学和渲染知识户型识别和模型处理需要几何算法支撑而所有的能力最终都会落到代码实现上。2. 数学基础模块别小看坐标系变换和向量运算2.1 坐标系变换是必考中的必考图形学里最基础也最重要的内容就是坐标系变换。A卷几乎必然会有一道题让你推导或者计算物体从模型空间到世界空间再到相机空间的变换矩阵。这个知识点在酷家乐场景里有多常用呢你拖一面墙、放一个沙发、切换相机视角每一步都在做矩阵运算。这道题容易出错的地方不在矩阵乘法本身而在变换顺序。图形学中常用的约定是先缩放、再旋转、最后平移组合方式是 $M T \times R \times S$向量要左乘这个矩阵。很多人在学校学的是行向量右乘的表示方法两个习惯一旦混用答案就完全错掉。我自己就因为这个丢掉过分数后来养成了每次做题先写清楚“我采用列向量左乘约定”的习惯。如果你的目标是图形学岗位这里建议把以下内容练熟三维旋转矩阵的推导绕X/Y/Z轴、绕任意轴旋转的Rodrigues公式、视锥体的投影矩阵推导、正交投影与透视投影的区别。尤其是透视投影矩阵光记得公式不行得能推导出来不然考场上稍微变形就懵。2.2 向量运算和叉积点积的实际意义A卷中向量运算的题不会只让你求个点积结果通常会和几何意义挂在一起。比如用叉积判断一个点在三角形内部还是外部用点积计算两个向量的夹角或者用混合积判断四面体的体积。这类题酷家乐的高频应用场景是判断视锥体剔除、碰撞检测、多边形朝向等。点积的含义是一个向量在另一个向量方向上的投影长度叉积的结果是一个垂直于两个输入向量的新向量其模长等于两个向量围成的平行四边形面积。我在准备这类题时会把所有公式自己推导一遍确保在考场上不需要死记硬背因为笔试现场压力很大临时推导比回忆更可靠。另外还有一个小技巧平面法向量判断、凸多边形顶点顺序、旋转方向判断本质都是叉积的应用。把这些知识点串起来理解比单独背公式效率高得多。3. 渲染主题从光栅化到光照模型都要能徒手推导3.1 遮挡关系和深度缓冲是渲染题的常客A卷里渲染部分很可能会考深度缓冲的工作原理给定几个三角形在屏幕空间的投影位置要你判断哪些像素被哪个三角形覆盖以及最终颜色是什么。这道题其实是GPU光栅化过程的简化版考察的是对深度测试机制的理解。做这种题的关键是建立三维空间到屏幕空间的映射直觉。题目通常会给出相机参数和三角形顶点坐标你需要先做透视除法把坐标转换到NDC空间再映射到屏幕坐标最后通过重心坐标判断像素是否在三角形内并比较深度值。这里有一个很常见的坑透视除法做除法用的是w分量而w分量在透视投影矩阵中是根据距离变化的。如果距离远w值大除以w之后物体的屏幕尺寸就变小。如果忽略了这一步得到的坐标完全不可用。这道题考察的就是对“透视除法”这个细节的掌握程度。3.2 光照模型从Phong到PBR的基本概念酷家乐的渲染引擎实际使用的是PBR流程但对校招生的要求是至少能解释清楚Phong光照模型。A卷中很可能会让你写出Phong模型中环境光、漫反射、高光的计算公式并说明每一项的物理含义。// Phong光照模型的核心公式简化版 // I Ia Id Is // 环境光: Ia ka * Iambient // 漫反射: Id kd * (N dot L) * Ilight // 高光: Is ks * pow(max(dot(R, V), 0), shininess) * Ilight如果只是照抄公式考试分数会很低。出题人更希望你解释每一个点乘到底做了什么法线和光方向的点乘表示光照在表面上的分布反射向量和视线方向的点乘表示看到高光的可能性。要做的是理解公式背后的几何直觉而不是在考场临时背诵。从Phong扩展到Blinn-Phong也很常见区别仅仅是把反射向量与视线方向点乘换成了半程向量与法线的点乘。半程向量计算更高效结果也足够接近真实效果。我在实际写渲染器时也喜欢用Blinn-Phong效果比Phong稳定不会出现高光断断续续的瑕疵。4. 几何算法空间查询和网格处理是酷家乐的重头戏4.1 BVH加速结构性能优化的关键一环酷家乐的场景里有大量模型和三角面片如果每次都逐个测试所有三角形帧率会低到无法使用。所以BVH包围体层次结构几乎是必考的知识点。A卷里可能会出现让你描述BVH构建过程或计算某个包围盒的题目。BVH的基本思想是把场景中的物体递归地分组每个节点都是一个包围盒从根节点开始逐层向下查询。射线求交时如果射线没有命中某个节点的包围盒整个子树都可以跳过这样就实现了快速剔除。我复习时曾经花了一晚上手写BVH构建这段经历对理解这个数据结构帮助很大。核心量其实是选择划分轴和划分点并保证每个子树下的三角形数量相近。有些实现会使用表面积启发式算法来寻找最佳划分点考场上可能不会要求到这个深度但理解启发式的思路会让你的方案更从容。4.2 网格简化和多边形运算编辑器功能的底层支撑酷家乐编辑器里用户可以对模型进行拉伸、切割、对齐等操作这些操作背后都涉及多边形运算和网格简化。A卷可能出现的题型包括判断两个多边形是否相交、计算多边形面积、判断点在多边形内部射线法、合并两个网格的顶点。其中点在多边形内部的判断是最常考的。经典的射线法做法是从点出发沿任意方向发射一条射线统计与多边形边界的交点个数奇数则在内部偶数则在外部。需要注意射线经过顶点或与边重合的边界情况这些细节处理不好会让算法产生错误结果。// 射线法判断点是否在多边形内部伪代码 bool pointInPolygon(Point p, vectorPoint poly) { int count 0; for (int i 0; i poly.size(); i) { Point a poly[i]; Point b poly[(i 1) % poly.size()]; // 严格处理边界情况避免射线经过顶点导致误判 if ((a.y p.y) ! (b.y p.y)) { double t (p.y - a.y) / (b.y - a.y); double x a.x t * (b.x - a.x); if (x p.x) count; } } return count % 2 1; }上面这个实现其实已经处理了一部分边界问题用交点在点左侧的严格大于判断去规避射线穿过顶点时的歧义。但实际工程中我们会直接把边界情况抽出来单独处理例如给多边形顶点坐标加一个极小的偏移避免射线恰好经过某个顶点。这个细节在笔试的扩展题里被问到过。5. 编程题实操手写是检验图形学能力的试金石5.1 空间点的最近邻搜索一道能拉差距的经典题A卷的压轴编程题往往是这种风格给定一个点集合查询距离某个目标点最近的前k个点要求实现完整算法并分析复杂度。这题看似简单但如果直接暴力计算所有距离再排序在大数据量下显然不可靠。这道题实际上在考察空间数据结构kd树或八叉树的运用能力。我印象很深刻的是我当年实现kd树时忽略了一个重要环节选择划分维度时需要计算各维度下方差方差最大的维度作为切分维度这样可以减少树的深度、提升查询效率。如果只做最简单的“轮转维度切分”在某些数据集上构建出来的树会非常不平衡查询效率退化严重。// kd树构建的核心伪代码划分维度选择 int chooseSplitDimension(vectorPoint points) { int dim 0; double maxVariance -1.0; for (int d 0; d 3; d) { double mean 0.0; for (auto p : points) mean p[d]; mean / points.size(); double variance 0.0; for (auto p : points) variance (p[d] - mean) * (p[d] - mean); variance / points.size(); if (variance maxVariance) { maxVariance variance; dim d; } } return dim; }面试官通常还会追问一个扩展性问题如果点集是动态更新的如何维护查询效率。这个问题比kd树本身更难回答但也更能体现工程能力。对于动态场景可以采用向量化存储加重建的简单策略或者用更复杂的R树结构。如果能在笔试时主动提到这个扩展方向会是很扎实的加分项。5.2 三角形光栅化把数学公式变成可运行代码另一类高概率编程题是实现一个简单的三角形光栅化函数。输入是三个二维顶点输出是覆盖的像素列表要求使用重心坐标算法。这道题考察的是对GPU内部工作机制的理解程度。光栅化过程简单来说是先找到三角形的包围盒遍历包围盒内的所有像素计算出重心坐标检查三个分量是否都在0到1之间如果是这个像素就在三角形内部。这个算法效率可能不高但胜在逻辑清晰、容易实现是学习阶段最推荐掌握的方案。// 三角形光栅化基于重心坐标判断 void rasterizeTriangle(vec2 v0, vec2 v1, vec2 v2, vectorivec2 outputPixels) { int minX floor(min(v0.x, min(v1.x, v2.x))); int maxX ceil(max(v0.x, max(v1.x, v2.x))); int minY floor(min(v0.y, min(v1.y, v2.y))); int maxY ceil(max(v0.y, max(v1.y, v2.y))); for (int y minY; y maxY; y) { for (int x minX; x maxX; x) { vec2 p vec2(x 0.5f, y 0.5f); vec2 v0v1 v1 - v0; vec2 v0v2 v2 - v0; vec2 v0p p - v0; // 半面积法计算重心坐标 float denom v0v1.x * v0v2.y - v0v2.x * v0v1.y; float v (v0p.x * v0v2.y - v0v2.x * v0p.y) / denom; float w (v0v1.x * v0p.y - v0p.x * v0v1.y) / denom; float u 1.0f - v - w; if (u 0 v 0 w 0) { outputPixels.push_back(ivec2(x, y)); } } } }实现时最容易出的问题有两个。一个是坐标中心点的偏移像素中心是(x0.5, y0.5)而不是(x, y)不加偏移会导致三角形边缘反走样效果差另一个是浮点数精度误差导致边界像素闪烁在插值时需要加一个极小epsilon值。这些经验在面试聊到实战经验时非常有价值。6. 备考路线与校招复盘给准备投图形图像岗位的同学一些实在建议6.1 系统复习的路线规划如果你还有两到三个月准备时间建议系统过一遍基础线性代数向量、矩阵、特征值、微积分导数、极值、几何算法多边形、空间划分以及实时渲染基础管线、光照模型、阴影。参考书方面《Fundamentals of Computer Graphics》和《Real-Time Rendering》是图形学入门的经典读物不要求逐页精读但核心章节必须吃透。刷题方面LeetCode上标记几何、数学标签的题值得做一遍尤其是计算几何相关题目。但单纯刷LeetCode不够你需要自己动手实现一个小软件渲染器把光线投射、深度缓冲、纹理映射都实现一遍这会让你把零散知识彻底串联起来。我当年写完一个300行的软件渲染器之后对笔试里的光照题、光栅化题、坐标系变换题的把握感完全不同了。6.2 笔试现场的时间分配技巧笔试时间通常比较紧张建议按分值配比时间。数学基础题尽量10到15分钟内解决几何算法题每道控制在20分钟以内渲染题25分钟内编程题留40分钟以上写代码。如果某道数学题推导卡住了先跳过别因为一题卡住把后面的编程题时间吃掉。编程题即使代码写不完整也要把核心思路和伪代码结构写上去。阅卷人通常会更看重你对数据结构的选择和算法复杂度的分析而不是仅仅看最终结果。切记在提交前完成一轮自查特别是坐标系方向、浮点数精度、边界条件等图形学题目常见的坑。6.3 复盘时发现的几个容易忽略的细节准备这套卷子的过程中我发现自己好几次栽在同一个地方对矩阵乘法的顺序和行/列主序问题想当然。很多图形学题目本身不算难但如果在变换顺序上没写清楚整套题就全错了。建议考试时先明确约定使用的向量形式再开始计算这样阅卷老师也能看清你的思路。另外一个是关于BVH和kd树的选择问题。有些同学一听到空间加速结构就想用kd树但kd树更适合静态点集查询而BVH对动态物体、移动模型更友好。酷家乐的场景中模型经常移动所以BVH是更常见的选择。笔试时如果能区分不同数据结构的适用场景会让阅卷人觉得你真的理解这些结构的本质而不是只记住了名字。7. 图形图像岗位的长期成长路径校招笔试只是第一道门槛真正进入图形引擎领域后你会发现笔试里学的都是地基。无论是做渲染、做几何建模还是做性能优化都与这些基础密不可分。我见过不少实习生刚进入项目组时连最基本的AABB更新逻辑都要看很久原因就是笔试虽过但基础知识没有沉淀成自己的理解。我的建议是把笔试当成一次知识的系统梳理而不是临时抱佛脚。趁准备校招这个机会把坐标系变换、光栅化流程、加速结构、光照模型这些图形学核心知识全部打通对你入职后的前半年会非常有帮助。酷家乐的图形图像岗位能接触到的业务场景非常丰富从GPU渲染优化到户型图识别再到云端高性能计算对新人来说是一个能快速成长的环境。最后分享一个我个人的复习技巧准备一个笔记本每学完一个知识点试着用一张图和一段话把它讲给别人听。这个方法最大的好处是你被迫把糊弄自己的“好像懂了”变成真正清晰的逻辑链。笔试时可以不会写完整代码但关键思路必须一眼看穿。这种感觉只有经过大量推导和手动模拟之后才会真正建立起来。