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_WIREFRAMErasterDesc.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;elseVertices[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 开发学习笔记(六)添加水模型相关推荐

  1. Windows 8 DirectX 开发学习笔记(十六)使用Terragen生成自然环境贴图

    DirectX 游戏编程入门中提到一个Terragen软件可以生成环境贴图,所以登陆它的官方网站看了下.没想到Terragen生成的图片和照片一样,效果非常好,很多电影里有用到,所以下载免费版尝试一下 ...

  2. Windows 8 Directx 开发学习笔记(十一)地形纹理贴图

    前一篇实现木箱贴图时,木箱的六个面都正好用一整张纹理图,即六个面的纹理坐标均在[0,1]内.然而在为比较大的模型贴图时,像山峰河谷模型,如果只用一张纹理图,那么每个三角形只得到几个纹理元素,无法为提供 ...

  3. Windows 8 Directx开发学习笔记(一)应用基本框架

    Windows 8系统10月25日就要正式发布,其应用可与Windows Phone 8应用兼容,所以打算转到Windows 8系列的开发.之前虽然开发过应用,但对游戏开发更感兴趣,随意开始学习Met ...

  4. Windows 8 Directx 开发学习笔记(十二)利用混合实现浮在水面的木箱

    在场景中绘制多个不透明物体时很简单,哪个物体离得近,看到的就是哪个物体.但如果加入一个透明的物体,像玻璃,如何渲染就有些麻烦.拿一块红色的玻璃挡住眼睛,看到的物体都偏红,换成蓝色的玻璃,物体都偏蓝.D ...

  5. Windows 8 DirectX 开发学习笔记(十五)使用Billboard实现树木贴图

    要使用DirectX来获得三维效果,一般首先要生成一个三维模型,然后计算它在可视空间中的投影.这样得到的二维图像十分真实,但是计算量也很大.在大规模场景渲染中,随着模型精度的提高,这样的处理方式十分消 ...

  6. Windows 8 Directx 开发学习笔记(八)要有光

    上一篇已经完成水波纹模型,但是只是在线框模式下能清晰的看到波动效果,实体填充时无法看出水面变化,主要原因就是没有引入光照.这里通过更改顶点着色器和像素着色器,引入水面的漫反射效果,让整个模型更加真实. ...

  7. Windows 8 Directx 开发学习笔记(二)建立模型及初始化设备

    上一篇中介绍的DirectxApp类给整个应用搭建了一个框架,而这篇文章涉及的CubeRenderer类则是负责填充框架,呈现实际内容:一个旋转的彩色立方体.CubeRenderer类中的方法通过名称 ...

  8. Windows 8 Directx 开发学习笔记(十三)利用模板实现木箱镜像

    假设墙上有一面镜子,镜子前面有个木箱.如果观察角度合适,整个木箱镜像都会在镜子里,计算起来还比较简单:而变换个角度,木箱的镜像可能只有一部分在镜子里,这时单纯依靠计算来实现就很麻烦.DirectX提供 ...

  9. Windows 8 Directx 开发学习笔记(十)纹理贴图实现旋转的木箱

    纹理贴图映射(texturemapping)是可以显著提高场景细节和真实感的一种技术,基本原理是将图像数据映射到3D三角形表面(之前的文章提到过,三维模型其实是由很多个三角形拼接而成).当使用纹理资源 ...

最新文章

  1. mysql ibatis xml配置 like_iBatis学习方法及入门总结
  2. 2021暑假实习-SSM超市积分管理系统-day10笔记
  3. 在Unity中做一个淡入式的屏幕虚化
  4. 【NOI2012】迷失游乐园【概率期望】【换根dp】【基环树】
  5. 用于Spring应用程序的Gradle原型
  6. 分类算法之邻近算法:KNN(应用篇)
  7. 看阮一峰ES6 笔记
  8. JAVA 连接SAP Jco3
  9. linux服务器双网卡路由优先级冲突 Metric值
  10. 优启通制作系统u盘_优启通u盘装系统制作工具
  11. 【Active Learning - 12】一种基于生成对抗网络的二阶段主动学习方法
  12. Jetpack Compose - Modifier入门篇
  13. CSS的文本属性阴影效果
  14. BTIM提升移动运维管理效率
  15. iOS XCode无线连接iPhone手机 (Pair a wireless device)
  16. win10备份为wim_U盘装机WIN10系统教程
  17. 远程桌面进去服务器的办法,远程重启服务器后没法链接远程桌面解决办法
  18. 公有继承/私有继承/保护继承的区别
  19. 身高和java 车架,自行车车架与身高尺寸(图文)
  20. 西门子S7-300型PLC与西门子S7200smart型PLC的以太网通讯例程

热门文章

  1. Web UI自动化测试之元素定位
  2. pyspark 数据写入hive_Pyspark将数据写入hi
  3. 诊所系统php,诊所管理系统
  4. 三次iframe框架切换
  5. 超火爆的6 个必学持续集成工具,测试人的福音
  6. 接口测试常用工具及测试方法(超全)干货
  7. 学完这篇Charles抓包教程,我直接把fiddler卸载了
  8. 你知道这5年我怎么过的吗!谈谈我做测试开发的这些年……【总结】
  9. 接口测试 Seldom 2.0 - 让接口自动化测试更简单
  10. Qt与MySQL的连接与基本操作