原文:
上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧。
具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明。
由于我们要画彩色的立方体,所以顶点结构体中加入颜色变量
struct Vertex{ XMFLOAT3 pos; XMFLOAT4 color;};
着色器代码
1 cbuffer cbPerObject 2 { 3 float4x4 gWorldViewProj; 4 }; 5 6 struct VertexIn 7 { 8 float3 PosL : POSITION; 9 float4 Color : COLOR;10 };11 12 struct VertexOut13 {14 float4 PosH : SV_POSITION;15 float4 Color : COLOR;16 };17 18 VertexOut VS(VertexIn vin)19 {20 VertexOut vout;21 22 // Transform to homogeneous clip space.23 vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);24 25 // Just pass vertex color into the pixel shader.26 vout.Color = vin.Color;27 28 return vout;29 }30 31 float4 PS(VertexOut pin) : SV_Target32 {33 return pin.Color;34 }35 36 technique11 ColorTech37 {38 pass P039 {40 SetVertexShader( CompileShader( vs_5_0, VS() ) );41 SetGeometryShader( NULL );42 SetPixelShader( CompileShader( ps_5_0, PS() ) );43 }44 }
定义了一个矩阵gWorldViewProj,后面我们会利用它进行旋转立方体
BoxDemo.h
1 #pragma once 2 3 #include "Dx11DemoBase.h" 4 #include "d3dx11effect.h" 5 6 class BoxDemo : public Dx11DemoBase 7 { 8 public: 9 BoxDemo();10 ~BoxDemo();11 12 bool LoadContent() override;13 void UnLoadContent() override;14 15 void Update(float dt) override;16 void Render() override;17 18 private:19 ID3D11Buffer *m_pVertexBuffer;20 ID3D11Buffer *m_pIndexBuffer;//新增21 ID3D11InputLayout *m_pInputLayout;22 23 ID3DX11Effect *m_pFx;24 ID3DX11EffectTechnique *m_pTechnique;25 ID3DX11EffectMatrixVariable *m_pFxWorldViewProj;26 XMFLOAT4X4 m_world;27 XMFLOAT4X4 m_view;28 XMFLOAT4X4 m_proj;29 30 };
LoadContent()函数
顶点信息及缓冲的创建
1 Vertex vertices[] = 2 { 3 { XMFLOAT3(-0.5f, -0.5f, -0.5f), XMFLOAT4(255, 255, 255, 1) },//white 4 { XMFLOAT3(-0.5f, +0.5f, -0.5f), XMFLOAT4(0, 0, 0, 1) },//black 5 { XMFLOAT3(+0.5f, +0.5f, -0.5f), XMFLOAT4(255, 0, 0, 1) },//red 6 { XMFLOAT3(+0.5f, -0.5f, -0.5f), XMFLOAT4(0, 255, 0, 1) },//green 7 { XMFLOAT3(-0.5f, -0.5f, +0.5f), XMFLOAT4(0, 0, 255, 1) },//blue 8 { XMFLOAT3(-0.5f, +0.5f, +0.5f), XMFLOAT4(255, 255, 0, 1) },//yellow 9 { XMFLOAT3(+0.5f, +0.5f, +0.5f), XMFLOAT4(0, 255, 255, 1) },//cyan10 { XMFLOAT3(+0.5f, -0.5f, +0.5f), XMFLOAT4(255, 0, 255, 1) }//magenta11 };12 13 14 D3D11_BUFFER_DESC vertexDesc;15 ZeroMemory(&vertexDesc, sizeof(vertexDesc));16 vertexDesc.Usage = D3D11_USAGE_DEFAULT;17 vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;18 vertexDesc.ByteWidth = sizeof(Vertex)* 8;19 20 D3D11_SUBRESOURCE_DATA resourceData;21 ZeroMemory(&resourceData, sizeof(resourceData));22 resourceData.pSysMem = vertices;23 result = m_pd3dDevice->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer);24 if (FAILED(result))25 {26 return false;27 }
相比三角形,立方体还要定义Index信息,来确定立方体的六个面
1 UINT indices[] = { 2 // front face 3 0, 1, 2, 4 0, 2, 3, 5 6 // back face 7 4, 6, 5, 8 4, 7, 6, 9 10 // left face11 4, 5, 1,12 4, 1, 0,13 14 // right face15 3, 2, 6,16 3, 6, 7,17 18 // top face19 1, 5, 6,20 1, 6, 2,21 22 // bottom face23 4, 0, 3,24 4, 3, 725 };26 27 D3D11_BUFFER_DESC indexDesc;28 ZeroMemory(&indexDesc, sizeof(indexDesc));29 indexDesc.Usage = D3D11_USAGE_IMMUTABLE;30 indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;31 indexDesc.ByteWidth = sizeof(UINT)* 36;32 33 D3D11_SUBRESOURCE_DATA indexData;34 ZeroMemory(&indexData, sizeof(indexData));35 indexData.pSysMem = indices;36 result = m_pd3dDevice->CreateBuffer(&indexDesc, &indexData, &m_pIndexBuffer);37 if (FAILED(result))38 {39 return false;40 }
定义输入布局
1 D3D11_INPUT_ELEMENT_DESC solidColorLayout[] = 2 { 3 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 4 { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } 5 }; 6 UINT numLayoutElements = ARRAYSIZE(solidColorLayout); 7 D3DX11_PASS_DESC passDesc; 8 m_pTechnique->GetPassByIndex(0)->GetDesc(&passDesc); 9 10 result = m_pd3dDevice->CreateInputLayout(solidColorLayout, numLayoutElements, passDesc.pIAInputSignature,11 passDesc.IAInputSignatureSize, &m_pInputLayout);
Update()函数----实现旋转
怎么实现立方体的旋转呢?我们之前不是给出了 world,view,proj三个矩阵吗,实现旋转的一种方式就是根据游戏时间旋转相应矩阵(例如world矩阵)。
可以定义一个静态变量表示游戏时间,每一帧运行时更新t值,同时对矩阵作相应旋转即可。
1 static float t = 0.0f; 2 t += (float)XM_PI * 0.0125f; 3 static DWORD dwTimeStart = 0; 4 DWORD dwTimeCur = GetTickCount(); 5 if (dwTimeStart == 0) 6 dwTimeStart = dwTimeCur; 7 t = (dwTimeCur - dwTimeStart) / 1000.0f; 8 9 XMVECTOR pos = XMVectorSet(2.0f, 0.0f, 0.0f, 1.0f);10 XMVECTOR target = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);11 XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);12 13 XMMATRIX V = XMMatrixLookAtLH(pos, target, up);14 XMStoreFloat4x4(&m_view, V);15 XMMATRIX T = XMMatrixPerspectiveFovLH(XM_PIDIV2, m_width / static_cast(m_height),16 0.01f, 100.0f);17 XMStoreFloat4x4(&m_proj, T);18 //根据时间旋转world矩阵19 XMMATRIX P = XMMatrixRotationY(t);20 XMStoreFloat4x4(&m_world, P);
Render()函数
和之前的代码大部分一样,不同的是要设置IndexBuffer,绘制的时候要用DrawIndexed()而不是Draw().
1 if (m_pImmediateContext == 0) 2 return; 3 //清除渲染目标视图 4 float clearColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };//背景颜色 5 m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, clearColor); 6 7 UINT stride = sizeof(Vertex); 8 UINT offset = 0; 9 //设置数据信息格式控制信息10 m_pImmediateContext->IASetInputLayout(m_pInputLayout);11 //设置要绘制的几何体信息12 m_pImmediateContext->IASetVertexBuffers(0,1,&m_pVertexBuffer,&stride,&offset);13 m_pImmediateContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0);14 //指明如何绘制15 m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);16 17 //设置常量 18 XMMATRIX world = XMLoadFloat4x4(&m_world);19 XMMATRIX view = XMLoadFloat4x4(&m_view);20 XMMATRIX proj = XMLoadFloat4x4(&m_proj);21 XMMATRIX worldViewProj = world*view*proj;22 m_pFxWorldViewProj->SetMatrix(reinterpret_cast(&worldViewProj));23 24 D3DX11_TECHNIQUE_DESC techDesc;25 m_pTechnique->GetDesc(&techDesc);26 for (UINT i = 0; i < techDesc.Passes; ++i)27 {28 m_pTechnique->GetPassByIndex(i)->Apply(0, m_pImmediateContext);29 m_pImmediateContext->DrawIndexed(36, 0, 0);30 }31 //马上输出32 m_pSwapChain->Present(0, 0);
这样我们的工作都完成了,运行便可以得到一个旋转的彩色立方体了.
下面是运行的一个截图
posted on 2019-05-05 12:59 阅读( ...) 评论( ...)