使用Direct3D有两种方式渲染视频:
Surface和Texture。使用Surface相对来说比使用Texture要简单一些,但是不如使用Texture灵活。
Surface和Texture。使用Surface相对来说比使用Texture要简单一些,但是不如使用Texture灵活。
抽象概念
Direct3D的抽象概念包括:Devices(设备),Swap Chains(交换链)和Resources(资源)。
Device(设备)用于渲染3D场景。例如单色设备就会渲染黑白图片,而彩色设备则会渲染彩色图片。Device目前我自己了解的有以下2类:
HAL(Hardware Abstraction Layer):支持硬件加速的设备。在所有设备中运行速度是最快的,也是最常用的。
Reference:模拟一些硬件还不支持的新功能。换言之,就是利用软件,在CPU对硬件渲染设备的一个模拟。
每一个Device至少要有一个Swap Chain(交换链)。一个Swap Chain由一个或多个Back Buffer Surfaces(后台缓冲表面)组成。渲染在Back Buffer中完成。此外,Device包含了一系列的Resources(资源),用于定义渲染时候的数据。每个Resources有4个属性:
Type:描述Resource的类型。例如surface, volume, texture, cube texture, volume texture, surface texture, index buffer 或者vertex buffer。
Usage:描述Resource如何被使用。例如指定Resource是以只读方式调用还是以可读写的方式调用。
Format:数据的格式。比如一个二维表面的像素格式。例如,D3DFMT_R8G8B8的Format表明了数据格式是24 bits颜色深度的RGB数据。
Pool:描述Resource如何被管理和存储。默认的情况下Resource会被存储在设备的内存(例如显卡的显存)中。也可以指定Resource存储在系统内存中。
渲染流水线(rendering pipeline)
Direct3D API定义了一组Vertices(顶点), Textures(纹理), Buffers(缓冲区)转换到屏幕上的流程。这样的流程称为Rendering Pipeline(渲染流水线),它的各阶段包括:
Input Assembler(输入组装):从应用程序里读取vertex数据,将其装进流水线。
Vertex Shader(顶点着色器):对每个顶点属性进行着色。每次处理一个顶点,比如变换、贴图、光照等。注意这个地方可能需要自己编程。
Geometry Shader(几何着色器): Shader Model 4.0引进了几何着色器,处理点、线、面的几何坐标变换。此处我自己还不是很了解。
PS:上述处理完后的数据可以理解为以下图片。即包含顶点信息,但不包含颜色信息。
Stream Output(流输出):将Vertex Shader和Geometry Shader处理完成的数据输出给使用者。
Rasterizer(光栅化): 把算完的顶点转成像素,再将像素(pixels)输出给Pixel Shader。这里也可执行其他工作,比如像素数据的切割,插值等。
PS:光栅化的过程可以理解为下图。即把顶点转换成像素。
Pixel Shader(像素着色器):对每个像素进行着色。注意这个地方可能需要自己编程。
Output Merger(输出混合):整合各种不同的数据,输出最后结果。
视频显示的基础知识
在记录Direct3D的视频显示技术之前,首先记录一下视频显示的基础知识。我自己归纳总结了以下几点知识。
1.三角形
在Direct3D中经常会出现“三角形”这个概念。这是因为在3D图形渲染中,所有的物体都是由三角形构成的。因为一个三角形可以表示一个平面,而3D物体就是由一个或多个平面构成的。比如下图表示了一个非常复杂的3D地形,它们也不过是由许许多多三角形表示的。
因此我们只要指定一个或多个三角形,就可以表示任意3D物体。
2.后台缓冲表面,前台表面,交换链,离屏表面
后台缓冲表面和前台表面的概念总是同时出现的。简单解释一下它们的作用。当我们进行复杂的绘图操作时,画面可能有明显的闪烁。这是由于绘制的东西没有同时出现在屏幕上而导致的。“前台表面”+“后台缓冲表面”的技术可以解决这个问题。前台表面即我们看到的屏幕,后台缓冲表面则在内存当中,对我们来说是不可见的。每次的所有绘图操作不是在屏幕上直接绘制,而是在后台缓冲表面中进行,当绘制完成后,需要的时候再把绘制的最终结果显示到屏幕上。这样就解决了上述的问题。
实际上,上述技术还涉及到一个“交换链”(Swap Chain)的概念。所谓的“链”,指的是一系列的表面组成的一个合集。这些表面中有一个是前台表面(显示在屏幕上),剩下的都是后台缓冲表面。其实,简单的交换链不需要很多表面,只要两个就可以了(虽然感觉不像“链”)。一个后台缓冲表面,一个前台表面。所谓的“交换”,即是在需要呈现后台缓冲表面中的内容的时候,交换这两个表面的“地位”。即前台表面变成后台缓冲表面,后台缓冲表面变成前台表面。如此一来,后台缓冲表面的内容就呈现在屏幕上了。原先的前台表面,则扮演起了新的后台缓冲表面的角色,准备进行新的绘图操作。当下一次需要显示画面的时候,这两个表面再次交换,如此循环往复,永不停止。
此外,还有一个离屏表面。离屏表面是永远看不到的表面(所谓“离屏”),它通常被用来存放位图,并对其中的数据做一些处理。本文介绍的例子中就用到了一个离屏表面。通常的做法是把离屏表面上的位图复制到后台缓冲表面,后台缓冲表面再显示到前台表面。