显示功能是在视图类中完成的,所以DX10的初始化及绘制工作都是视图类中完成。

首先建立一个多文档工程,工程名为02_01,在视图类头文件中加载相关的库,并包含头文件:

在视图类的头文件中添加DX10相关的成员:

其中三个变换矩阵、m_device以及显卡有关信息通过五个公有函数访问:

下面是DX具体的初始化过程,封装为一个视图类的成员函数InitDX()。

DX初始化过程中需要创建设备和交换链,在创建交换链的时候用到和视图窗口有关的几个参数:窗口的宽、高和窗口的句柄:

接下来是交换链、纹理资源、2D纹理描述结构体等,其中screenNear和screenDepth是渲染的深度范围,m_vsync_enabled设置为真,表明后面会根据实际的硬件设备设置刷新率,否则是尽可能快地刷新:

以下代码填充DXGI_SWAP_CHAIN_DESC结构体中在初始化过程中用到的一些成员:

 
    // Initialize the swap chain description.
    ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
 
    // Set to a single back buffer.
    swapChainDesc.BufferCount = 1;
 
    // Set the width and height of the back buffer.
    swapChainDesc.BufferDesc.Width = screenWidth;
    swapChainDesc.BufferDesc.Height = screenHeight;
 
    // Set regular 32-bit surface for the back buffer.
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 
    // Set the refresh rate of the back buffer.
    if(m_vsync_enabled)
    {
        swapChainDesc.BufferDesc.RefreshRate.Numerator = 1;
        swapChainDesc.BufferDesc.RefreshRate.Denominator = 60;
    }
    else
    {
        swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
        swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    }
 
    // Set the usage of the back buffer.
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 
    // Set the handle for the window to render to.
    swapChainDesc.OutputWindow = hwnd;
 
    // Turn multisampling off.
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
 
    // Set to full screen or windowed mode.
    swapChainDesc.Windowed = true;
 
    // Set the scan line ordering and scaling to unspecified.
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
 
    // Discard the back buffer contents after presenting.
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
 
    // Don't set the advanced flags.
    swapChainDesc.Flags = 0;

DXGI_SWAP_CHAIN_DESC结构体填充好后,创建交换链和Direct3D Device。Direct3D Device是调用所有D3D函数的接口。

// Create the swap chain and the Direct3D device.
    result = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, 
        &swapChainDesc, &m_swapChain, &m_device);
    if(FAILED(result))
    {
        return false;
    }

现在device和swap chain都有了,接下来需要back buffer的指针挂到swap chain上。通过CreateRenderTargetView函数来实现。

// Get the pointer to the back buffer.
    result = m_swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&backBufferPtr);
    if(FAILED(result))
    {
        return false;
    }

// Create the render target view with the back buffer pointer.
    result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
    if(FAILED(result))
    {
        return false;
    }

// Release pointer to the back buffer as we no longer need it.
    backBufferPtr->Release();
    backBufferPtr = NULL;

此外还需要设置depth buffer的描述结构体,通过这个深度缓冲区描述结构体创建depth buffer,以实现多边形在三维空间的绘制。同时还要把stencil buffer挂在depth buffer上。stencil buffer用来实现一些特效的,比如运动模糊,阴影体等。

// Initialize the description of the depth buffer.
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
 
    // Set up the description of the depth buffer.
    depthBufferDesc.Width = screenWidth;
    depthBufferDesc.Height = screenHeight;
    depthBufferDesc.MipLevels = 1;
    depthBufferDesc.ArraySize = 1;
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D10_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

现在可以创建depth/stencil buffer。实际上buffer只是一块2D纹理,所以这里使用CreateTexture2D函数创建这两个buffer。

// Create the texture for the depth buffer using the filled out description.
    result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
    if(FAILED(result))
    {
        return false;
    }

下面设置depth stencil的描述结构体,该结构体指定对每个像素使用的深度测试类型。

// Initialize the description of the stencil state.
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
 
    // Set up the description of the stencil state.
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
    depthStencilDesc.DepthFunc = D3D10_COMPARISON_LESS;
 
    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;
 
    // Stencil operations if pixel is front-facing.
    depthStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
 
    // Stencil operations if pixel is back-facing.
    depthStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;

下面用上述结构体创建一个depth stencil state:

// Create the depth stencil state.
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
    if(FAILED(result))
    {
        return false;
    }

接下来让这个depth stencil state在device上生效:

// Set the depth stencil state on the D3D device.
    m_device->OMSetDepthStencilState(m_depthStencilState, 1);

最后要创建的是depth stencil buffer视图的描述结构体,然后调用CreateDepthStencilView创建depth stencil buffer视图。

// Initailze the depth stencil view.
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
 
    // Set up the depth stencil view description.
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;
 
    // Create the depth stencil view.
    result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
    if(FAILED(result))
    {
        return false;
    }

现在要把render target view和depth stencil buffer绑定到输出渲染管线。这样一来管线中渲染的图形才能输出到前面我们创建的back buffer中去。back buffer里的图形绘制完成后,会被交换到前端,输出到显示器上。

// Bind the render target view and depth stencil buffer to the output render pipeline.
    m_device->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);

至此render target已经设置完毕。下面还要设置一些额外的功能,将来可能会用到。首先要创建的是光栅化状态rasterizer state,该状态用来控制多边形的绘制方式,比如用线框模式绘制或是双面绘制之类的。默认情况下rasterizer state是下面这样:

// Setup the raster description which will determine how and what polygons will be drawn.
    rasterDesc.AntialiasedLineEnable = false;
    rasterDesc.CullMode = D3D10_CULL_BACK;
    rasterDesc.DepthBias = 0;
    rasterDesc.DepthBiasClamp = 0.0f;
    rasterDesc.DepthClipEnable = true;
    rasterDesc.FillMode = D3D10_FILL_SOLID;
    rasterDesc.FrontCounterClockwise = false;
    rasterDesc.MultisampleEnable = false;
    rasterDesc.ScissorEnable = false;
    rasterDesc.SlopeScaledDepthBias = 0.0f;
 
// Create the rasterizer state from the description we just filled out.
    result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
    if(FAILED(result))
    {
        return false;
    }
 
    // Now set the rasterizer state.
    m_device->RSSetState(m_rasterState);

接下来还要设置viewport,让D3D能够把裁剪空间坐标映射到render target空间里去。这里把视口设置为窗口大小。

// Setup the viewport for rendering.
    viewport.Width = screenWidth;
    viewport.Height = screenHeight;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
 
    // Create the viewport.
    m_device->RSSetViewports(1, &viewport);

然后是投影矩阵,该矩阵用来把三维场景映射到刚刚设置好的二维视口空间上。今后渲染场景的时候需要把这个矩阵的副本传给shader。

// Setup the projection matrix.
    fieldOfView = (float)D3DX_PI / 4.0f;
    screenAspect = (float)screenWidth / (float)screenHeight;
 
    // Create the projection matrix for 3D rendering.
    D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth);

另外还要创建一个世界矩阵。该矩阵用来把一个对象上的顶点变换到我们创建的三维场景中去。同时这个矩阵也用来对三维场景中的对象进行旋转、缩放和平移。初始化的时候可以用一个单位矩阵作为世界矩阵。在渲染的时候也需要把该矩阵的副本传给shader。

// Initialize the world matrix to the identity matrix.
    D3DXMatrixIdentity(&m_worldMatrix);

下面实际应该创建一个视点矩阵。视点矩阵用来计算我们观察场景所处的位置。可以认为视点矩阵描述了摄像机的位置。视点矩阵的创建放在摄像机类中完成。

D3D初始化的最后一步是创建正交投影矩阵orthographic projection matrix。这个矩阵是用来渲染二维元素的。

// Create an orthographic projection matrix for 2D rendering.
    D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);

最后的最后。。

return true;

InitDX函数在初始化DX环境的时候需要知道窗口大小等参数,这个时候视图的尺寸需要有明确的值,所以InitDX函数要在OnInitialUpdate虚函数里调用。

最后测试一下DX初始化是否成功。可以逐步跟踪一下看各个COM接口调用的返回值,或者在OnPaint函数里简单写两行:

float color[4];
 
 
    // Setup the color to clear the buffer to.
    color[0] = 0.0f;
    color[1] = 0.0f;
    color[2] = 0.0f;
    color[3] = 1.0f;
 
    // Clear the back buffer.
    m_device->ClearRenderTargetView(m_renderTargetView, color);
 
    // Clear the depth buffer.
    m_device->ClearDepthStencilView(m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
 
    if(m_vsync_enabled)
    {
        // Lock to screen refresh rate.
        m_swapChain->Present(1, 0);
    }
    else
    {
        // Present as fast as possible.
        m_swapChain->Present(0, 0);
    }

三个矩阵的get函数:

void CMy02_01View::GetProjectionMatrix(D3DXMATRIX& projectionMatrix)
{
    projectionMatrix = m_projectionMatrix;
    return;
}
 
 
void CMy02_01View::GetWorldMatrix(D3DXMATRIX& worldMatrix)
{
    worldMatrix = m_worldMatrix;
    return;
}
 
 
void CMy02_01View::GetOrthoMatrix(D3DXMATRIX& orthoMatrix)
{
    orthoMatrix = m_orthoMatrix;
    return;
}

最后的最后的最后,释放资源,在视图类中添加一个ReleaseDX()函数,在视图类的析构中调用它:

void CMy02_01View::ReleaseDX()
{
    if(m_rasterState)
    {
        m_rasterState->Release();
        m_rasterState = NULL;
    }
 
    if(m_depthStencilView)
    {
        m_depthStencilView->Release();
        m_depthStencilView = NULL;
    }
 
    if(m_depthStencilState)
    {
        m_depthStencilState->Release();
        m_depthStencilState = NULL;
    }
 
    if(m_depthStencilBuffer)
    {
        m_depthStencilBuffer->Release();
        m_depthStencilBuffer = NULL;
    }
 
    if(m_renderTargetView)
    {
        m_renderTargetView->Release();
        m_renderTargetView = NULL;
    }
 
    if(m_swapChain)
    {
        m_swapChain->Release();
        m_swapChain = NULL;
    }
 
    if(m_device)
    {
        m_device->Release();
        m_device = NULL;
    }
 
    return;
}

完毕。

PS:英文原文教程地址http://www.rastertek.com/dx10tut03.html,根据自己的需要进行了小小改动。

刚刚接触DX,很多背景知识不懂,希望过路的朋友不吝指教,帮我进步。谢谢。

转载于:https://www.cnblogs.com/youthlion/archive/2012/11/19/2778151.html

DirectX10 学习笔记2:在多文档框架中初始化DirectX 10相关推荐

  1. 【学习笔记】Windows格式文档转换成Unix格式

    [学习笔记]Windows格式文档转换成Unix格式 我们有时候需要将文档格式从Windows格式转换成Unix格式,Windows下换行是\r\n,而Unix下换行是\n,所以只需要将文档中的\r去 ...

  2. HTML5+CSS3学习笔记(三)文档流和盒子模型【附练习:图片列表、左侧导航栏】

    HTML5+CSS3学习笔记(三) 本系列更多文章,可以查看专栏 HTML+CSS学习笔记 文章目录 HTML5+CSS3学习笔记(三) 一.CSS布局 1. 文档流(块级元素.行内元素.行内块元素) ...

  3. 【Word】学习笔记|批量解决文档中公式编号不居中的问题

    1. 问题描述 当你将一个Word中内容(包含公式)复制到另外一个Ward里,发现MathType公式编号未居中,如上图所示.如果你公式较少,可以参考官方教程解决,就是将段落→中文版式→文本对齐方式中 ...

  4. 【学习笔记】git 使用文档

    安装 git # mac 环境 brew install git 检查是否安装成功 ➜ ~ git --version git version 2.20.1 (Apple Git-117) 卸载 gi ...

  5. php 文档转html格式文件,php学习笔记之将word文档转化为HTML文件

    将word文档转化为HTML文件 function wordTohtml($wfilepath) { $word=new COM("Word.Application") or di ...

  6. WPF-学习笔记 获取我的文档路径

    获取我的文档路径:Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); 语句返回的是string值,但没有最后的 \ 档, ...

  7. 通关!游戏设计之道的学习笔记(四)文档

    一款游戏,你得从游戏的设计文档开始做起.在游戏开放的筹备阶段,需要有以下4中文档来帮忙进行工作:①单页说明书②十页说明书③游戏流程表④游戏设计文档,简写为GDO. 单页说明书 包含以下信息: 1.游戏 ...

  8. java计算机毕业设计计算机类在线学习管理系统MyBatis+系统+LW文档+源码+调试部署

    java计算机毕业设计计算机类在线学习管理系统MyBatis+系统+LW文档+源码+调试部署 java计算机毕业设计计算机类在线学习管理系统MyBatis+系统+LW文档+源码+调试部署 本源码技术栈 ...

  9. java计算机毕业设计计算机课程在线培训学习管理系统MyBatis+系统+LW文档+源码+调试部署

    java计算机毕业设计计算机课程在线培训学习管理系统MyBatis+系统+LW文档+源码+调试部署 java计算机毕业设计计算机课程在线培训学习管理系统MyBatis+系统+LW文档+源码+调试部署 ...

最新文章

  1. 解决ORA-28000: the account is locked
  2. 简单的 docker SVG 动画(无聊之作)
  3. SpringCloud:入门介绍
  4. webfocus在移动终端上的应用DEMO
  5. java(6)——+号和++号--号
  6. 100的阶乘c语言代码,求10000的阶乘(c语言代码实现)
  7. sql server获取表的所有字段
  8. 从PHP5.2.x迁移到PHP5.3.x
  9. 山西计算机等级考试科目一模拟试题,2011山西省计算机等级考试试题 二级ACCESS一点通科目一...
  10. storm metric的使用说明
  11. RabbitMQ(2) 一般介绍
  12. loadView加载(变换成ScrollView)
  13. 栈溢出笔记1.8 字符串问题
  14. 直方图均衡[附C实现代码]
  15. 活着是一种罪过,是上帝对你的另一种眷顾,叫做惩罚!活着痛苦!
  16. JS中编码的三种方法
  17. 如何快速通过信息系统管理工程师考试
  18. php 画布源代码,PHP中的画布详解
  19. Filename和chunkFilename的区别
  20. Python解释器的选择,初学者必看

热门文章

  1. COM组件转换成.NET组件[转]
  2. (1)学习数组,集合,IEnumerable接口,引申学习迭代器
  3. Ubuntu16.04.1 安装Nginx
  4. Linux-find命令应用举例-按时间筛选和删除文件
  5. Powershell检测AD账户密码过期时间并邮件通知
  6. Centos+PHP模块+exif扩展 (第三方模块)
  7. 转 C++STL之string
  8. Cygwin鸡毛蒜皮
  9. 如何面对“大概什么时候能完成?”
  10. [整理] - Relational Engine之UMS Internals