#include <WinApp.h>
#include <Lights.h>
#include <AppUtil.h>
#include <GeometryGens.h>
#include "Inputs.h"
#include "Effects.h"
#include <vector>
#include <string>
#include <RenderStates.h>
using namespace std;
class BlendDemo: public WinApp
{
public:
BlendDemo(HINSTANCE hInst, std::wstring title = L"D3D11学习 混合(Blending)", int width = 640, int height = 480);
~BlendDemo();
bool Init();
bool Update(float delta);
bool Render();
void OnMouseDown(WPARAM btnState, int x, int y);
void OnMouseUp(WPARAM btnState, int x, int y);
void OnMouseMove(WPARAM btnState, int x, int y);
private:
//创建顶点、索引缓冲区
bool BuildBuffers();
//创建ShaderResourceView
bool BuildSRVs();
private:
ID3D11Buffer *m_VB;
ID3D11Buffer *m_IB;
//3个平行光源(三点式照明)
Lights::DirLight m_dirLights[3];
GeoGen::MeshData m_basin; //水池(包括池壁、池底)
GeoGen::MeshData m_water; //水面
GeoGen::MeshData m_box; //箱子
Lights::Material m_materialWater; //水面材质
Lights::Material m_materialBasin; //水池材质
Lights::Material m_materialBox; //箱子材质
ID3D11ShaderResourceView *m_SRVBasin; //水池壁纹理
ID3D11ShaderResourceView *m_SRVBasinB; //水池底纹理
ID3D11ShaderResourceView *m_SRVWater; //水面纹理
ID3D11ShaderResourceView *m_SRVBox; //箱子纹理
XMFLOAT4X4 m_worldBasin; //世界变换矩阵
XMFLOAT4X4 m_worldViewProjBasin; //世界+视角+投影矩阵
XMFLOAT4X4 m_worldInvTransposeBasin; //世界矩阵的逆+转置,用于法线转换
XMFLOAT4X4 m_texTransBasin; //纹理坐标变换矩阵
XMFLOAT4X4 m_worldBasinB; //同上
XMFLOAT4X4 m_worldViewProjBasinB;
XMFLOAT4X4 m_worldInvTransposeBasinB;
XMFLOAT4X4 m_texTransBasinB;
XMFLOAT4X4 m_worldBox; //同上
XMFLOAT4X4 m_worldViewProjBox;
XMFLOAT4X4 m_worldInvTransposeBox;
XMFLOAT4X4 m_texTransBox;
XMFLOAT4X4 m_worldWater; //同上
XMFLOAT4X4 m_worldViewProjWater;
XMFLOAT4X4 m_worldInvTransposeWater;
XMFLOAT4X4 m_texTransWater;
//用来标记各物体在顶点、索引缓冲区中的位置信息
UINT m_basinVStart, m_basinIStart; //水池壁的顶点、索引开始处
UINT m_basinBVStart, m_basinBIStart; //水池底的顶点、索引开始处
UINT m_basinICount, m_basinBICount; //水池壁、水池底的索引个数
UINT m_boxVStart, m_boxIStart; //箱子的顶点、索引开始处
UINT m_waterVStart, m_waterIStart; //水面的顶点、索引开始处
//鼠标控制参数
float m_theta, m_phy;
float m_radius;
POINT m_lastPos;
};
BlendDemo::BlendDemo(HINSTANCE hInst, std::wstring title, int width, int height):WinApp(hInst,title,width,height),
m_VB(NULL),
m_IB(NULL),
m_SRVBasin(NULL),
m_SRVBasinB(NULL),
m_SRVBox(NULL),
m_theta(0.25f*XM_PI),
m_phy(XM_PI*0.45f),
m_radius(8.f)
{
//"三点式"照明
//主光源
m_dirLights[0].ambient = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
m_dirLights[0].diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
m_dirLights[0].specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
m_dirLights[0].dir = XMFLOAT3(0.57735f, -0.57735f, 0.57735f);
//侧光源
m_dirLights[1].ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
m_dirLights[1].diffuse = XMFLOAT4(0.20f, 0.20f, 0.20f, 1.0f);
m_dirLights[1].specular = XMFLOAT4(0.25f, 0.25f, 0.25f, 1.0f);
m_dirLights[1].dir = XMFLOAT3(-0.57735f, -0.57735f, 0.57735f);
//背光源
m_dirLights[2].ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
m_dirLights[2].diffuse = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
m_dirLights[2].specular = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
m_dirLights[2].dir = XMFLOAT3(0.0f, -0.707f, -0.707f);
//材质
m_materialBasin.ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
m_materialBasin.diffuse = XMFLOAT4(1.f, 1.f, 1.f, 1.0f);
m_materialBasin.specular = XMFLOAT4(0.3f, 0.3f, 0.3f, 16.0f);
m_materialBox.ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
m_materialBox.diffuse = XMFLOAT4(1.f, 1.f, 1.f, 1.0f);
m_materialBox.specular = XMFLOAT4(0.3f, 0.3f, 0.3f, 16.0f);
m_materialWater.ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
m_materialWater.diffuse = XMFLOAT4(1.0f, 1.0f, 1.0f, 0.5f);
m_materialWater.specular = XMFLOAT4(0.8f, 0.8f, 0.8f, 32.0f);
//初始化各自的世界变换矩阵及其逆+转置矩阵、纹理坐标变换矩阵
//这些矩阵是固定不变的,因此一次初始化
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&m_worldBasin,I);
XMStoreFloat4x4(&m_worldInvTransposeBasin,InverseTranspose(I));
XMStoreFloat4x4(&m_worldBasinB,I);
XMStoreFloat4x4(&m_worldInvTransposeBasinB,InverseTranspose(I));
XMMATRIX wBox = XMMatrixTranslation(0.f,-1.f,0.f);
XMStoreFloat4x4(&m_worldBox,wBox);
XMStoreFloat4x4(&m_worldInvTransposeBox,InverseTranspose(wBox));
XMMATRIX wWater = XMMatrixTranslation(0.f,-1.f,0.f);
XMStoreFloat4x4(&m_worldWater,wWater);
XMStoreFloat4x4(&m_worldInvTransposeWater,InverseTranspose(wWater));
XMMATRIX texTransBasin = XMMatrixScaling(10.f,1.f,1.f);
XMMATRIX texTransWater = XMMatrixScaling(5.f,5.f,1.f);
//纹理坐标变换矩阵
XMStoreFloat4x4(&m_texTransBasin,texTransBasin);
XMStoreFloat4x4(&m_texTransBasinB,XMMatrixIdentity());
XMStoreFloat4x4(&m_texTransWater,texTransWater);
XMStoreFloat4x4(&m_texTransBox,XMMatrixIdentity());
}
BlendDemo::~BlendDemo()
{
SafeRelease(m_IB);
SafeRelease(m_VB);
SafeRelease(m_SRVBasin);
SafeRelease(m_SRVBasinB);
SafeRelease(m_SRVWater);
SafeRelease(m_SRVBox);
RenderStates::ReleaseAll();
InputLayouts::ReleaseAll();
Effects::ReleaseAll();
}
bool BlendDemo::BuildBuffers()
{
//创建水池壁的顶点、索引(圆柱的侧壁)
GeoGen::CreateCylinder(10.f,10.f,4.f,50,10,m_basin);
m_basinVStart = 0;
m_basinIStart = 0;
m_basinICount = m_basin.indices.size();
m_basinBVStart = m_basin.vertices.size();
m_basinBIStart = m_basin.indices.size();
//添加水池底顶点、索引(圆柱的底)
GeoGen::AddCylinderBottomCap(10.f,10.f,4.f,50,10,m_basin);
m_basinBICount = m_basin.indices.size()-m_basinICount;
//创建水面的顶点、索引(网格)
GeoGen::CreateGrid(20.f,20.f,1,1,m_water);
m_waterIStart = m_basin.indices.size();
m_waterVStart = m_basin.vertices.size();
//创建箱子的顶点、索引
GeoGen::CreateBox(2.f,2.f,2.f,m_box);
m_boxIStart = m_waterIStart + m_water.indices.size();
m_boxVStart = m_waterVStart + m_water.vertices.size();
UINT totalV = m_basin.vertices.size()+m_water.vertices.size()+m_box.vertices.size();
UINT totalI = m_basin.indices.size()+m_water.indices.size()+m_box.indices.size();
//开始创建顶点缓冲区
D3D11_BUFFER_DESC vDesc = {0};
vDesc.ByteWidth = sizeof(Vertex::Basic32)*totalV;
vDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vDesc.Usage = D3D11_USAGE_IMMUTABLE;
std::vector<Vertex::Basic32> vertices(totalV);
for(UINT i=0; i<m_basin.vertices.size(); ++i)
{
vertices[i].pos = m_basin.vertices[i].pos;
//法线方向取反
//对于水池壁,法线指向水池内侧;对于水池底,法线指向上方
XMFLOAT3 normal = m_basin.vertices[i].normal;
vertices[i].normal = XMFLOAT3(-normal.x,-normal.y,-normal.z);
vertices[i].tex = m_basin.vertices[i].tex;
}
for(UINT i=0; i<m_water.vertices.size(); ++i)
{
vertices[i+m_waterVStart].pos = m_water.vertices[i].pos;
vertices[i+m_waterVStart].normal = m_water.vertices[i].normal;
vertices[i+m_waterVStart].tex = m_water.vertices[i].tex;
}
for(UINT i=0; i<m_box.vertices.size(); ++i)
{
vertices[i+m_boxVStart].pos = m_box.vertices[i].pos;
vertices[i+m_boxVStart].normal = m_box.vertices[i].normal;
vertices[i+m_boxVStart].tex = m_box.vertices[i].tex;
}
D3D11_SUBRESOURCE_DATA vData;
vData.pSysMem = &vertices[0];
vData.SysMemPitch = 0;
vData.SysMemSlicePitch = 0;
if(FAILED(m_d3dDevice->CreateBuffer(&vDesc,&vData,&m_VB)))
{
MessageBox(NULL,L"Create Vertex Buffer failed!",L"Error",MB_OK);
return false;
}
//开始创建索引缓冲区
D3D11_BUFFER_DESC iDesc = {0};
iDesc.ByteWidth = sizeof(UINT)*(totalI);
iDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
iDesc.Usage = D3D11_USAGE_IMMUTABLE;
std::vector<UINT> indices(totalI);
for(UINT i=0; i<m_basin.indices.size(); ++i)
{
indices[i] = m_basin.i
- 1
- 2
- 3
前往页