之前一篇文章讲了如何初始化DirectX 11,现在在此基础上绘制一个Cube,总体可概括为以下几个步骤:

  1. 定义Cube顶点数据结构
  2. 创建Vertex Buffer和Index Buffer
  3. 编写应用于Cube的effect file
  4. 读取effect,编译创建
  5. 根据顶点数据结构,创建input layout,将顶点与effect中VS的input signature关联
  6. 开始绘制,clear掉render target view和depth stencil view
  7. 设置若干IA参数,input layout,primitive toplogy,vertex buffer,index buffer
  8. 将一些必要参数设置给effect的cbuffer中,如worldViewProjMatrix
  9. 将effect的每个pass依次apply到context中,进行绘制
  10. 绘制提交,结束绘制

定义Cube顶点数据结构

当前只需要顶点的position和color属性,position是三维向量,color是四维向量,定义如下:

	struct Vertex
{
XMFLOAT3 position;
XMFLOAT4 color;
};

这里用的是DirectXmath.h中的XMFLOAT3XMFLOAT4,也可以用自定义的向量类。

创建Vertex Buffer和Index Buffer

HRESULT CreateBuffer(
const D3D11_BUFFER_DESC *pDesc,
const D3D11_SUBRESOURCE_DATA *pInitialData,
ID3D11Buffer **ppBuffer
);

主要用到的是ID3D11Device::CreateBuffer这一函数。其中,pDesc主要设置要创建的buffer大小,用途,是否cpu可访问等等,D3D11_BIND_VERTEX_BUFFER用于创建vertex buffer,D3D11_BIND_INDEX_BUFFER用于创建index buffer;pInitialData存放的是初始化数据。

编写应用于Cube的effect file

这个effect效果很简单,就是将Cube变换到正确的屏幕空间位置,设置为插值后的颜色。大致包括的内容如下:

cbuffer cbPerObject
{
float4x4 gWorldViewProj;
}; struct VertexIn
{
float3 posL : POSITION;
float4 color : COLOR;
}; struct VertexOut
{
float4 posH : SV_POSITION;
float4 color : COLOR;
}; VertexOut VS(VertexIn vIn)
{
VertexOut vOut;
vOut.posH = mul(float4(vIn.posL, 1.0f), gWorldViewProj);
vOut.color = vIn.color; return vOut;
} float4 PS(VertexOut pIn) : SV_TARGET
{
return pIn.color;
} technique11 ColorTech
{
pass P0
{
SetVertexShader(CompileShader(vs_5_0, VS()));
SetPixelShader(CompileShader(ps_5_0, PS()));
}
}

cBuffer存放的是要从外部读取的数据,这里就是个MVP矩阵了。

读取effect,编译创建

HRESULT D3DX11CompileFromFile(
_In_ LPCTSTR pSrcFile,
_In_ const D3D10_SHADER_MACRO *pDefines,
_In_ LPD3D10INCLUDE pInclude,
_In_ LPCSTR pFunctionName,
_In_ LPCSTR pProfile,
_In_ UINT Flags1,
_In_ UINT Flags2,
_In_ ID3DX11ThreadPump *pPump,
_Out_ ID3D10Blob **ppShader,
_Out_ ID3D10Blob **ppErrorMsgs,
_Out_ HRESULT *pHResult
);

这里,我们要编译整个effect而不是某个shader,因而将pFunctionName设置为nullptr。得到编译后的effect后:

HRESULT D3DX11CreateEffectFromMemory(
void *pData,
SIZE_T DataLength,
UINT FXFlags,
ID3D11Device *pDevice,
ID3DX11Effect **ppEffect
);

effect创建完成。

创建input layout

input layout将定义的顶点结构与effect中VS的input结构关联,为VS中的input指定输入来源。

HRESULT CreateInputLayout(
const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
UINT NumElements,
const void *pShaderBytecodeWithInputSignature,
SIZE_T BytecodeLength,
ID3D11InputLayout **ppInputLayout
);

pInputElementDescs可以被当作是两者关联的桥梁,现在顶点只有positioncolor两个属性,pInputElementDescs定义如下:

D3D11_INPUT_ELEMENT_DESC VertexDesc[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
};

D3D11_APPEND_ALIGNED_ELEMENT这个宏省去了自己计算每个分量偏移的麻烦。

绘制

首先,清空back buffer和depth/stencil buffer;

void ClearRenderTargetView(
ID3D11RenderTargetView *pRenderTargetView,
const FLOAT [4] ColorRGBA
);
void ClearDepthStencilView(
ID3D11DepthStencilView *pDepthStencilView,
UINT ClearFlags,
FLOAT Depth,
UINT8 Stencil
);

接下来,设置若干IA参数,这里我们需要的就是input layout关联,绘制基本primitive的类型,还有设置vertex buffer和index buffer。

void IASetInputLayout(
ID3D11InputLayout *pInputLayout
);
void IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY Topology
);
void IASetVertexBuffers(
UINT StartSlot,
UINT NumBuffers,
ID3D11Buffer * const *ppVertexBuffers,
const UINT *pStrides,
const UINT *pOffsets
);
void IASetIndexBuffer(
ID3D11Buffer *pIndexBuffer,
DXGI_FORMAT Format,
UINT Offset
);

值得一提的是,vertex buffer可以存在多个,index buffer只能存在一个。不同的vertex buffer会分配到不同的input slots中去,这里只用到了一个vertex buffer,暂时不考虑多个input slots的情况。

在effect渲染之前,往往存在需要设置一些参数给effect的情况,比如我们这个例子,就需要把MVP矩阵传给effect:

		XMMATRIX worldViewProj = world * view * proj;
shaderMVP->SetMatrix(reinterpret_cast<float*>(&worldViewProj));

然后就到了正式的绘制阶段,将effect的每个pass依次apply到context中,进行绘制:

		D3DX11_TECHNIQUE_DESC techDesc;
shaderTech->GetDesc(&techDesc);
for (UINT i = 0; i < techDesc.Passes; ++i)
{
shaderTech->GetPassByIndex(i)->Apply(0, mD3dImmediateContext);
mD3dImmediateContext->DrawIndexed(36, 0, 0);
}

一个Cube有6个面,描述一个面需要6个index,所以总共是36个index。

最后不要忘记将绘制内容提交:

mSwapChain->Present(0, 0);

运行效果如图:

用DirectX 11绘制一个Cube的更多相关文章

  1. 用DirectX12绘制一个Cube

    之前一篇文章讲了DirectX12的初始化流程,现在来看看在此基础上如何绘制一个Cube. 首先,我们要为这个Cube准备一个shader,来告诉GPU绘制的具体流程,DirectX中的shader使 ...

  2. Unity3d修炼之路:用Mesh绘制一个Cube

    #pragma strict function Awake(){ var pMeshFilter : MeshFilter = gameObject.AddComponent(typeof(MeshF ...

  3. DX11 Without DirectX SDK--03 渲染一个立方体

    回到 DirectX11--使用Windows SDK来进行开发 一个立方体有8个顶点,然而绘制一个立方体需要画12个三角形,如果按照前面的方法绘制的话,则需要提供36个顶点,而且这里面的顶点数据会重 ...

  4. {转自MC}NVIDIA DirectX 11演示DEMO详解

    http://tieba.baidu.com/p/1960826986 图形技术无论如何发展,最终都要落到实际的应用中才有效果.在个人电脑上,图形技术最大的用户除了显示UI和操作界面外,就是呈现美轮美 ...

  5. DirectX 文本绘制

    在Direct中进行文本绘制,可以通过Win32程序框架实现,也可以通过DXUT进行绘制. 基于第一篇的Win32框架入门实现非常简单,只需要添加数行代码即可.主要说需要修改的地方. #pragma  ...

  6. Introduction to 3D Game Programming with DirectX 11 翻译--开篇

    Direct3D 11简介 Direct3D 11是一个渲染库,用于在Windows平台上使用现代图形硬件编写高性能3D图形应用程序.Direct3D是一个windows底层库,因为它的应用程序编程接 ...

  7. CAD绘制一个单行文字(com接口VB语言)

    主要用到函数说明: _DMxDrawX::DrawText 绘制一个单行文字.详细说明如下: 参数 说明 DOUBLE dPosX >文字的位置的X坐标 DOUBLE dPosY 文字的位置的Y ...

  8. CAD绘制一个对齐标注(com接口VB语言)

    主要用到函数说明: _DMxDrawX::DrawDimAligned 绘制一个对齐标注.详细说明如下: 参数 说明 DOUBLE dExtLine1PointX 第一条界线开始点X值 DOUBLE ...

  9. CAD绘制一个角度标注(com接口VB语言)

    主要用到函数说明: _DMxDrawX::DrawDimAngular 绘制一个角度标注.详细说明如下: 参数 说明 DOUBLE dAngleVertexX 角度标注的顶点的X值 DOUBLE dA ...

随机推荐

  1. Fruity Parametric EQ 2使用说明(二)——FL Studio插件教程

    Fruity Parametric EQ 2均衡器,是一款我们在FL Studio制作音乐时经常会用到的插件,它是EQ中的战斗鸡,它不仅有一个高级的 7 波段参数均衡器,还具有声谱分析能力.我们在对很 ...

  2. FLstudio 系列教程(七):FL Studio五大常用按钮介绍

    我们打开FL Studio编曲软件会发现界面中有好多的菜单和窗口,这些窗口每个都有其单独的功能.今天小编主要给大家详细讲解下FL Studio水果软件的五大常用按钮. 1.首先我,我们双击桌面的水果图 ...

  3. 【应用服务 App Service】解决无法从Azure门户SSH登录问题

    问题描述 中国区的Azure App Service(应用服务)已经支持创建Docker并选择Linux环境.在使用中,我们可以继续通过kudu站点的方式登录查看站点的一些日志及部署文件.它的登录方式 ...

  4. 解决YUM下Loaded plugins: fastestmirror Determining fastest mirrors 的错误问题

    最近想再购买一台虚拟服务器做项目测试,之前在西部数码购买的已经过期了,在同事的推荐下去搬瓦工购买了一台服务器,听他介绍在这里购买服务器很便宜($19.99/年)而且还是国外的,看着相比之前的确实挺便宜 ...

  5. Spring Framework 5.0简述

    从Spring框架5.0开始,Spring需要JDK 8+ (Java SE 8+),并且已经为JDK 9提供了现成的支持. Spring框架还支持依赖注入(JSR 330)和通用注释(JSR 250 ...

  6. Prafab Varient 预制体变体

    预制体与类的类比思维:     预制体相当于一个类,当它应用到场景当中,就是一个实例. 类的继承特性也充分运用到预制体中,即预制体变体. 相似预制体的需求场景:         例子1:多个游戏的窗口 ...

  7. Android开发环境及Hello World程序

    Android的开发需要以下四个工具: 1. JDK 2. Eclipse 3. Android SDK 4. ADT 具体功能: 1. JDK.JDK即Java Development Kit(Ja ...

  8. Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: aidl is missing from '/Users/renguodong/Library/Android/sdk/build-tools/26.0.2/aidl'

    错误信息:Error:Execution failed for task ':app:compileDebugAidl'. > java.lang.IllegalStateException: ...

  9. python数据更新

    def cal(s,m): if s==u"废弃" or s==u"拆除": return 4 elif s==u"竣工": return ...

  10. Java读书计划和分享

    写在前面 为什么要写这些呢? 接触java已经有三年多了,感触颇多,比如从0到60,只要勤实践.勤思考,很快就可以入门,从60分到满分极致,则单单不是凭借工作年限或者什么就可以.曾经也有过一段迷茫时期 ...