前言
站内似乎很少出现和游戏开发或图形学相关的帖子,作为一个自学刚入门并总算找到了暑期实习的过来人稍微分享一下这次的找暑期实习相关的经验。
投递前的准备
首先说一下我做的前期准备。
图形学我是在大三上学期开始就有在课余时间读 虎书 来自学的了,当时看到了第9章左右,然后就因为别的事情暂时搁置了。
因为之前看虎书一直都是停留在理论上的学习,我希望有点实践以让自己更好地理解图形学。于是寒假期间我就跟着 LearnOpenGL 这个教程学了一点 OpenGL。
然后到了三月份开学,为了能让简历上有点项目可写,我决定实现一个软光栅化渲染器。首先我找到的就是知乎上很多大佬都推荐的一个项目 tinyrenderer,这个项目基本上就是只提供了两个最基本的库(图像读写和矩阵向量运算),然后带着你从零开始实现一个比较简单的500行左右的软光栅。跟着这个项目一步步来学其实并不会太难,但是直接复刻一个一模一样的项目放到简历上自然是没啥用的,所以我想对它加入一些新的功能。于是接下来我就跟着闫令琪老师为国内学子开设的免费网课 GAMES101(没做作业)重温了一下虎书里的内容,做好了加入新功能所需要的理论准备。因为个人更喜欢通过文字资料来学习,所以主要还是通过各位大佬们的课程笔记来学习:
- 孙小磊-计算机图形学系列笔记
- 灼灼炽风-GAMES101-现代计算机图形学入门-闫令琪——学习笔记
- PP-GAMES101:汇总-学习笔记
- marsggbo-计算机图形学随笔分类
最后,在三月底,我爆肝了几天写完了一个 基础的软光栅化渲染器,虽说一些像 PBR 这样的高级特性还没有实现,但也总算是做到了自己比较满意的程度了。(虽说天美的面试官一上来就给我挑了个bug就是了)
然后到了四月份,我才开始看面经和面试经典题,所以投实习的时间相对来说比较晚。不过从目前的面试经历来看我准备的这个项目确实也起到了一定的作用,起码能让一些面试官抓着项目来问一些我比较熟悉的内容,也算是没白费功夫吧。
所以到了最后我的简历上少数能看的亮点就是一块区域赛铜牌加这个项目了。
接下来是常规的面经了。
一、腾讯IEG 游戏客户端(已主动结束流程)
本来投的是另一个工作室的,虽然我也想着他们应该不会要没啥实战经验的实习生,但还是想面一下看看什么情况。没想到对面直接连面试机会都不给一个,面天美第一场到最后反问环节了我才知道原来现在是被天美捞了。
1、天美技术一面1.0(1.5h)
手撕算法:01矩阵中的最大全1子矩阵。
自我介绍。
项目+图形学:
- 一开头就指出我项目里 Shadow Mapping 有点小问题,模型的头部看不出来有阴影,然后等我思考了一小会无果后面试官直接告诉我应该是 shadow bias 设得太大了。(一开场就抓到问题了,害怕)
- PCF 怎么做的?
- 光栅化用的扫描线算法吗?(不是) 那怎么实现的?做了哪些优化?
- 渲染管线介绍一下。
- 在渲染管线过程中有哪些坐标空间?
- 法线贴图怎么做的?讲解 TBN 矩阵怎么算出来的?(直接打开画图推公式)
- 项目有做 Mipmap吗? 对 Mipmap 有了解吗?介绍一下它?怎么决定选取的层级?(当时答的是用短的那边做标准) 为什么是用短的一边做标准?(然后这个就没答上来了) 那各向异性有了解吗?
- PBR 有了解吗?(有试着去了解过,但暂时消化不来) 能和传统光照模型对比一下吗,哪怕是只看输入的参数?(面试官已经引导得很友好了,但我还没理解所以连渲染方程都想不起来,最后只好 pass 了)
- 齐次坐标有了解吗?它是用来做什么的?
- MVP 中哪个不是线性变换?
- OpenGL 的函数了解吗?最终绘制时调用的是什么函数?
C++:
- 有用 C++ 写过大的项目吗?
- C++ 新特性你知道的有哪些?实际使用中帮助最大的是?
- 智能指针介绍一下。
- 传参方式。
- __stdcall加在函数前有什么用。
- 内存五大区。
- 堆和栈比较。
- new 和 malloc 比较。
- 多线程了解吗?
- 设计模式有了解吗?单例模式写的时候要注意什么,它的使用场景是什么?
经历+吹水:
- 从 ACM 比赛中收获了什么?
- 身边应该没什么人想做游戏吧,为什么突然想向这个方向发展?
- 投的是客户端,为什么接触游戏开发不是从做具体游戏开始而是从图形学开始?(因为图形学很酷!) 图形学的什么让你觉得很酷?(真就变成吹水了?)
- 职业生涯规划?
- 你对游戏客户端和引擎岗各自有什么了解?
反问:
- 你觉得我今天表现如何?
- 对进一步学习有什么建议?
面试体验:
这个面试官面的节奏很快,一般都是我说完他马上就紧跟着追问的,而且中间也没太多停顿时间,除了前面半小时的手撕算法,后面一小时基本上双方的话头就没断过,这种一来一往的面试体验感觉很不错。
(在后面的天美技术二面2.0的反问环节我问面试官这是第几轮,结果他告诉我是第二轮,但实际上我在天美已经面了3场了,也就是说第一场天美技术一面1.0应该是没过的。不过我个人觉得这么多次面试里这一场是表现得最好的了,可能是面试官要求特别高吧。
2、天美技术一面2.0(40min)
自我介绍。
项目介绍。(介绍完面试官小声嘀咕了一句“确实挺基础的”,然后就全程没问我图形学了,估计是个图形学大佬。)
C++:
- 堆和栈的区别。
- 介绍一下野指针和空指针。
- 什么是多态?虚函数表和虚函数指针有了解吗?虚函数表每个对象各有一个还是共用一个?它存在内存的哪里?(这我还真不知道,面试完查了一下似乎标准没规定,都是由编译器的实现决定的。)
- STL 各种容器底层实现介绍一下。AVL 和红黑树对比一下。
- 智能指针介绍一下。
- 函数传参方式介绍一下。
- 给了份代码让我纠错,是关于传参时 char* 和 char** 的区别。
- std::sort 实现有了解吗?(没有) 如果让你来实现你怎么做?
- 内存对齐了解吗?
操作系统:
- 虚拟内存与物理内存的区别?(我中间用分页式举了下例子) 页表的结构是什么样的?页面置换算法有哪些?
- 线程安全有了解吗?
计网:
- tcp 与 udp 区别?怎么用 udp 实现 tcp 的可靠传输?
杂项:
- 怎么判断一个点在不在三角形内?(重心坐标)
- 给定射线起点与方向向量,再给点球心与半径,怎么判断会不会相交?(射线方程代进去球面方程后得到一元二次方程,解一下就行了) 有没有线代的做法?(当时脑抽了一下子想不出来,后来发现挺简单的)
- Cache 命中有了解吗?编程时怎么提高命中率?
- 编程时有遇到过内存碎片问题吗?怎么优化?(当时想着内存碎片不是 os 的事吗,就回答说没处理过不清楚了。事后想了下应该是指多次 new 或 malloc 分配到的内存可能东一块西一块,所以提前 malloc 好一大块后再在上面用 placement new 来创建对象,然后让申请的内存更连续这样子。)
嘴撕算法:
- 给 n 个矩形左上角右下角坐标,每个矩形还有一个颜色 (可能相同),现将它们按顺序叠放到平面上,问最终平面上怎样选择两个点能使得两点构成的矩形面积最大且内部颜色一致?(没想到什么好方法,只说了一个暴力的做法)
- 无向带权图,走的过程中最多可以免费地走 k 条边,问从给定起点到给定终点的最短路。(面试时口胡的是在原本的 spfa 上做一定修改的做法,后来查了下标准解法是分层图最短路)
反问:
- 你对我怎么评价?(没像之前的面试官那样直接回应,说还要综合评估一下)
- 现在面的还是天美还是换成了别的工作室?(是天美)
面试体验:
这个面试官基本上很少追问,也很少提示,都是等我回答完一个问题,然后就换另一个话题去了。感觉似乎他做面试官也不太熟练的样子?
3、天美技术二面2.0(40min)
自我介绍。
手撕算法:
最长公共子序列(当时一下子脑抽想不起来标解的 DP 方程了,甚至还把标解的复杂度记成了最长不下降子序列的标解的复杂度,搞得我想了很久怎样才能做到 O(NlogN),最后实在没办法就临时花了点时间想了一个丑一点但复杂度和标解一样的做法,结果最后调bug还没调好他就打断我问我打acm负责的是什么类型的题目了,可能觉得一个 ACMer 居然不能秒了 LCS 这种入门题很奇怪吧。)
C++:
- 虚函数有了解吗?
- 智能指针有了解吗?
- 手写一个
shared_ptr
的实现。(我写了一个版本之后他让我优化一下资源的获取,但当时我一直没听懂他要我优化的是到底哪个部分,最后就不了了之了。
经历+吹水:
- 有没有在实验室做过什么项目?
- 能实习多久?是不想读研吗?为什么不想读研?那你想做些什么?
- 想做 gameplay 还是渲染?
反问:
- 这是在面哪个工作室?是属于第几轮面试?如果通过了这一轮面试后面还有多少轮面试?
- 你希望实习生进来之前掌握一些什么?
面试体验:
没问多少东西,说不出什么体验来。但是让我改进 shared_ptr
的时候面试官也很友好地从不同角度提示了我,虽说我完全没get到就是了。
二、网易互娱 游戏研发工程师(已oc)
1、技术一面(1.5h)
开场手撕算法:给一个 w*h 的屏幕,现在有一个句子,句子由若干个单词组成,问最多能在屏幕上完整地输出多少次这个句子,要求句子的单词之间至少空一格,且一个单词不能分两行输出。
自我介绍。
项目:
- 有参考项目吗?在它之上做了哪些改进?
- MSAA 怎么做的?
- Mipmap 有做吗?(没有) 如果要做的话你准备怎么实现?
经历:
- 看简历上有打过 ACM,你在队伍里扮演什么样的角色?
图形学:
- 介绍一下 OpenGL 渲染管线。
- Stencil Test 有用过吗?它发生在什么时候?可以用来做什么?
C++:
- dynamic_cast 的用法介绍一下。(这里我理直气壮地说了一大堆,中间面试官还让我写代码演示一下,结果面试完发现自己理解错了emmmmm)
- static 有哪些用法?如果在头文件中声明一个 static 全局变量会怎样?如果要让多个文件共享一个全局变量要加什么?成员函数前加 static 会有什么作用?
操作系统:
- 虚拟内存的作用?
- 进程间通信的方法有哪些?挑一个深入讲一下。
计网:
- socket 有了解吗?
结尾手撕算法:最近公共祖先,面试官似乎是预期我写个 O(N) 的做法,结果我给他写了个 O(logN) 的倍增。
反问:
- 你对我怎么评价?
- 对接下来的进一步学习有什么建议?
面试体验:
这次的面试官在我回答完每个问题之后都会静静地等好一小会,经常都是我等了一会他还没反应,最后要我“嗯”一声他才继续问下去的,给我感觉好像我说的答案他还不满意一样,搞得我面试过程中挺慌的。但是反问环节他给的反馈却是“你应该自信一点,很多时候你说话的方式给人一种好像你不太确定的感觉,但实际上给出的答案却给人一种截然相反的印象。”
(很奇怪的是网易这边只面了技术一面然后就没了,甚至连hr面都没有,然后就直接发offer了。
总结
在大学瞎搞了这么多年终于也算是离当初自己做游戏的理想迈进了一步,不过现在回过头来看看的话,可能从大一起就不要去打ACM,而是把额外的精力集中到做各种游戏项目来,反而对于找相关岗位的工作来说会更好一点。不过到底情况会变好还是变坏我也无从验证就是了,毕竟时间都已经过去了。
从上面的面经可以看到在两家大厂面试的过程中问的更多的其实还是基础问题,甚至到了天美后面的几场,项目和图形学就没问了,所以各位想找游戏岗实习的小伙伴们在紧急时期还是先把基础复习好了再去搞一些锦上添花的东西比较好,不要像我这样弄得太晚。当然,最好的做法当然还是在大二左右就做出这种小项目来了,既不会占据掉复习基础的时间,也能给简历增加亮点。
希望这篇总结能给到有同样志向的小伙伴们一点帮助吧。