Direct3D
Direct3D是Windows平台上开发硬件加速的程序一个架构,它提供了
- 图形处理和渲染加速
- 视频编解码加速
- 并行计算加速
Direct3D和OpenGL非常相似,很多概念、术语和流程基本上是相通的,在显卡(GPU)内部的加速原理基本上差不多,它不仅是Windows和XBox游戏开发的渲染基本技术架构,我们还能利用显卡(GPU)强大的计算能力,为高清视频、图像和图形编解码,渲染和特效处理提供实时和流畅的处理能力,是Windows平台上视频和图像处理进阶的必备编程技术。
本系列主要介绍如何用D3D处理2D视频和图像,所有演示程序和代码均基于Direct3D11。
Direct3D坐标系
Direct3D提供了这么几种坐标系,这些对于D3D rendering pipeline以及shader的代码阅读和编写来说非常重要,毕竟GPU端的代码的调试和优化相对于CPU端来说是比较麻烦的,对于基本概念的不了解会造成代码编写和运行效率的低下。
Pixel Coordinate System
这个坐标系的原点(0, 0)在Render Target(渲染目标)的左上方,这个坐标系与图像和视频decoded buffer是一致的,大部分图片和主流视频都是用这个坐标系来表示图像像素信息,下面这张图片很好的描述了它:
图一
从这张图可以看到,因为D3D是矢量图,所以像素的大小和位置可以是小数,而且它们也是连续的,一个像素方框的左上方是整数坐标系,比如(0, 0), (1, 4)等, 一个像素的中心是左上方整数坐标加上(0.5, 0.5)的偏移量。
可以把它理解成buffer坐标系。
Texel Coordinate System
在2D Quad Render Target里面可以理解填充素材(Texture)坐标,也称作uv坐标,主要用来描述素材中哪部分区域用来填充到Render Target中。左上方的坐标为(0, 0),然后右下方normlized坐标为(1, 1):
图二
在HLSL shader中一般用TEXCOORD来申明。 可以把它理解重素材填充坐标系
NDC(Normalized Device Coordinates)
中文好像翻译成标准化设备坐标,原点(0, 0)在Render Target的中心,左上角坐标为(-1, 1),右下角为(1, -1)。在D3D中一般用来描述点在渲染区域的坐标,比如顶点(Vertex)的坐标。也可以在图一
中看到对应的图示。在D3D中,Shader中的SV_Position语义就用在这个坐标系来描述指定屏幕空间坐标(screen space coordinates)。
可以把它理解成渲染坐标系。
相关代码
有了上面这些基本概念之后,来看一段用HSL写的Vetex Shader的代码:
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS(uint vI : SV_VERTEXID)
{
PS_INPUT output = (PS_INPUT)0;
float2 texcoord = float2(vI & 1, vI >> 1);
output.Pos = float4((texcoord.x - 0.5f) * 2.0f, -(texcoord.y - 0.5f) * 2.0f, 0.0f, 1.0f);
output.Tex = texcoord;
return output;
}
从这段代码可以看出, 这个vertex shader的输出PS_INPUT用来告诉pixel shader的输入坐标信息,包括素材(ShaderResourceView)中哪个区域(Tex: TEXCOORD, Texel Coordinate System)应该填充到哪个渲染区域(Render Target)(Pos: SV_POSITION, NDC),然后Vertex Shader就根据设计的场景来构建素材内容和渲染区域,很多转场动画都是通过调整这个输出来达到要想的一些效果。
再来看一段Pixel Shader的代码:
//--------------------------------------------------------------------------------------
// ScreenPS.hlsl
//--------------------------------------------------------------------------------------
Texture2D txInput : register(t0);
SamplerState GenericSampler : register(s0);
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD;
};
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS(PS_INPUT input) : SV_Target
{
return txInput.Sample(GenericSampler, input.Tex);
}
这段代码中Pixel Shader的输入为PS_INPUT input
, pos: SV_POSITION
为在NDC坐标系要处理的某点的D3D坐标(x, y, z, w),而Tex : TEXCOORD
则用来描述填充素材(Texture)上对应某点填充到pos:SV_POSITION
对应的这个点。而语句txInput.Sample(GenericSampler, input.Tex)
则是根据Texel Coordinate System坐标系统从素材(Texture)上取一点的具体信息,比如颜色信息(Blue, Green, Red和Alpha)值,然后把它渲染到Render Target中。当然在这个最简单的场景中, Pixel Coordinate System和NDC坐标并没有参与到具体运算逻辑来影响输出效果。
结论
通过上面的介绍,应该能对用于2D场景中各个坐标系有个粗略的了解,在后面的文章中会进一步讲解这三个坐标如何用在一些实际场景中。