承接上次的渲染方体。我们用同样步骤来实现一个山峰,和上次方体的一点不同的就是,再新建了一个类,封装了常用的几何体(网格,方体,球体等)的新建顶点、索引操作。
(一) 定义结构点:
//Vertex.h
namespace Vertex
{
struct mountainVertex
{...
};
}
构成点的元素(位置 颜色 纹理等)进行描述
//vertex.cpp
const D3D11_INPUT_ELEMENT_DESC InputLayoutDec::MountainVertexs[] =
{...
};
Effect是一样的
建立inputlayout
//Vertex.h
ID3D11InputLayout* InputLayouts::Mountain = 0;
void InputLayouts::CreateInputLayouts(ID3D11Device* device)
{ ...
HR(device->CreateInputLayout(InputLayoutDec::MountainVertexs, 2, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &Mountain));
}
(二)
//GeometryHelper.h
class GeoGen
{
public:
struct Vertex
{
Vertex(){}
Vertex(const XMFLOAT3& pos,const XMFLOAT3& nor,const XMFLOAT3& tex, const XMFLOAT2& uv)
:Position(pos),Normal(nor),TangentU(tex),TexC(uv){}
Vertex(
float px, float py, float pz,
float nx, float ny, float nz,
float tx, float ty, float tz,
float u, float v)
: Position(px,py,pz), Normal(nx,ny,nz),
TangentU(tx, ty, tz), TexC(u,v){}
XMFLOAT3 Position;
XMFLOAT3 Normal;
XMFLOAT3 TangentU;
XMFLOAT2 TexC;
}; //类里面的VERTEX定义,主要是服务于类里面的顶点定义,通过观察vertex的构造函数,可以看出position,normal,texture的内容。
//用于返回到cpp,方便管理?
struct MeshData
{
std::vector<Vertex> Vertices;
std::vector<UINT> Indices;
};
//建立正方体
void CreateBox(float width, float height, float depth, MeshData& meshData);
//建立圆球
void CreateSphere(float radius, UINT sliceCount, UINT stackCount, MeshData& meshData);
//另一种方式建立圆球
void CreateGeosphere(float radius,UINT numSubdivisions, MeshData& meshData);
//建立圆柱
void CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData);
//建立方格
void CreateGrid(float width, float depth, UINT m, UINT n, MeshData& meshData);
//建立满屏四边形?
void CreateFullscreenQuad(MeshData& meshData);
private:
void Subdivide(MeshData& meshData);
//建立圆柱顶盖,底盖
void BuildCylinderTopCap(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData);
void BuildCylinderBottomCap(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData);
};
//GeometryHelper.cpp
void GeoGen::CreateGrid(float width, float depth, UINT m, UINT n, MeshData& meshData)
{
UINT vertexCount = m*n;
UINT faceCount = (m-1)*(n-1)*2;
// 建立点
float halfWidth = 0.5f*width;
float halfDepth = 0.5f*depth;
float dx = width / (n-1);
float dz = depth / (m-1);
float du = 1.0f / (n-1);
float dv = 1.0f / (m-1);
meshData.Vertices.resize(vertexCount);
for(UINT i = 0; i < m; ++i)
{
float z = halfDepth - i*dz;
for(UINT j = 0; j < n; ++j)
{
float x = -halfWidth + j*dx;
meshData.Vertices[i*n+j].Position = XMFLOAT3(x, 0.0f, z);
meshData.Vertices[i*n+j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
meshData.Vertices[i*n+j].TangentU = XMFLOAT3(1.0f, 0.0f, 0.0f);
// Stretch texture over grid.
meshData.Vertices[i*n+j].TexC.x = j*du;
meshData.Vertices[i*n+j].TexC.y = i*dv;
}
}
// 建立索引.
meshData.Indices.resize(faceCount*3); // 3 indices per face
// Iterate over each quad and compute indices.
UINT k = 0;
for(UINT i = 0; i < m-1; ++i)
{
for(UINT j = 0; j < n-1; ++j)
{
meshData.Indices[k] = i*n+j;
meshData.Indices[k+1] = i*n+j+1;
meshData.Indices[k+2] = (i+1)*n+j;
meshData.Indices[k+3] = (i+1)*n+j;
meshData.Indices[k+4] = i*n+j+1;
meshData.Indices[k+5] = (i+1)*n+j+1;
k += 6;
}
}
}
//mountainDemo.cpp
void moutainApp::BuildVerInBuffers()
{
GeoGen::MeshData grid;
GeoGen geoGen;
geoGen.CreateGrid(160.0f, 160.0f, 50, 50, grid);
mLandIndexCount = grid.Indices.size(); //Vertex的自带函数
//vertices要改变一下
std::vector<Vertex::mountainVertex> vertices(grid.Vertices.size());
for(size_t i = 0; i < grid.Vertices.size(); ++i)
{
XMFLOAT3 p = grid.Vertices[i].Position;
p.y = GetHillHeight(p.x, p.z);
vertices[i].pos = p;
// 根据顶点高度设置颜色
if( p.y < -10.0f )
{
// 沙滩色
vertices[i].Color = XMFLOAT4(1.0f, 0.96f, 0.62f, 1.0f);
}
else if( p.y < 5.0f )
{
// 淡绿色
vertices[i].Color = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
}
else if( p.y < 12.0f )
{
// 深绿色
vertices[i].Color = XMFLOAT4(0.1f, 0.48f, 0.19f, 1.0f);
}
else if( p.y < 20.0f )
{
// 棕色
vertices[i].Color = XMFLOAT4(0.45f, 0.39f, 0.34f, 1.0f);
}
else
{
// 白色
vertices[i].Color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
}
}
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex::mountainVertex) * grid.Vertices.size();
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mVB));
// 要创建的索引的描述
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * mLandIndexCount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;
// 设定用于初始化索引缓冲的数据
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &grid.Indices[0];
// 创建索引缓冲
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIB));
};
<pre name="code" class="cpp">float moutainApp::GetHillHeight(float x, float z)const
{
return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) );
}
void moutainApp::Draw()
{
...
for(UINT p = 0; p < techDesc.Passes; ++p)
{
Effects::BasicFX->Tech->GetPassByIndex(p)->Apply(0, md3dContext);
md3dContext->DrawIndexed(mLandIndexCount, 0, 0);
}
HR(mSwapChain->Present(0, 0));
}
配套代码:
http://download.csdn.net/detail/vwwyohann/9215151