提示:本篇将会非常长~
本系列文章分为
硬件
编程入门
工程实践
上一篇
主要介绍了GPU的特征工作原理 以及渲染的底层流程 其实对于新架构而言还有所不同
Shader描述了如何渲染物体的信息,包括:
Texture Setup、纹理设置
Material Property、材质设置
Render State、渲染状态
Blend Setup、混合设置
Pixel Shader、像素着色
Vertex Shader、定点着色
Render Target Setup 渲染目标设置
Shader并不直接和几何体相关联,因为对于同一个几何体,有可能会用不同的Shader来渲染。
为了简化描述我们来定义一下:
vs: vertex shader, 顶点处理/多边形处理的
ps: pixel shader, 处理像素单位的阴影和处理相关纹理
以上两种shader都是可编程的
在各自的着色器单元(Shader Unit)上,有着把各种各样的Shader程序来实现为3D图形的处理的结构。而且,作为用语,如果直接说[Programmable Shader],有指双方(VS和PS)的情况,或者是指这个整体的概念。
并且,由于这个Shader程序是软件,开发者可以自己制作独创的Shader程序,就可以在GPU上实现新的图形功能。
但是在之前的着色器架构中无法面对任务的调节 造成闲置资源
而在现有的统一着色器架构下 资源配置得到了有效保障
所以在DX11之后通用shader架构得到了广泛使用 比较理想的过程是:
当然
以上看不懂也无所谓 因为这个是软件之前的一点小铺垫。
正式篇前导一,纹理?材质?贴图?
整个 CG 领域中这三个概念都是差不多的,在一般的实践中,大致上的层级关系是:
材质 Material包含贴图 Map,贴图包含纹理 Texture。
而我们要说的时更广泛应用的概念
纹理
是最基本的数据输入单位,游戏领域基本上都用的是位图。常见格式有PNG,TGA,BMP,TIFF此外还有程序化生成的纹理 Procedural Texture。
在内存中通常表示为二维像素数组。
贴图
英语 Map 其实包含了另一层含义就是“映射”。其功能就是把纹理通过 UV 坐标映射到3D 物体表面。贴图包含了除了纹理以外其他很多信息,比方说 UV 坐标、贴图输入输出控制等等。
一张图便能说明其之间的关系
材质
本质就是一个数据集,主要功能就是给渲染器提供数据和光照算法。贴图就是其中数据的一部分,根据用途不同,贴图也会被分成不同的类型,比方说 Diffuse Map,Specular Map,Normal Map 和 Gloss Map 等等。另外一个重要部分就是光照模型 Shader ,用以实现不同的渲染效果。
贴图种类繁多:我做个不完全总结
Diffuse Map -
漫反射贴图/也被称作反照率贴图albedo map 存储了物体相应部分漫反射颜色
Normal Map -
法线贴图 本质上存储的是被RGB值编码的法向量 表现凹凸,比如一些凹凸不平的表面,光影在表面产生实时变化 常用来低多边形表现高多边形细节 比如在高多边形下生成normal map在匹配给低多边形模型 是一种常见的降低性能要求的做法
对于讲解normal map来说这篇文章很值得借鉴
N’= N + D =[0,0,c]+ D =[a,b,c]
a = -dF/du * 1/k
b = -dF/dv * 1/k
c = 1
常规来说就是光向量和法向量的点积来确定明暗以表现凹凸质感,也就是把法线存在纹理中
我们又会发现另外一个奇怪的地方
法线贴图的颜色为什么都这么怪?
事实上,真正的法线贴图并不是记录贴图上每个点的法线的绝对角度,而是记录的是相对于平面的一个差值。这样的话,随着平面的3D变换都能够实现即时的法线运算了。而借RGB数据存储的法线信息会被法线方向扰动,于是在RGB(x,y,z)上的平均分布空间上 x,z 值较大或者y得值比较大 因此表现出来合成的结果上普遍是紫色(xz)代表面 而绿色(y)反应深浅
Specular Map -
高光贴图 表现质感 高光区域大小可真实反映材质区别
Gloss Map -
光泽贴图,每个纹理元素上描述光泽程度
而讲解贴图和纹理的工作机理中这篇博客讲的很不错
总体上说 他们都是要被shader加工的原材料
正式篇前导二,光照模型?
我们先来探讨一下几个问题
1. 当一个物体能被我们看见需要具备什么因素 ?
2. 当一个物体是不同材质的时候,视觉上的区别在哪里?
带着这两个问题 我们来说一下 什么是光照模型
它总结了在什么情况下 一个物体能够被看见 以及以一个近似的概念描述了真实情况下光照的种类
基础-Phone式光照模型(Phone reflection model)
真实世界中的光照效果抽象为三种独立的光照效果的叠加
1.环境光(Ambient)
此为模拟环境中的整体光照水平,是间接反射光的粗略估计,间接反射的光使阴影部分不会变成全黑 关于环境光还有个事实,1某个可以独立分析的局部场合的环境光强和能够进入这个地方的光的强度有关。
其计算公式为:
2.漫反射光(Diffuse)
模拟直接光源在表面均匀的向各个方向反射,能够逼近真实光源照射到哑光表面的反射。比如在阳光下,由于路面粗糙的性质,我们发现从任意一个角度观察路面,亮度都是差不多。
其计算公式为
3.镜面反射光(Specular)
模拟在光滑表面会看到的光亮高光。会出现在光源的直接反射方向。镜子、金属等表面光亮的物体会有镜面反射光。镜面反射光同时与物体表面朝向、光线方向、视点位置有关。如图
I是入射光,N是表面法线,R是反射光线,V是从物体上的目标观察点指向视点的向量,a是V和R的夹角。
我们可以判断出一个规律,夹角a越小,即视线与反射方向的偏离越小,则目标点的光强越大
其计算公式为:
Ks为物体对于反射光线的衰减系数
Shininess为高光指数
高光指数反映了物体表面的光泽程度。
Shininess越大,反射光越集中,当偏离反射方向时,光线衰减的越厉害,只有当视线方向与反射光线方向非常接近时才能看到镜面反射的高光现象,此时,镜面反射光将会在反射方向附近形成亮且小的光斑;
Shininess 越小,表示物体越粗糙,反射光分散,观察到的光斑区域小,强度弱。
以上所在的公式都是便于理解的形式 实际要复杂得多
最后可得:
其组成类似于
至于更多的光照模型结合了更多的物理光学等信息 在模拟单种材质例如塑料 合金 石膏陶瓷等等上要好于Phone式模型的效果 但是基本上属于Phone式模型的扩充
有了以上基础概念 我们就可以更好的理解shader的编写了
正式篇第一节 扫盲
前一章提到了 可编程shader分为vertex (顶点)/fragement(片段) shader
其可由多种语言去编写 比如CGSL/HLSL/CG
我们先来比较一下 三种主流语言的优缺点
GLSL:
基于OpenGL的OpenGL Shading Language