Graphics-principle & PBR
Graphics-principle & PBR
渲染是什么
渲染是一个 CPU 驱动引擎,引擎驱动 OpenGL,OpenGL 驱动 GPU 修改显存的过程。
VRAM(显存)包括图像缓冲区、深度缓冲、顶点缓冲区、纹理图,显存大小经常决定了渲染的效率。
这是渲染的基础驱动流程,
Application -> Command -> Geometry -> Rasterization -> Fragment -> Display
下面我用伪代码大概写一下渲染管线需要做那些处理,方便理解。
渲染管线详解
- 描述了3D模型的几何数据结构;
- 几何体分为三角形。将变换应用于模型(即模型的三角形)称为模型变换;
- 我们有一个与眼睛相对应的虚拟相机。在相机上应用的变换称为“视图变换”;
- 为了提供3D效果,应用透视投影将3D模型转换为2D空间。这些被称为投影变换;
- 模型视图投影变换转换对象并将其放入屏幕空间。这些由MVP矩阵描述;
- 栅格化三角形以获得像素(它们被称为片段,直到到达最后阶段);
- 片段有阴影。它可以像使用插值颜色或复杂一样简单(应用光照和纹理来获得真实感);
- 片段被组合(混合)以获得单个像素。该组合可以是任何仲裁操作,如混合,或者像向观察者显示最近的像素一样简单;
概括来说,面剔除(遮挡剔除等),光栅化之后片段着色,最后输出颜色到显存中(图像缓存区)。
A shader is a small computer program that performs the necessary calculations to describe the appearance of a surface.
一个简单的着色器。vert&frag
使用shader language 编写的程序称之为shader program(着色程序)。着色程 序分为两类:vertex shader program(顶点着色程序)和fragment shader program (片断着色程序)。为了清楚的解释顶点着色和片断着色的含义,我们首先从阐 述GPU 上的两个组件:Programmable Vertex Processor(可编程顶点处理器,又 称为顶点着色器)和 Programmable Fragment Processor(可编程片断处理器,又 称为片断着色器)
整个渲染过程中,顶点处理器和片段处理器是属于可编程图形渲染管线。
顶点着色器控制顶点坐标转换过程;片段着色器控制像素颜色计算过程。这样就区分出顶点着色程序和片段着色程序的各自分工:
Vertex program 负责顶点坐标变换;
- 对象空间 -> 相机空间
- 相机空间 -> 齐次裁剪空间
- 齐次裁剪空间 -> 窗口空间
一般段数据包括 像素深度、顶点插值的颜色、差值得出的纹理坐标、像素位置等。
Fragment program 负责像素颜色计算;
像素最终的颜色可以简单地设置为顶点颜色的插值结果,也可以是纹理映射图中相应的数值,也可以是 PBR 计算出来的结果;
Vertex program 的输出是 Fragment program 的输入。
输出颜色之前会执行片段测试。
- 像素包含测试
- 裁剪测试
- Alpha测试
- 模板测试
- 深度测试
- 混合 -> 图像缓冲区
部分测试,GPU 会提到段着色之前,避免计算很多不需要的像素,以提高性能。
CPU 和 GPU 在渲染中承担的角色
- CPU 处理平截头体剔除和遮挡剔除以及BSP等场景管理算法,识别出潜在可视的网格实例,并把它们以及材质提供给 GPU 渲染(DrawCall);
- GPU 几何阶段和光栅化,上面已经详细介绍过了;
光照模型以及 PBR
光照模型
漫反射
粗糙的物体表面向各个方向等强度地反射光,这种等同地向各个方向散射的现象称为光的漫反射(diffuse reflection)。
diffuse = Kd x lightColor x max(N · L, 0)
- Kd is the material’s diffuse color,
- lightColor is the color of the incoming diffuse light,
- N is the normalized surface normal,
- L is the normalized vector toward the light source, and
- P is the point being shaded.
自发光
emissive = Ke
- Ke is the material’s emissive color.
高光
specular = Ks x lightColor x facing x (max(N · H, 0)) shininess
(pow shininess)
- Ks is the material’s specular color,
- lightColor is the color of the incoming specular light,
- N is the normalized surface normal,
- V is the normalized vector toward the viewpoint,
- L is the normalized vector toward the light source,
- H is the normalized vector that is halfway between V and L,
- P is the point being shaded, and
- facing is 1 if N · L is greater than 0, and 0 otherwise.
环境光
ambient = Ka x globalAmbient
- Ka is the material’s ambient reflectance and
- globalAmbient is the color of the incoming ambient light.
最终像素
surfaceColor = emissive + ambient + diffuse + specular
基于上面的算法,我写了个测试 Shader,通过 Shader Toggle 切换显示 Final Surface Color 各个组成部分。
See more detail…
LowpolyPBR
PBR
PBR 关键点:
- 光照现象,漫反射并不是各个方面平均发散,微表面模型(NDF);
- 菲涅尔定理(Fresnel),光源在边角处有更明亮的反光;
- 能量守恒,反射的光不能超过入射的光,遮挡因素,越光滑镜面越集中越亮;
- 线性空间;
PBR 算法主要有三项,F & D & G
F 是 Fresnel 反射系数(Fresnel reflect term),表示反射方向上的光强占原始光强的比率;
D 表示微平面分布函数(Beckmann distribution factor),返回的是“给定方向上的微平面的分数值”;
G 是几何衰减系数(Geometric attenuation term),衡量微平面自身遮蔽光强的影响。N 、V 、L 分别表示法向量、视线方向(从顶点到视点)和入射光方向(从顶点向外);
UNITY_BRDF_PBS 需要传入以下参数:
网上有很多 PBR 的 shader 我就不班门弄斧了,因为我也不太熟。
To be continue…
参考书籍
游戏引擎架构
3D 游戏与计算机图形学中的数学方法
GPU 编程与CG 语言之阳春白雪下里巴人
http://developer.download.nvidia.com/CgTutorial/cg_tutorial_chapter05.html