#Directx12基本的Graphics概念和Direct3D类型(二)
2016-10-05 19:27
337 查看
多重采样(Multisampling)
由于我们的屏幕的像素点不是足够的小,因此在绘制一条直线时候可能出现阶梯形近似的表达一条直线。如下通过不断的提高屏幕的分辨率可以逐步的消除这种影响。然而当提高分辨率变得不可能时候,我们可以采取一些其他的方法减弱这个影响,其中一种技术是 超级采样(supersampling),其原理是将backbuffer和depthbuffer增大到屏幕分辨率的四倍大小,然后将图像渲染在这个增大的backbuffer上,然后当需要将backbuffer上的内容呈现到屏幕上的时候在将4个像素点的颜色值取平均数,最后映射到屏幕上。这个方法通过软件增大屏幕的分辨率达到效果
然而超级采样的代价是昂贵的,这种做法既要增加像素计算量也会增加内存占用。Direct3D采取一种折中的方法:多重采样(multisampling),这种方法通过共享一些计算结果来减少计算量。例如对于常用的四重采样,同样需要四倍大小的backbuffer和depthbuffer,但是不同于超级采样计算每一个子像素点的颜色,对么一个像素点只计算一次,而且只计算中心店的像素值,对于下一个像素点则根据是否可见共享一些计算结果。
Direct3D中的多重采样
为了使用Direct3D中的多重采样,需要填充一个结构体DXGI_SAMPLE_DESCtypedef struct DXGI_SAMPLE_DESC{ UINT Cout;//每个采样点的像素数量 UINT Quality;//采样的质量水平 } DXGI_SAMPLE_DESC
其中的Quality因各个厂商而异,且由纹理格式和采样像素点数量决定。高的采样像素点数量和采样质量意味着更高的代价,因此必须权衡。
我们可以通过
**ID3D12Device::CheckFeatureSupport()**方法查询特定的纹理格式和采样大小下的质量水平,如下
typedef struct D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS{
DXGI_FORMAT Foramt; //纹理格式
UINT SampleCount; //采样大小
D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG Flags; //采样质量标志位
UINT NumQulityLevels; //采样水平
}D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS;
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msQualityLevels;
msQualityLevels.Format=mBackBufferFormat;
msQualityLevels.SampleCount=4 ;
msQualityLevels.Flags=D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG_NONE;
msQualityLevels.NumQualityLevels=0;
ThrowIfFailed(md3dDevice->CheckFeatureSupport(
D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, //查询的特性枚举
& msQualityLevels, //既是输入也是查询结果的输出
sizeof(msQualityLevels)));
//查询的结果会填充在msQualityLevels中,合法的采样质量水平是[0,NumQualityLevels-1]的一个值
最大的采样大小是通过
#define D3D11_MAX_MULTYSAMPLE_SAMPLE_COUNT来定义的。通常我们使用4重或者8重采样,如果不希望使用多重采样,可以通过定义采样大小为1,采样质量水平为0来达到效果。所有的Direct3D 11设备对于所有的渲染目标格式都支持4重采样。
特性等级(Feature Levels)
Direct3D 11引入了特性等级概念,这是一个枚举量,其枚举值对应着Directx 9到11版本eum D3D_FEATURE_LEVEL{ D3D_FEATURE_LEVEL_9_1 =0X9100, D3D_FEATURE_LEVEL_9_2 =0X9200, D3D_FEATURE_LEVEL_9_3 =0X9300, D3D_FEATURE_LEVEL_10_0 =0Xa000, D3D_FEATURE_LEVEL_10_1 =0Xa100, D3D_FEATURE_LEVEL_11_0 =0Xb000, D3D_FEATURE_LEVEL_11_1 =0Xb100, } D3D_FEATURE_LEVEL;
特性等级的概念方便了开发者进行开发,假设GPU支持某一个等级的特性,例如D3D_FEATURE_LEVEL_11_0 特性,则要求GPU必须支持整个Direct3D 11的所有特性(当然允许某些特性需要根据情况查询,例如多重采样水平,因为允许不同的硬件设备不同)。
如果某个硬件设备不支持一个特定的特性水平,则会按照顺序往下查询直到找到支持的设备特性等级。
DXGI(DirectX Graphics Infrastructure)
-DXGI 是一组基础的Direct3D API。DXGI 的基本思想是很多看似不一样的任务其实使用的是同一套API,因此DXGI处理其他通用的图形功能,例如全屏模式转换,图形枚举系统信息,如显示适配器,显示器和支持的显示模式(分辨率,刷新率,等等);它还定义了各种支持的表面的格式(DXGI_FORMAT)。DXGI中一个重要的接口是IDXGIFactory,这个接口主要用于创建IDXGISwapChain交换链以及枚举显示适配器(display adapters),显示适配器主要用于实现图形化功能。通常显示适配器由硬件提供支持,然而一个系统同样可以拥有一些软件显示适配器,一个适配器使用IDXGIAdapter表示。可以通过以下方法枚举所有的适配器
void D3DApp::LogAdapters() { UINT i = 0; IDXGIAdapter* adapter = nullptr;//定义一个显示适配器指针对象 std::vector<IDXGIAdapter*> adapterList; //保存当前系统的所有适配器 while(mdxgiFactory->EnumAdapters(i, &adapter) !=DXGI_ERROR_NOT_FOUND) { //EnumAdapters() 枚举显示适配器 DXGI_ADAPTER_DESC desc; adapter->GetDesc(&desc); //获得当前适配器的信息 std::wstring text = L”***Adapter: “; text += desc.Description; text += L”\n”; OutputDebugString(text.c_str()); adapterList.push_back(adapter); ++i; } for(size_t i = 0; i < adapterList.size(); ++i) { LogAdapterOutputs(adapterList[i]); ReleaseCom(adapterList[i]); } } **** 一种可能的输出为 *** Adapter: NVIDIA GeForce GTX 760 //硬件适配器 *** Adapter: Microsoft Basic Render Driver //win8以及以后的系统包含的软件适配器
输出适配器(IDXGIOutput)
一个系统可以包含很多个屏幕,因此一个屏幕就是一个输出适配器的实例,一个输出使用IDXGIOutput表示。一个适配器可以关联一系列的输出,例如一个显示屏多个图形显卡以及一个显卡多个屏幕情况,我们可以使用以下代码枚举出关联到一个适配器的所有输出实例:void D3DApp::LogAdapterOutputs(IDXGIAdapter* adapter) { UINT i = 0; IDXGIOutput* output = nullptr; while(adapter->EnumOutputs(i, &output) !=DXGI_ERROR_NOT_FOUND) { //枚举所有的输出实例 DXGI_OUTPUT_DESC desc; output->GetDesc(&desc); std::wstring text = L”***Output: “; text += desc.DeviceName; text += L”\n”; OutputDebugString(text.c_str()); LogOutputDisplayModes(output, DXGI_FORMAT_B8G8R8A8_UNORM); ReleaseCom(output); ++i; } } //注: win自带的软件显示适配器(Microsoft Basic Render Driver) 不包含输出适配器
DXGI_MODE_DESC(显示模式信息)
每一个显示器都有一系列其支持的显示模式,使用DXGI_MODE_DESC 表示显示模式typedef struct DXGI_MODE_DESC { UINT Width; //分辨率 width UINT Height; // 分辨率height DXGI_RATIONAL RefreshRate; //刷新频率 DXGI_FORMAT Format; // 显示格式 DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;//扫描顺序:渐进式 隔行扫描 DXGI_MODE_SCALING Scaling; // 图像拉伸方式 } DXGI_MODE_DESC; typedef struct DXGI_RATIONAL { UINT Numerator; UINT Denominator; } DXGI_RATIONAL; typedef enum DXGI_MODE_SCANLINE_ORDER { DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0, DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE = 1, DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST = 2, DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST = 3 } DXGI_MODE_SCANLINE_ORDER; typedef enum DXGI_MODE_SCALING { DXGI_MODE_SCALING_UNSPECIFIED = 0, DXGI_MODE_SCALING_CENTERED = 1, DXGI_MODE_SCALING_STRETCHED = 2 } DXGI_MODE_SCALING;
填充一个显示格式,可以通过以下代码得到一些列支持的显示模式:
void D3DApp::LogOutputDisplayModes(IDXGIOutput*output, DXGI_FORMAT format) { UINT count = 0; UINT flags = 0; output->GetDisplayModeList(format, flags, &count,nullptr); std::vector<DXGI_MODE_DESC> modeList(count); output->GetDisplayModeList(format, flags, &count,&modeList[0]); //获得支持的显示模式列表 for(auto& x : modeList){ UINT n = x.RefreshRate.Numerator;//获得刷新率的分子 UINT d = x.RefreshRate.Denominator;//获得刷新率的分母 std::wstring text = L”Width = ” + std::to_wstring(x.Width) + L” ” + L”Height = ” + std::to_wstring(x.Height) + L” ” + L”Refresh = ” + std::to_wstring(n) + L”/” +std::to_wstring(d) +L”\n”; ::OutputDebugString(text.c_str()); } } //一种可能的输出是: width = 1920 Height = 1080 Refresh = 59950/1000 Width = 1920 Height = 1200 Refresh = 59950/1000
//* 2016/10/5 23:33
相关文章推荐
- #Directx12基本的Graphics概念和Direct3D类型(-)
- C++类型转换基本概念浅谈
- 商业模式研究(一):基本概念 类型及特点
- JAVA笔记一(01-06 java的基本概念和数据类型)
- (3)javascript 基本概念--- -- 数据类型
- [转载]MongoDB学习(二):数据类型和基本概念
- 由string类型想到的基本概念
- Lesson_for_java_day04--java基本知识、概念、变量、基本数据类型、运算符及表达式
- CoreGraphics基本数据类型
- MongoDB学习(二):数据类型和基本概念
- MySQL基本概念--索引&索引类型
- C++ Primer 学习笔记--基本概念和数据类型
- Direct3D 9学习笔记(2)基本概念
- Direct3D 开发之旅 3D 游戏基本概念的介绍2
- 3D游戏基础 Direct3D(一) D3D基本概念及渲染流水线简介
- 系统安全的基本概念和权限控制系统的类型
- C++ Primer 学习笔记--基本概念和数据类型
- C#基本概念和类型(完善中)
- MongoDB学习(二):数据类型和基本概念
- Java自学第二天、第三天Java的基本概念、变量、数据类型