计算机图形学相关知识
参考书籍:
《OpenGL Programming Guide 8th Edition》 — Addison Wesley
《Fundamentals of Computer Graphics (3rd Edition)》 — Peter Shirley, Steve Marschnner
《Real-Time Rendering, Third Edition》 — Tomas Akenine-Moller, Eric Haines, Naty Hoffman
Rendering Knowledge
在进入书籍内容的学习之前,先了解一些必要的知识
What is Rendering?
“Rendering is a process that takes as its input a set of objects and produces as its output an array of pixels.” — 《Fundamentals of Computer Graphics (3rd Edition)》
既然Rendering是通过处理一系列的对象数据最终输出成一组一组的像素呈现出来,那接下来的问题就是What is the rendering process(Graphic Pipeline)?
What is the rendering process(Graphic Pipeline)?
首先我们来看看wiki上对pipieline的解释
the sequence of steps used to create a 2D raster representation of a 3D scene.
那么结合Rendering的定义,不难看出Rendering pipeline就是一系列的操作(把前一个操作的输出当做输入)使得输入的对象数据最终以像素的形式输出到屏幕上
Note:
“A chain is no stronger than its weakest link.”
—Anonymous
渲染的速度是由最慢的阶段决定的。
图形渲染和GPU的是密不可分的。
渲染管线最大的变化就是从传统的固定渲染管线转变到了可编程的渲染管线。
在了解固定渲染管线和可编程渲染管线之前,先让我们来了解一下什么是Rendering Pipeline。
Rendering Pipeline Stages
Application
e.g collision detection, global acceleration algorithms, animation, physics simulation….. (On CPU)
Acceleration algorithms, such as hierarchical view frustum culling, are also implemented in this stage. — 《Real-Time Rendering, Third Edition》
可以看出Application阶段主要是做一些非渲染相关的一些计算,但部分计算也可以帮助我们减少渲染数量提高渲染效率(比如:hierachical view frustum culling)Geometry
Deal with transforms, projection. Computes what is to be draw, how it should be drawn, and where it should be drawn (On GPU)
e.g. model and view transform, vertex shading, projection, clipping, and screen mapping — 《Real-Time Rendering, Third Edition》
可以看出Geometry阶段主要是负责3D到2D Screen的顶点运算和顶点剔除Rasterizer
Conversion from two-dimensional vertices in screen space – each with a z-value (depth value), and various shading information associated with each vertex – into pixels on the screen (On GPU) — 《Real-Time Rendering, Third Edition》
可以看出Rasterizer阶段主要是负责2D Screen的顶点像素运算(包括Z-Buffer test, Color computation, Alpha test, Stencil buffer等)
Accumulation Buffer — Images can be accumulated using a set of operators. E,g, motion blur……
让我们结合OpenGL Rendering Pipeline来学习理解:
从上图可以看出,OpenGL的第一个阶段Vertex Data相当于Application阶段所收集的数据
不难看出从Vertex Shader到Clipping都属于从3D到2D Screen的顶点运算和顶点剔除,所以这一部分处于Geometry阶段(由于后来统一架构的(US)原因,Vertex Shader, Geometry Shader, Pixel Shader很多)
而从Rasterization到最后的屏幕输出都是对像素的运算,所以是Rasterizer阶段
OpenGL更多的学习了解
了解了什么是Rendering Pipeline之后,让我们来看看什么是固定管线和可编程管线?他们之间的关系是怎样的?
传统的固定渲染管线
那么什么是PSU(像素着色器单元)?什么是TMU(纹理贴图单元)?什么是ROP(光栅化引擎)了?
在统一渲染架构(US(Unified Shader))出现之前有单独的顶点着色器单元和像素着色器单元,分别负责顶点数据和像素处理。
TMU(纹理贴图单元 — Texture Mapping Unit)
归根到底就是对材质的贴图和过滤操作。根据程序的需要,在完成几何处理和光栅化之后,TMU单元会从材质库中找出合适的纹理贴在对应的位置上以实现模型的外形完整化”
在可编程渲染管线(Shader)出现后,程序员可以实现对像素级别上的操作,可以实现更加真实的效果(预先烘焙的材质无法真实的实时渲染)。Vertex Texture Fetch(顶点纹理拾取)的出现允许Vertex Shader直接访问材质的一些信息,这也算是TMU进军GPGPU的一个契机。
从DirectX 9.0C开始,TMU单元正式分割成了TA和TF两个部分,TA单元专门负责材质的定址操作,在完成定址之后,TF单元根据定址结果对材质进行拾取并完成贴图作业。
后续改进纹理阵列(处理材质操作的纹理单元阵列)以及Gather指令(Gather指令的作用,在于允许单元从非连续存储器地址中直接读取数据。)
Computer Shader的出现也使得纯数学的纹理计算成为了可能。
ROP(光栅化引擎 — Render Output Units)
The render output unit, often abbreviated as “ROP”, and sometimes called (perhaps more properly) raster operations pipeline.
Conversion from two-dimensional vertices in screen space – each with a z-value (depth value), and various shading information associated with each vertex – into pixels on the screen (On GPU) — 《Real-Time Rendering, Third Edition》
可编程渲染管线
为什么会有可编程渲染管线了?
“由于传统的渲染管线不可编辑性,实现的图像效果受到很大限制,Shader(着色器)的引入就替代了传统的固定渲染管线,实现了可编程的渲染管线,各个Shader(着色器)替代了固定渲染管线中相应的功能。”
那么什么是Shader(着色器)?Shader(着色器)和GPU硬件的关系是怎样的了?
“Shaders are programmed using C-like shading languages such as HLSL, Cg and GLSL. These are compiled to a machine-independent assembly language, also called the intermediate language(IL). This assembly language is converted to the actual machine language in a separate step, usually in the drivers. This arrangement allows compatibility across different hardware implementations.” — Real-Time Rendering, Third Edition》
GPU的像素着色器单元和顶点着色器单元就对应了Shader里面的Pixel Shader和Vertex Shader。由于像素在计算机都是以RGB三种颜色构成,加上Alpha总共4个通道,所以GPU的像素着色器单元和顶点着色器单元一开始就被设计成为同时具备4次运算能力的算数逻辑运算器(ALU)
从上面可以看出Shader是machine-independent的,因为事先被编译成了与机器无关的intermediate language(This intermediate language can be seen as defining a virtual machine, which is targeted by the shading language compiler — 《Real-Time Rendering, Third Edition》), 最后才会被机器转换成机器码来运行.
可编程Shading进化史可参考
3.3 The Evolution of Programmable Shading — 《Real-Time Rendering, Third Edition》
计算机架构与Shader的关系
非同一架构
那么影响Pixel Shader和Vertex Shader速度的因素又是什么了?
数据流处理速度。
我们都知道计算机是通过发送指令来对数据进行处理的,而计算机架构则是对指令流和数据处理的设计,是影响数据流处理速度的关键。
根据Flynn分类法,计算机架构分为:
- SISD(Single Instruction Signle Data Stream) — 单指令单数据流
“传统的顺序执行的计算机在同一时刻只能执行一条指令(即只有一个控制流)、处理一个数据(即只有一个数据流),因此被称为单指令单数据流计算(Single Instruction Single Data Stream,SISD)” - MIMD(Multiple Instruction Multiple Data Stream) — 多指令多数据流
“而对于大多数并行计算机而言,多个处理单元都是根据不同的控制流程执行不同的操作,处理不同的数据,因此,它们被称作是多指令流多数据流计算机,即MIMD(Multiple Instruction Stream Multiple Data Stream,简称MIMD)计算机,它使用多个控制器来异步地控制多个处理器,从而实现空间上的并行性。” - SIMD(Single Instruction Multiple Data Stream) — 单指令多数据流
- MISD(Multiple Instruction Single Data Stream) — 多指令多数据流
那么各个计算机架构设计之间的优势和劣势分别是什么了?
还记得我们之前说的像素着色单元和顶点着色单元已开被设计成具备4次运算能力的算数逻辑运算器(ALU)吗?
因为数据的基本单元是Scalar(标量),GPU的ALU一个时钟周期可进行四次这种变量并行运算。
那么如果我们传入4D标量进行运算,SIMD可以最大程度满足我们的需求,达到GPU利用率100%。但如果我们传入1D标量进行运算,SIMD的效率就会下降到原来的四分之一(随着API的更新,1D/2D/3D等混合指令开始大幅出现),固传统的SIMD架构效率开始降低。而3D+1D/2D+2D等混合架构设计也并不能最大限度利用ALU运算能力,这也是统一架构出现的契机。
统一架构
统一架构出来以后,因为有了US(Unified Shader)单元,指令直接面向底层的ALU而非特定单元,所以后来的N卡统一架构把原来的4D着色器单元完全打散,流处理器(SP)统统由矢量设计改为了标量运算单元(由4D矢量运算器改为了1D标量运算器),采用的是MIMD架构。
MIMD架构相比SIMD架构需要占用更多的晶体管数,因为4个1D标量ALU和一个4D矢量ALU的运算能力是相当的,但前者需要4个指令发射端和4个控制单元,而后者只需要1个
而A卡的流处理器(SPU)依然采用的是SIMD(单指令多数据流)架构,每个SPU内包含了5个ALU。
N卡的第二次革新引入的atomic单元以及SIMT(Single Instruction Multiple Thread)特性对N卡并行化设计起到了先到作用。
Shader Virtual Machine (Shader Model)
了解了计算机架构与Shader的关系,让我们来看看Common-shader core virtual machine architecture and register layout吧
Input Type
Uniform inputs
With values that remain constant throughout a draw call(but can be changed between draw calls) — accessed via read-only constant registers or constant buffersVarying inputs
Which are different for each vertex or pixel processed by the shader — accessed via varying input registers
Shader Knowledge
Shader
Shader programs can be compiled offline before program load or during run time. As with any compiler, there are options for generating different output files and for using different optimization levels. A compiled shader is stored as a string of text, which is passed to the GPU via the driver.
MRT(Multiple Render Target)
MRT is a feature of modern graphics processing units, that allows the programmable rendering pipeline to render images to multiple render target textures at once. These textures can then be used as inputs to other shaders or as texture maps applied to 3D models.
?不是非常明白这里。大概是一次渲染可以对象信息存储在多个buffer里,然后以texture的形式交给后续pass的pixel shader做处理
wiki上提到MRT的一个使用deferred shading
在first pass的时候收集相应信息存储在特定buffer里,在second pass(真正的渲染绘制是在这里)的时候Pixel shader把这些信息用作渲染数据,把整个场景一次性渲染出来而不是针对每个空间物体进行光照,材质等渲染
Effects
什么是Effects文件了?
可以看出Effects文件主要是记录一系列的渲染状态和固定信息用于特定渲染流程里。
为什么需要Effects文件了?
在我们事先特定效果的渲染时,不仅需要一系列的shader文件,我们同时会设定相应的渲染状态和一些固定的渲染信息,这些状态和信息对于特定效果来说是固定不变的,所以通过Effects文件可以有效的帮助我们记录特定效果所需的渲染状态等信息,方便重复使用。
Effects Languages
Such as HLSL FX, CgFX, and COLLADA FX
Shader Models Comparision
渲染总结
可编程管线的出现主要是由于固定管线能实现的渲染效果有限不够灵活,Shader的出现象征着可编程管线的诞生。
统一渲染架构主要是为了提高ALU(算数逻辑运算器)利用率的问题。US(Unified Shader)单元的出现象征则统一渲染架构的开始,指令直接面向底层的ALU而非特定单元,流处理器的数量成为了性能的关键,流处理器的设计和架构紧密相关。(并行分块花渲染也随之出现)