基于 DirectX11 的 MMDViewer 04-渲染目标视图和多视口

时间:2021-04-12 09:09:25

  上篇文章给出了一个简单并且可以运行的渲染框架,接下来将介绍框架中的渲染管线构成。

  1、创建渲染管线

  在你创建完一个窗口后,接着便要创建渲染管线,使用的函数是 D3D11CreateDeviceAndSwapChain,

  交换链:


  要创建交换链,必须先设置交换链描述。交换链描述定义了将由交换链使用的渲染缓冲区的大小和数量。它还将窗口与交换链相关联,从而确定最终图像的显示位置。交换链描述还定义了该应用的消除锯齿(如果有的话)的质量以及在展示过程中后端缓冲区的翻转方式。

    UINT create_device_flags = ;
#ifdef _DEBUG
create_device_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif D3D_DRIVER_TYPE driver_types[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT num_driver_types = ARRAYSIZE(driver_types); D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels); DXGI_SWAP_CHAIN_DESC swap_desc;
ZeroMemory(&swap_desc, sizeof(swap_desc));
swap_desc.BufferCount = ;
swap_desc.BufferDesc.Width = width;
swap_desc.BufferDesc.Height = height;
swap_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swap_desc.BufferDesc.RefreshRate.Numerator = ;
swap_desc.BufferDesc.RefreshRate.Denominator = ;
swap_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_desc.OutputWindow = g_hWnd;
swap_desc.SampleDesc.Count = ;
swap_desc.SampleDesc.Quality = ;
swap_desc.Windowed = TRUE; for ( UINT driver_type_index = ; driver_type_index < num_driver_types; driver_type_index++ )
{
g_driverType = driver_types[driver_type_index];
hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, create_device_flags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &swap_desc, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
if ( SUCCEEDED(hr) ) break;
}

  创建交换链是指定了一个窗口的句柄,并且设置了一个 D3D11_CREATE_DEVICE_DEBUG 标志,这个标志可以创建一个支持调试层的设备。如果我们做错了事,调试层为渲染管线的正确性和一致性提供了额外的检查并提供了更好的反馈。但是,如果在启用调试层的情况下运行应用程序,则应用程序将显着变慢。

要创建支持调试层的设备,必须安装DirectX SDK(以获取D3D11SDKLayers.dll)

  渲染管线输出:


  渲染管线并不能将渲染结果直接输出到窗口,只能输出到一个叫渲染目标视图(ID3D11RenderTargetView)的对象,在创建 ID3D11RenderTargetView 时需要和一个纹理对象绑定。可以使用交换链的 GetBuffer 方法来获取交换链后台纹理缓冲区指针,并创建一个渲染目标视图,最后将该视图设置到渲染管线,就可以将渲染管线的结果呈现给窗口了。

    /* 获取交换链的后缓冲 */
ID3D11Texture2D* pBackBuffer = NULL;
hr = g_pSwapChain->GetBuffer(, __uuidof(ID3D11Texture2D), ( LPVOID* ) &pBackBuffer);
if ( FAILED(hr) ) return hr; /* 创建渲染目标视图 */
hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);
pBackBuffer->Release();
if ( FAILED(hr) ) return hr; g_pImmediateContext->OMSetRenderTargets(, &g_pRenderTargetView, );

  

  使用函数 OMSetRenderTargets 设置渲染目标视图到渲染管线时,可以设置 1 - D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT 之间数量的渲染目标视图。默认情况下使用第一个渲染目标视图,如果你要使用其它的渲染目标视图,必须在像素着色器中映射管线多输出值到 SV_Target[n] (其中 介于 0 和 D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT 之间)语义,实现多渲染目标(MRT)。像素着色器代码如下:

struct PS_OUTPUT
{
float4 color0 : SV_Target0;
float4 color1 : SV_Target1;
}; //--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
PS_OUTPUT PS( VS_OUTPUT input )
{
PS_OUTPUT o; o.color0 = input.Color;
o.color1 = float4(, , , ); return o;
}

  因为没有多少文章介绍 DirectX11 多渲染目标(MRT)的实现,所以在这里简单介绍一下。

  视口(ViewPort):


  然不是严格考虑Direct3D初始化阶段的一部分,但设置视口定义是初始化光栅化器阶段的必要组件。视口定义了我们的最终渲染将进入的屏幕空间区域。对于这个应用程序,我们将渲染到应用程序窗口的整个客户区,但是如果我们想实现分屏多人或画中画效果,我们也可以定义两个视口。

    D3D11_VIEWPORT view_port;

    view_port.Width = ( FLOAT ) width;
view_port.Height = ( FLOAT ) height;
view_port.MinDepth = 0.0f;
view_port.MaxDepth = 1.0f;
view_port.TopLeftX = ;
view_port.TopLeftY = ; g_pImmediateContext->RSSetViewports(, &view_port);

  

  使用 RSSetViewports 设置视口到渲染管线时,可以设置 1 D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX 之间数量的视口。默认情况下使用第一个视口,如果你想使用其它的视口,必须在几何着色器中设置 SV_ViewportArrayIndex 语义确定输出到哪个视口。如果想将窗口或分为 4 部分,先创建 4 个视口:

    D3D11_VIEWPORT view_port[];
for ( int i = ; i < ; i++ )
{
view_port[i].Width = ( FLOAT ) width / ;
view_port[i].Height = ( FLOAT ) height / ;
view_port[i].MinDepth = 0.0f;
view_port[i].MaxDepth = 1.0f;
view_port[i].TopLeftX = ;
view_port[i].TopLeftY = ;
}
view_port[].TopLeftX = ( FLOAT ) width / ;
view_port[].TopLeftY = ; view_port[].TopLeftX = ;
view_port[].TopLeftY = ( FLOAT ) height / ; view_port[].TopLeftX = ( FLOAT ) width / ;
view_port[].TopLeftY = ( FLOAT ) height / ;
g_pImmediateContext->RSSetViewports(, view_port);

  接着是几何着色器的设置:

//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
cbuffer ConstantBuffer : register( b0 )
{
matrix World;
matrix View;
matrix Projection;
} //--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
}; //--------------------------------------------------------------------------------------
struct GS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
uint view_idx : SV_VIEWPORTARRAYINDEX;
}; //--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR )
{
VS_OUTPUT output = (VS_OUTPUT);
output.Pos = mul( Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Color = Color;
return output;
} //--------------------------------------------------------------------------------------
// Geometry Shader
//--------------------------------------------------------------------------------------
[maxvertexcount()]
void GS(triangle VS_OUTPUT input[], inout TriangleStream<GS_OUTPUT> output)
{
for(int j = ; j < ; j++)
{
GS_OUTPUT element;
element.view_idx = j; for (uint i = ; i < ;i++)
{
element.Pos = input[i].Pos;
element.Color = input[i].Color;
output.Append(element);
}
output.RestartStrip();
}
} //--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( VS_OUTPUT input ) : SV_Target
{
return input.Color;
}

  在编译并设置几何着色器到渲染管线后,得到以下结果:

基于 DirectX11 的 MMDViewer 04-渲染目标视图和多视口

  因为没有什么文章介绍这种方法的实现,所以在这里简单介绍一下。当然你要可以不这样做,你可以渲染 4 次,每次使用不同的视口,得到和上面一样的结果。

  源码下载:MMDViewer 04.zip

基于 DirectX11 的 MMDViewer 04-渲染目标视图和多视口的更多相关文章

  1. 基于 DirectX11 的 MMDViewer 01-简介

    这个项目主要是为了 DirectX11 而来,前面做了一个关于 OpenGL 的项目,这次打算使用 DirectX11 来做一个 MMD 的模型浏览器.以前,我使用过 DirectX11 来做过一些项 ...

  2. 基于 DirectX11 的 MMDViewer 03-渲染管线

    准备工作: 开始搭建框架之前,你需要确保已经进行了 D3D 开发环境的搭建,相关教程可以阅读这篇文章.不了解 DirectX11 的人,这个作者有关 DirectX11 的教程最好阅读一下,虽然文章不 ...

  3. 基于 DirectX11 的 MMDViewer 02-创建一个窗口

    项目的创建和配置: 1.新建一个 Win32 空项目 2.创建源码文件夹.库文件夹和资源文件夹 3.在 VS2013(我使用的 IDE 是 vs2013)配置这些文件夹 这里使用了 $(Solutio ...

  4. Spring实战第六章学习笔记————渲染Web视图

    Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...

  5. Vuejs - 花式渲染目标元素

    Vue.js是什么 摘自官方文档: Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库 ...

  6. Spring学习&lpar;六&rpar;--渲染Web视图

    一.将模型数据渲染为Html 在上一篇文章中,我们所编写的控制器方法都没有直接产生浏览器中渲染所需的HTML.这些方法只是将数据填充到模型中,然后将模型传递给一个用来渲染的视图.这些方法会返回一个St ...

  7. CVPR2020&vert;3D-VID&colon;基于LiDar Video信息的3D目标检测框架

    作者:蒋天园 Date:2020-04-18 来源:3D-VID:基于LiDar Video信息的3D目标检测框架|CVPR2020 Brief paper地址:https://arxiv.org/p ...

  8. 基于显卡的光栅化渲染器Gaius计划

    决定实现一个基于显卡的光栅化渲染器,能将一些基于显卡的新算法融入其中.

  9. 【Spring】渲染Web视图

    前言 前面学习了编写Web请求的控制器,创建简单的视图,本篇博文讲解控制器完成请求到结果渲染到用户的浏览器的过程. 渲染Web视图 理解视图解析 前面所编写的控制器方法都没有直接产生浏览器中渲染所需要 ...

随机推荐

  1. 在Asp&period;Net中操作PDF – iTextSharp - 使用表格

    使用Asp.Net生成PDF最常用的元素应该是表格,表格可以帮助比如订单或者发票类型的文档更加格式化和美观.本篇文章并不会深入探讨表格,仅仅是提供一个使用iTextSharp生成表格的方法介绍 使用i ...

  2. 不懂CSS也能定制博客界面&excl;

    之前没想过定制博客界面,毕竟CSS,HTML什么的都不懂,不过看了这篇文章分分钟搞定: [详细图解]一步一步教你自定义博客园(cnblog)界面 我是基于模板BlueSky做了些改动,先看修改前后的效 ...

  3. 【读书笔记】WebApi 和 SPA&lpar;单页应用&rpar;--knockout的使用

    Web API从MVC4开始出现,可以服务于Asp.Net下的任何web应用,本文将介绍Web api在单页应用中的使用.什么是单页应用?Single-Page Application最常用的定义:一 ...

  4. 使用本地服务器组来管理局域网或公网上的SQLSERVER

    使用本地服务器组来管理局域网或公网上的SQLSERVER 测试的两台机器 Windows7 64位   SQLSERVER2005 SP5 Windows7 64位   SQLSERVER2012 S ...

  5. Js 正则表达式特殊字符含义

    字符   匹配 \o     null \t      制表符 \n     换行符 \v     垂直制表符 \f     换页符 \r     回车符 \xnn   由十六进制nn指定的拉丁字符 ...

  6. Docker Centos安装Openssh

    环境介绍: Docker版本:1.5.0 镜像:docker.io:centos latest 操作步骤: 1.启动镜像 docker run -ti centos /bin/bash 2.安装pas ...

  7. VisualSVN SERVER的安装和使用

    SVN Server安装 Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说.下载的网址是:http://subversion.apache.org/packages. ...

  8. OSSEC - Agent端查看命令

    命令:/opt/ossec/bin/agent_control -h注释:/opt/为安装目录 [root@redhat rules]# /opt/ossec/bin/agent_control -h ...

  9. Ztree使用

    基础: <link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type ...

  10. Springmvc默认首页的问题

    之前自己写的springmvc 默认首页都是偷懒方式: web.xml 中定义的默认首页: <welcome-file-list> <welcome-file>index.ht ...