Windows 8 Directx 开发学习笔记(六)添加水模型
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 开发学习笔记(六)添加水模型相关推荐
- Windows 8 DirectX 开发学习笔记(十六)使用Terragen生成自然环境贴图
DirectX 游戏编程入门中提到一个Terragen软件可以生成环境贴图,所以登陆它的官方网站看了下.没想到Terragen生成的图片和照片一样,效果非常好,很多电影里有用到,所以下载免费版尝试一下 ...
- Windows 8 Directx 开发学习笔记(十一)地形纹理贴图
前一篇实现木箱贴图时,木箱的六个面都正好用一整张纹理图,即六个面的纹理坐标均在[0,1]内.然而在为比较大的模型贴图时,像山峰河谷模型,如果只用一张纹理图,那么每个三角形只得到几个纹理元素,无法为提供 ...
- Windows 8 Directx开发学习笔记(一)应用基本框架
Windows 8系统10月25日就要正式发布,其应用可与Windows Phone 8应用兼容,所以打算转到Windows 8系列的开发.之前虽然开发过应用,但对游戏开发更感兴趣,随意开始学习Met ...
- Windows 8 Directx 开发学习笔记(十二)利用混合实现浮在水面的木箱
在场景中绘制多个不透明物体时很简单,哪个物体离得近,看到的就是哪个物体.但如果加入一个透明的物体,像玻璃,如何渲染就有些麻烦.拿一块红色的玻璃挡住眼睛,看到的物体都偏红,换成蓝色的玻璃,物体都偏蓝.D ...
- Windows 8 DirectX 开发学习笔记(十五)使用Billboard实现树木贴图
要使用DirectX来获得三维效果,一般首先要生成一个三维模型,然后计算它在可视空间中的投影.这样得到的二维图像十分真实,但是计算量也很大.在大规模场景渲染中,随着模型精度的提高,这样的处理方式十分消 ...
- Windows 8 Directx 开发学习笔记(八)要有光
上一篇已经完成水波纹模型,但是只是在线框模式下能清晰的看到波动效果,实体填充时无法看出水面变化,主要原因就是没有引入光照.这里通过更改顶点着色器和像素着色器,引入水面的漫反射效果,让整个模型更加真实. ...
- Windows 8 Directx 开发学习笔记(二)建立模型及初始化设备
上一篇中介绍的DirectxApp类给整个应用搭建了一个框架,而这篇文章涉及的CubeRenderer类则是负责填充框架,呈现实际内容:一个旋转的彩色立方体.CubeRenderer类中的方法通过名称 ...
- Windows 8 Directx 开发学习笔记(十三)利用模板实现木箱镜像
假设墙上有一面镜子,镜子前面有个木箱.如果观察角度合适,整个木箱镜像都会在镜子里,计算起来还比较简单:而变换个角度,木箱的镜像可能只有一部分在镜子里,这时单纯依靠计算来实现就很麻烦.DirectX提供 ...
- Windows 8 Directx 开发学习笔记(十)纹理贴图实现旋转的木箱
纹理贴图映射(texturemapping)是可以显著提高场景细节和真实感的一种技术,基本原理是将图像数据映射到3D三角形表面(之前的文章提到过,三维模型其实是由很多个三角形拼接而成).当使用纹理资源 ...
最新文章
- mysql ibatis xml配置 like_iBatis学习方法及入门总结
- 2021暑假实习-SSM超市积分管理系统-day10笔记
- 在Unity中做一个淡入式的屏幕虚化
- 【NOI2012】迷失游乐园【概率期望】【换根dp】【基环树】
- 用于Spring应用程序的Gradle原型
- 分类算法之邻近算法:KNN(应用篇)
- 看阮一峰ES6 笔记
- JAVA 连接SAP Jco3
- linux服务器双网卡路由优先级冲突 Metric值
- 优启通制作系统u盘_优启通u盘装系统制作工具
- 【Active Learning - 12】一种基于生成对抗网络的二阶段主动学习方法
- Jetpack Compose - Modifier入门篇
- CSS的文本属性阴影效果
- BTIM提升移动运维管理效率
- iOS XCode无线连接iPhone手机 (Pair a wireless device)
- win10备份为wim_U盘装机WIN10系统教程
- 远程桌面进去服务器的办法,远程重启服务器后没法链接远程桌面解决办法
- 公有继承/私有继承/保护继承的区别
- 身高和java 车架,自行车车架与身高尺寸(图文)
- 西门子S7-300型PLC与西门子S7200smart型PLC的以太网通讯例程