Windows 8 Directx 开发学习笔记(六)添加水模型
来源:互联网 发布:mac系统压缩文件 编辑:程序博客网 时间:2024/05/19 03:43
HillExample已经完成山峰河谷的模型,可惜的是河谷是旱季的河谷,没有水。这次的目标就在河谷里注入水。
首先新建HillWaterExample项目,其配置与HillExample项目相同。然后复制HillExample中CubeRenderer.cpp和CubeRenderer.h文件到HillWaterExample目录覆盖同名文件,这样可以省去重写生成山峰模型的代码。为了使代码结构更清晰,打算把生成模型的功能从CubeRenderer类里抽出来,方便后面增加自定义模型,而CubeRenderer只负责进行渲染。由于CubeRenderer类不再生成Cube,就将它的名称改为Renderer。Crtl+Shift+H替换当前项目中所有的CubeRenderer为Renderer,并重命名对应的.cpp和.h文件。同时把CubeRenderer.h里两个结构体的定义剪切到Direct3DBase.h里,方便其他类使用。
接着右键点击项目->添加->类。
新建HillModel类,编译器会自动生成.h和.cpp文件。该类将负责定义山峰模型。在HillModel.h包含Direct3DBase.h,以使用顶点结构体。从Renderer类里抽出顶点相关成员加入HillModel类,同时更改构造方法。
Microsoft::WRL::ComPtr<ID3D11Buffer> m_vertexBuffer;Microsoft::WRL::ComPtr<ID3D11Buffer> m_indexBuffer;uint32 m_indexCount;
HillModel类还需要两个方法Initialize和Render,分别负责初始化顶点缓冲区和渲染设置。这两个方法的代码都从Renderer类里抽取。
void Initialize(ID3D11Device* d3dDevice);void Render(ID3D11DeviceContext* d3dContext);
Initialize方法从Renderer类的CreateDeviceResources方法中抽取createCubeTask包括的代码。Render方法从Renderer类的Render方法中抽取设置顶点缓冲区的代码。这两个方法的最终代码见附1。完成HillModel类的创建后,开始更新Renderer类。
让Renderer.h包含HillModel.h,并向Render类添加HillModel m_hill成员,专门负责山峰模型的顶点设置。
createCubeTask改为createHillTask在其中添加HillModel的Initialize方法,代码如下:
auto createHillTask = (createPSTask &&createVSTask).then([this] () { m_hill.Initialize(m_d3dDevice.Get()); });
然后在Render方法末尾添加
m_hill.Render(m_d3dContext.Get());
完成以上工作后,程序功能并没有变化,只是为后面添加其他模型提供方便。下面创建WaterModel类。它的成员和方法中都可以直接复制HillModel类的代码,只有Initialize方法与HillModel有差别,需要稍作改动。要实现蓝色水平面,需将模型定义为蓝色,并统一各个顶点在一个水平面上,即各顶点的y坐标相同。依此修改WaterModel类的Initialize方法,只需修改顶点生成部分,代码如下:
const XMFLOAT3 BLUE(0.0f, 0.0f, 1.0f); for(int row=0; row<zRange; ++row) { float zPos = row*dx; for(int col=0; col<xRange; ++col) { float xPos = col*dx; float yPos = 0.3f; Vertices[xRange*row +col].pos = XMFLOAT3(xPos, yPos, zPos); Vertices[xRange*row +col].color = BLUE; } }
水模型类就此完成,很简单。接着让Renderer.h包含WaterModel.h,向Renderer类添加成员WaterModel m_water。
在CreateDeviceResources方法中添加createWaterTask,当HillModel和WaterModel均初始化完成后设置载入完成。修改后的代码如下:
auto createHillTask = (createPSTask&& createVSTask).then([this] () { m_hill.Initialize(m_d3dDevice.Get()); }); auto createWaterTask = (createPSTask&& createVSTask).then([this] () { m_water.Initialize(m_d3dDevice.Get()); }); (createHillTask &&createWaterTask).then([this] () { m_loadingComplete = true; });
最后还需要在Render方法中添加WaterModel的Render方法,如下:
m_hill.Render(m_d3dContext.Get());m_water.Render(m_d3dContext.Get());
至此工作全部完成,运行后效果如图2:
另外,在DirectX中有两种渲染模式,实体模式和线框模式,为了以后观察方便,这里再为Renderer类增加私有成员Microsoft::WRL::ComPtr<ID3D11RasterizerState>m_rasterState和方法SetFillMode,用来设置渲染模式。
void Renderer::SetFillMode(D3D11_FILL_MODE mode){ D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.AntialiasedLineEnable= false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp =0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = mode; //实体模式D3D11_FILL_SOLID,线框模式D3D11_FILL_WIREFRAME rasterDesc.FrontCounterClockwise= false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias= 0.0f; DX::ThrowIfFailed( m_d3dDevice->CreateRasterizerState( &rasterDesc, &m_rasterState ) ); m_d3dContext->RSSetState(m_rasterState.Get());}
为了设置渲染模式,需要在每个模型的Render方法前调用SetFillMode方法,代码如下:
SetFillMode(D3D11_FILL_SOLID);m_hill.Render(m_d3dContext.Get()); SetFillMode(D3D11_FILL_WIREFRAME);m_water.Render(m_d3dContext.Get());
程序运行结果如图3:
附1:
void HillModel::Initialize(ID3D11Device* d3dDevice){ const int xRange = 128; const int zRange = 128; const float dx = 1.0f; const XMFLOAT3 WHITE(1.0f, 1.0f,1.0f); const XMFLOAT3 BEACH_SAND(1.0f,0.96f, 0.62f); const XMFLOAT3LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f); const XMFLOAT3DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f); const XMFLOAT3 DARKBROWN(0.45f,0.39f, 0.34f); VertexPositionColorVertices[xRange*zRange]; for(int row=0;row<zRange; ++row) { float zPos = row*dx; for(int col=0;col<xRange; ++col) { float xPos = col*dx; float yPos = 0.3f *(zPos*sinf(0.1f*xPos) + xPos*cosf(0.1*zPos)); Vertices[xRange*row+ col].pos = XMFLOAT3(xPos, yPos, zPos); if(yPos < -10.0f) Vertices[xRange*row+ col].color = BEACH_SAND; else if (yPos < 5.0f) Vertices[xRange*row+ col].color = LIGHT_YELLOW_GREEN; else if (yPos < 10.0f) Vertices[xRange*row+ col].color = DARK_YELLOW_GREEN; else if (yPos < 12.0f) Vertices[xRange*row+ col].color = DARKBROWN; else Vertices[xRange*row+ col].color = WHITE; } } D3D11_SUBRESOURCE_DATA vertexBufferData ={0}; vertexBufferData.pSysMem= Vertices; vertexBufferData.SysMemPitch= 0; vertexBufferData.SysMemSlicePitch= 0; CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(Vertices), D3D11_BIND_VERTEX_BUFFER); DX::ThrowIfFailed( d3dDevice->CreateBuffer( &vertexBufferDesc, &vertexBufferData, &m_vertexBuffer ) ); unsigned shortIndices[3*2*(xRange-1)*(zRange-1)]; int tempIndice = 0; for(int row=0;row<(zRange-1); ++row) { for(int col=0; col<(xRange-1);++col) { Indices[tempIndice]= xRange*row + col; Indices[tempIndice+1]= xRange*row + col + 1; Indices[tempIndice+2]= xRange*(row+1) + col; Indices[tempIndice+3]= xRange*(row+1) + col; Indices[tempIndice+4]= xRange*row + col + 1; Indices[tempIndice+5]= xRange*(row+1) + col + 1; tempIndice+= 6; } } m_indexCount = ARRAYSIZE(Indices); D3D11_SUBRESOURCE_DATA indexBufferData ={0}; indexBufferData.pSysMem= Indices; indexBufferData.SysMemPitch= 0; indexBufferData.SysMemSlicePitch= 0; CD3D11_BUFFER_DESC indexBufferDesc(sizeof(Indices), D3D11_BIND_INDEX_BUFFER); DX::ThrowIfFailed( d3dDevice->CreateBuffer( &indexBufferDesc, &indexBufferData, &m_indexBuffer ) );} void HillModel::Render(ID3D11DeviceContext* d3dContext){ UINT stride = sizeof(VertexPositionColor); UINT offset = 0; d3dContext->IASetVertexBuffers( 0, 1, m_vertexBuffer.GetAddressOf(), &stride, &offset ); d3dContext->IASetIndexBuffer( m_indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0 ); d3dContext->DrawIndexed( m_indexCount, 0, 0 );}
- Windows 8 Directx 开发学习笔记(六)添加水模型
- Windows 8 Directx 开发学习笔记(二)建立模型及初始化设备
- Windows 8 Directx 开发学习笔记(五)山峰河谷模型的简单实现
- Windows 8 Directx 开发学习笔记(八)要有光
- Windows 8 Directx开发学习笔记(一)应用基本框架
- Windows 8 Directx 开发学习笔记(三)摄像机设置及控制正方体旋转
- Windows 8 Directx 开发学习笔记(四)示例程序小结
- Windows 8 Directx 开发学习笔记(七)水波纹的实现
- Windows 8 Directx 开发学习笔记(九)材质定义及混合光照效果实现
- Windows 8 Directx 开发学习笔记(十)纹理贴图实现旋转的木箱
- Windows 8 Directx 开发学习笔记(十一)地形纹理贴图
- Windows 8 Directx 开发学习笔记(十二)利用混合实现浮在水面的木箱
- Windows 8 Directx 开发学习笔记(十三)利用模板实现木箱镜像
- Windows 8 Directx 开发学习笔记(十四)使用几何着色器实现三角形细分
- Windows 8 DirectX 开发学习笔记(十五)使用Billboard实现树木贴图
- Windows 8 DirectX 开发学习笔记(十六)使用Terragen生成自然环境贴图
- Linux 学习笔记(六)添加用户
- sunburnt 学习笔记(六)添加文档
- 测试not_in_vstart_and_v3(mate)_no_tec_rec错误
- 大数乘法。大数运算。“无限大数字”乘法。大数乘法两种方法对比
- 测试not_w_add(mate)_no_tec_rec1修改
- IT人士,要注重身体情况
- eclipse远程开发hadoop几个要点
- Windows 8 Directx 开发学习笔记(六)添加水模型
- LinQ 学习笔记
- sql 触发器和游标
- [iOS]Objective-C 实用特性索引(Objective-C Feature Availability Index)
- warning: control reaches end of non-void function
- Linux远程编译
- 数值排位函数 RANK
- VC++深入详解(11):文档与串行化
- Android ListView性能优化之视图缓存