用DirectX 11绘制一个Cube
之前一篇文章讲了如何初始化DirectX 11,现在在此基础上绘制一个Cube,总体可概括为以下几个步骤:
- 定义Cube顶点数据结构
- 创建Vertex Buffer和Index Buffer
- 编写应用于Cube的effect file
- 读取effect,编译创建
- 根据顶点数据结构,创建input layout,将顶点与effect中VS的input signature关联
- 开始绘制,clear掉render target view和depth stencil view
- 设置若干IA参数,input layout,primitive toplogy,vertex buffer,index buffer
- 将一些必要参数设置给effect的cbuffer中,如worldViewProjMatrix
- 将effect的每个pass依次apply到context中,进行绘制
- 绘制提交,结束绘制
定义Cube顶点数据结构
当前只需要顶点的position和color属性,position是三维向量,color是四维向量,定义如下:
struct Vertex
{
XMFLOAT3 position;
XMFLOAT4 color;
};
这里用的是DirectXmath.h
中的XMFLOAT3
和XMFLOAT4
,也可以用自定义的向量类。
创建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
可以被当作是两者关联的桥梁,现在顶点只有position
和color
两个属性,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的更多相关文章
- 用DirectX12绘制一个Cube
之前一篇文章讲了DirectX12的初始化流程,现在来看看在此基础上如何绘制一个Cube. 首先,我们要为这个Cube准备一个shader,来告诉GPU绘制的具体流程,DirectX中的shader使 ...
- Unity3d修炼之路:用Mesh绘制一个Cube
#pragma strict function Awake(){ var pMeshFilter : MeshFilter = gameObject.AddComponent(typeof(MeshF ...
- DX11 Without DirectX SDK--03 渲染一个立方体
回到 DirectX11--使用Windows SDK来进行开发 一个立方体有8个顶点,然而绘制一个立方体需要画12个三角形,如果按照前面的方法绘制的话,则需要提供36个顶点,而且这里面的顶点数据会重 ...
- {转自MC}NVIDIA DirectX 11演示DEMO详解
http://tieba.baidu.com/p/1960826986 图形技术无论如何发展,最终都要落到实际的应用中才有效果.在个人电脑上,图形技术最大的用户除了显示UI和操作界面外,就是呈现美轮美 ...
- DirectX 文本绘制
在Direct中进行文本绘制,可以通过Win32程序框架实现,也可以通过DXUT进行绘制. 基于第一篇的Win32框架入门实现非常简单,只需要添加数行代码即可.主要说需要修改的地方. #pragma ...
- Introduction to 3D Game Programming with DirectX 11 翻译--开篇
Direct3D 11简介 Direct3D 11是一个渲染库,用于在Windows平台上使用现代图形硬件编写高性能3D图形应用程序.Direct3D是一个windows底层库,因为它的应用程序编程接 ...
- CAD绘制一个单行文字(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawText 绘制一个单行文字.详细说明如下: 参数 说明 DOUBLE dPosX >文字的位置的X坐标 DOUBLE dPosY 文字的位置的Y ...
- CAD绘制一个对齐标注(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawDimAligned 绘制一个对齐标注.详细说明如下: 参数 说明 DOUBLE dExtLine1PointX 第一条界线开始点X值 DOUBLE ...
- CAD绘制一个角度标注(com接口VB语言)
主要用到函数说明: _DMxDrawX::DrawDimAngular 绘制一个角度标注.详细说明如下: 参数 说明 DOUBLE dAngleVertexX 角度标注的顶点的X值 DOUBLE dA ...
随机推荐
- [sql 注入] insert 报错注入与延时盲注
insert注入的技巧在于如何在一个字段值内构造闭合. insert 报错注入 演示案例所用的表: MariaDB [mysql]> desc test; +--------+--------- ...
- 攻克solo第七课(Randy Rhoads风格)
本期文章,笔者将通过Guitar Pro 7吉他软件跟大家分享一下Randy Rhoads的solo句子. 相信很多精研电吉他的朋友都会听过这个一手把Ozzy Osbourne从离开黑色安息日乐队的深 ...
- CorelDRAW 里面如何将文字调整成半透明的颜色
早在几年前,平面设计师在做设计时会遇到关于印刷的难题,那就是为了降低印刷成本,必须减少他们的颜色数量.随着印刷方法的进步,特别是数字出版物的兴起,我们生活在一个主要是通过屏幕观看图形的时代,一个可以显 ...
- PowerPoint无法正常加载MathType的解决方法
MathType是一款十分便捷的数学公式编辑器,可以和很多办公软件和网站兼容使用,我们日常用的比较多的也就是Office和WPS,更具体的说是Word\Excel\PPT等等一系列办公常用软件. 不过 ...
- 网络系列之GET与POST请求方式的区别
作为一枚正在学习前端的 小萌新,如果下面哪里有写的不对的话,可以帮我指出来吗,谢谢 1.是基于什么前提的?如果什么前提都没有,不使用任何规范,只考虑语法和理论上的HTTP协议 那么GET和POST几乎 ...
- redis启动报错Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接。
报错内容 解决办法 启动redis-server服务 测试 连接成功
- LeetCode 046 Permutations
题目要求:Permutations(全排列) Given a collection of numbers, return all possible permutations. For example, ...
- java43
自定义日期格式 import java.text.DateFormat; import java.text.ParseException; import java.util.Date; public ...
- K 均值算法-如何让数据自动分组
公号:码农充电站pro 主页:https://codeshellme.github.io 之前介绍到的一些机器学习算法都是监督学习算法.所谓监督学习,就是既有特征数据,又有目标数据. 而本篇文章要介绍 ...
- 20200203_windows2012下安装mysql 5.7.29
一. 检查系统版本: 二. 下载mysql, 下载地址: https://dev.mysql.com/downloads/mysql/5.7.html#downloads 三. 解压下载后的压 ...