Shader 是运行在 GPU 上的程序,中文叫着色器。它的主要用途是给三维物体上色、计算光影、控制纹理颜色的呈现等。最终将游戏引擎中的几何数据转化为屏幕上的模型、场景和特效。
《绝地求生》、《绝地求生》、《战地》、《塞尔达传说》……都离不开着色器游戏开发,着色器被称为照亮虚拟世界的“魔法”。着色器还可以用于后期处理,类似于 Photoshop。
着色器是一组经过编译和链接的着色器。着色器使用 GL 着色器语言 (GLSL) 编写,其语法与 C 类似。
Shader 编程不仅考验开发技巧,也挑战程序员的想象力。有一句话说,会写 Shader 的程序员是站在食物链顶端的。如果你想成为游戏开发高手,Shader 编程是必备技能。
有兴趣为你的 3D 游戏添加纹理、灯光、阴影、法线贴图和环境光遮蔽吗?太棒了!今天,New Wisdom 为你带来了一个 Github 项目,教你如何从头开始进行 3D 游戏着色。
以下一系列着色技术是可移植性极高的技术,可在 Godot 和 Unity 中使用。借助这些技术,您的游戏视觉效果将提升到新的高度。
对于着色器之间的粘合剂,作者选择了神器 Panda3D 游戏引擎和 OpenGL 着色语言(GLSL)。
Panda3D 是一款功能强大的渲染引擎,核心渲染模块基于 C++ 开发,提供 Python 脚本接口。
本项目代码已在以下环境中测试过。
本文只对该repo做了简单的介绍,具体代码及解释请参考项目地址:
要运行示例代码,您需要构建
如果要运行示例代码,必须先编译它。根据平台安装相应版本的Panda3D。然后克隆项目仓库,进入目录,开始编译。
坐标系
在开始介入shader代码之前,需要先了解3D物体的坐标系。以及立体几何中坐标系的含义,绘制3D物体也需要x、y、z三个坐标轴的值。
将定义的坐标轴值转换成实际绘制的坐标游戏开发,需要进行五次坐标系转换。
模型空间
相对于原点 (0,0,0) 的自定义起点。
世界空间
世界空间是一个更大的坐标系,当所有物体绘制在一起时,它仍然是相对于原点的。它可以防止模型聚集在一起。
观察空间
将世界空间坐标转换为相机观察到的空间坐标。
剪辑空间
将一定范围内的物体按照我们的需求进行裁剪,而这个范围之外的坐标将会被忽略,本质上还是一个坐标操作。
屏幕空间
将坐标投影到屏幕上。
渲染到纹理
Render To Texture(RTT)是目前很多特效中用到的很基础的技术,实现起来很简单,但非常重要。
渲染到纹理是为了实现一些特殊的效果,比如一个光滑的球体,要能反射周围的环境,这时候就需要先渲染到纹理。
在此设置中,示例代码执行以下操作:
纹理和照明
纹理处理涉及使用 UV 坐标将某种颜色或其他类型的矢量映射到片段。U 和 V 的范围从 0 到 1。每个顶点都有一个 UV 坐标,并在顶点着色器中输出。
光照涉及计算和组合环境光、漫反射光、镜面反射光和反射光。示例代码使用 Phong 光照。
中风
笔触着色器需要输入纹理,用于检测边缘的颜色。此输入纹理的候选对象包括材质的漫反射颜色、漫反射贴图的颜色、顶点法线,甚至法线贴图的颜色。
雾化,全屏泛光
雾(或 Blender 中的薄雾)为场景增添了雾气效果,带来神秘感和柔和感。
Panda3D 提供了一个很好的数据结构来保存所有的雾参数,或者您可以手动将其传递给着色器。
Bloom有时也被称为Glow效果,中文一般叫“全屏泛光”,可以使发光的物体看起来更加真实。
屏幕空间环境光遮蔽 (SSAO)
环境光遮蔽 (AO) 是指几何物体的边角由于未被完全照亮(被相邻表面阻挡/遮挡)而变暗。屏幕环境光遮蔽技术使用屏幕空间场景的深度而不是真实的几何数据来确定遮蔽量。这种方法不仅比真正的环境光遮蔽速度快,而且取得了良好的效果,使其成为近实时环境光遮蔽的标准。
下面的动画展示了使用 AO 和不使用 AO 的区别。使用 AO 后,物体的角落会变得更暗,看起来更加真实。
景深
景深(DOF)是指相机对焦点前后相对清晰的成像范围。在光学特别是视频或摄影中,是对空间中可清晰成像的距离范围的描述。
虽然镜头只能将光线聚焦到某一固定的距离,离开这一点就会逐渐模糊,但是在一定距离内,图像模糊的程度是肉眼难以察觉的,这个距离就叫做景深。
景深越浅,虚化范围越大,虚化效果越明显;反之,景深越浅,虚化效果越弱。
色调分离和像素化
色调分离是指原本由紧密相邻的渐变色阶组成的图像被几个突然的颜色变化所取代。这种突然的变化也称为“跳跃阶跃”。色调分离实际上就是用来创建颜色分离效果的。
像素化 3D 游戏不仅趣味十足,而且无需手动创建所有像素图,节省了时间。结合色调分离,可以创造出真正的复古风格。
参考链接: