原文:Directx教程(30) 如何保证渲染物体不会变形

     在Directx11教程(6)中, 我们曾经实现过这个功能,但那时是在SystemClass中,处理WM_SIZE时候,重新调用m_Graphics的初始化函数,这样的话,它的成员变量D3D类还有其它几个成员类,都会重新创建,所以我们的场景等于是从头重新渲染。对于静态场景,这没有问题,但是对于动画场景,我们一改变窗口大小,动画就会从头播放,这显然不是我们所希望的。

     本章中,我们在D3DClass类中新建一个函数,每次改变窗口大小时候,我们就改变framebuffer大小,然后重新建立目标渲染视图、深度模版视图等等。代码是在myTutorialD3D_23的基础上改写的。

    

最关键的代码就是这一行:

m_swapChain->ResizeBuffers(1, screenWidth, screenHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);

D3Class类中增加的函数为:

bool D3DClass::ResizeBuffer(int screenWidth, int screenHeight)
    {
   
    HRESULT result;

    //交换链为空直接返回
    if(!m_swapChain)
        return false;

    //窗口最小化时候为0,会创建缓冲失败
    if(screenHeight < 1)
        screenHeight = 1;
    if(screenWidth < 1)
        screenWidth = 1;

    if(m_renderTargetView)
        {
        m_renderTargetView->Release();
        m_renderTargetView = 0;
        }
    if(m_depthStencilView)
        {
        m_depthStencilView->Release();
        m_depthStencilView = 0;
        }

    if(m_depthStencilBuffer)
        {
        m_depthStencilBuffer->Release();
        m_depthStencilBuffer = 0;
        }

    //改变交换链中后后缓冲大小后,重新创建渲染目标视图
    result = m_swapChain->ResizeBuffers(1, screenWidth, screenHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
    if(FAILED(result))
        {
        HR(result);
        return false;
        }
    // 得到交换链中的后缓冲指针.
    ID3D11Texture2D* backBufferPtr;
    result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
    if(FAILED(result))
        {
        HR(result);
        return false;
        }

    // 用后缓冲创建渲染目标视图.
    result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
    if(FAILED(result))
        {
        HR(result);
        return false;
        }

    //释放后缓冲.(引用计数减1)
    backBufferPtr->Release();
    backBufferPtr = 0;

    D3D11_TEXTURE2D_DESC depthBufferDesc;
    D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
    D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
    D3D11_RASTERIZER_DESC rasterDesc;
    D3D11_VIEWPORT viewport;
    //创建深度模版视图
    // 初始化深度缓冲描述.
    // 初始化深度缓冲描述.
    ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));

    //设置深度缓冲描述
    depthBufferDesc.Width = screenWidth;
    depthBufferDesc.Height = screenHeight;
    depthBufferDesc.MipLevels = 1;  //对于深度缓冲为1
    depthBufferDesc.ArraySize = 1;  //对于深度缓冲为1,对于纹理,这2个参数有更多用途
    depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthBufferDesc.SampleDesc.Count = 1;
    depthBufferDesc.SampleDesc.Quality = 0;
    depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
    depthBufferDesc.CPUAccessFlags = 0;
    depthBufferDesc.MiscFlags = 0;

    // 创建深度缓冲.
    result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer);
    if(FAILED(result))
        {
        HR(result);
        return false;

        }

    // 初始化深度模版状态描述.
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));

   // 设置深度模版状态描述.
    depthStencilDesc.DepthEnable = true;
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;//D3D11_DEPTH_WRITE_MASK_ZERO禁止写深度缓冲
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;

    depthStencilDesc.StencilEnable = true;
    depthStencilDesc.StencilReadMask = 0xFF;
    depthStencilDesc.StencilWriteMask = 0xFF;

    // 对于front face 像素使用的模版操作操作.
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // 对于back face像素使用的模版操作模式.
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

    // 创建深度模版状态,使其生效
    result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
    if(FAILED(result))
        {
        HR(result);
        return false;

        }

   // 设置深度模版状态.
    m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1);

    // 初始化深度模版视图.
    ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

    // 设置深度模版视图描述.
    depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
    depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    depthStencilViewDesc.Texture2D.MipSlice = 0;

    // 创建深度模版视图.
    result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView);
    if(FAILED(result))
        {
        HR(result);
        return false;
        }

   // 绑定渲染目标视图和深度缓冲到渲染管线.
    m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);

    // 设置光栅化描述,指定多边形如何被渲染.
    rasterDesc.AntialiasedLineEnable = false;
    rasterDesc.CullMode = D3D11_CULL_BACK;
    rasterDesc.DepthBias = 0;
    rasterDesc.DepthBiasClamp = 0.0f;
    rasterDesc.DepthClipEnable = true;
    rasterDesc.FillMode = D3D11_FILL_SOLID; //D3D11_FILL_SOLID
    rasterDesc.FrontCounterClockwise = false;
    rasterDesc.MultisampleEnable = false;
    rasterDesc.ScissorEnable = false;
    rasterDesc.SlopeScaledDepthBias = 0.0f;

    // 创建光栅化状态
    result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState);
    if(FAILED(result))
        {
        HR(result);
        return false;
        }

    //设置光栅化状态,使其生效
    m_deviceContext->RSSetState(m_rasterState);

    // 设置视口,显示全部后缓冲内容
    viewport.Width = (float)screenWidth;
    viewport.Height = (float)screenHeight;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0.0f;
    viewport.TopLeftY = 0.0f;

    // 创建视口
    m_deviceContext->RSSetViewports(1, &viewport);

    }

// 设置透视投影矩阵
fieldOfView = (float)D3DX_PI / 4.0f;
screenAspect = (float)screenWidth / (float)screenHeight;

// 创建透视投影矩阵.
D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, m_screenNear, m_screenDepth);

//初始化world矩阵为单位矩阵.
//该矩阵实现局部坐标到世界坐标的转换
D3DXMatrixIdentity(&m_worldMatrix);

// 创建正交投影矩阵,主要用来实施2D渲染.
D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, m_screenNear, m_screenDepth);

    注意:m_screenNear,m_screenDepth是D3DClass增加的两个成员变量,在初始化函数中,它们被用来保存screenNear和screenDetph。

   另外一点小变动就是在GraphicsClass中把m_D3D设置为public,还有就是SystemClass中

if(m_Graphics)
    {
    bool result = m_Graphics->m_D3D->ResizeBuffer(screenWidth, screenHeight);
    if(!result)
        {
        return false;
        }
    }

完整的代码请参考:

工程文件myTutorialD3D11_26

代码下载:

http://files.cnblogs.com/mikewolf2002/myTutorialD3D11_26.zip

Directx教程(30) 如何保证渲染物体不会变形的更多相关文章

  1. 【Visual C++】游戏开发五十六 浅墨DirectX教程二十三 打造游戏GUI界面(一)

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/16384009 作者:毛星云 ...

  2. [译]Vulkan教程(30)深度缓存

    [译]Vulkan教程(30)深度缓存 Depth buffering 深度缓存 Introduction 入门 The geometry we've worked with so far is pr ...

  3. Directx教程(22) 简单的光照模型(1)

    原文:Directx教程(22) 简单的光照模型(1)      在前面的教程中,我们在顶点属性中直接给顶点赋颜色,这样生成的三维物体缺乏真实感,如下图中两个立方体,左边的是通过光照生成物体表面颜色的 ...

  4. Directx教程(27) 简单的光照模型(6)

    原文:Directx教程(27) 简单的光照模型(6)      从myTutorialD3D11_15到myTutorialD3D11_19的工程中,我们都只有一个光源,光源的位置在LightCla ...

  5. Directx教程(23) 简单的光照模型(2)

    原文:Directx教程(23) 简单的光照模型(2)    在工程myTutorialD3D11_16中,我在文件light.vs中定义了一个材质光源属性常量缓冲. //const buffer最好 ...

  6. CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率

    CSharpGL(30)用条件渲染(Conditional Rendering)来提升OpenGL的渲染效率 当场景中有比较复杂的模型时,条件渲染能够加速对复杂模型的渲染. 条件渲染(Conditio ...

  7. PS网页设计教程——30个优秀的PS网页设计教程的中文翻译教程

    PS网页设计教程--30个优秀的PS网页设计教程的中文翻译教程   作为编码者,美工基础是偏弱的.我们可以参考一些成熟的网页PS教程,提高自身的设计能力.套用一句话,"熟读唐诗三百首,不会作 ...

  8. Directx教程(29) 简单的光照模型(8)

    原文:Directx教程(29) 简单的光照模型(8)      现在我们新建一个工程myTutorialD3D_23,在这个工程中,对前面一章的代码进行一些整理: 1.我们在顶点属性中增加材质的的漫 ...

  9. Directx教程(28) 简单的光照模型(7)

    原文:Directx教程(28) 简单的光照模型(7)        现实生活中的点光源都是随着距离衰减的,比如一个电灯泡在近处会照的很亮,远处光线就很弱.本节中我们在前面光公式的基础上,再给漫反射和 ...

随机推荐

  1. sqlserver 下三种批量插入数据的方法

    本文将介绍三种批量插入数据的方法,需要的朋友可以参考下 本文将介绍三种批量插入数据的方法.第一种方法是使用循环语句逐个将数据项插入到数据库中:第二种方法使用的是SqlBulkCopy,使您可以用其他源 ...

  2. 左神算法书籍《程序员代码面试指南》——1_08构造数组的MaxTree

    [题目] 将一个没有重复数字的数组中的数据构造一个二叉树 每个节点都是该子树的最大值 [要求] 时间复杂度为O(N)[题解] 使用单调栈,栈的顺序是维持从大到小排序 通过使用单调栈,将数组中中所有数的 ...

  3. JQuery学习:事件绑定&入口函数&样式控制

    1.基础语法学习: 1.事件绑定 2.入口函数 3.样式控制 <!DOCTYPE html> <html lang="en"> <head> & ...

  4. Java中移动文件或目录的方法盘点

    本文不再更新,可能存在内容过时的情况,实时更新请移步原文地址:Java中移动文件或目录的方法盘点: import org.apache.commons.io.FileUtils; import jav ...

  5. 在vue项目中正确的引入jquery

    最近学习vue,习惯性的通过<script>标签引入jquery,写完后报错才想起来,这种方式在vue是不适用的. 1:因为已经安装了vue脚手架,所以需要在webpack中全局引入jqu ...

  6. [Array] 561. Array Partition I

    Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1 ...

  7. 【python之路27】vars()包含的全局变量对象

    213 一..py文件里面包含全局变量 print(vars())输出结果如下: {'__name__': '__main__', '__doc__': None, '__package__': No ...

  8. windows 2008 安装 apache + mysql + php

    下载准备 php : http://windows.php.net/downloads/releases/archives/ apache : https://www.apachehaus.com/c ...

  9. Git的基本了解与使用、向github提交代码

    #Git的基本了解与使用.向github提交代码- git:是一个版本控制系统.- github:一个代码托管提供商.开源网站.是一个面向开源及私有软件项目的托管平台,因为支持Git作为唯一的版本库格 ...

  10. 从零开始Android逆向教程(二)——什么是Xposed

    前言在阅读本文之前,假设你的手机已经root,并且已经成功安装好了 XposedInstaller. Xposed是什么?       Xposed 是一个 Android 平台上的动态劫持框架,通过 ...