D3D11地形渲染教程八之ColorMap(颜色贴图)

来源:互联网 发布:mac air 电池容量 编辑:程序博客网 时间:2024/05/10 03:30

这节教程的程序结构如下:



一,ColorMap

在前面的教程我们实现了地形的渲染,包括光照,纹理,这一节教程我们实现ColorMap(颜色贴图),也就是在地形已经有一层纹理的前提下,再用一张纹理的颜色调节整个地形的细节,实际上ColorMap的原理类似于LightMapD3D11教程十之LighhtMap(光照贴图).这次我们加载ColorMap的颜色于相应位置的顶点里,就是加载高度图那样。也许你会问,为什么不直接使用加载纹理为ID3D11ShaderResourceView,因为我们前面教程D3D11地形渲染教程五之TerrainTexture使用的纹理是以平铺(Tile)的方式来渲染地形的,也就是整个地形的纹理多次重复绘制,以铺满整个地形,若我们将ColorMap加载成ID3D11ShaderResourceView,则ColorMap调节的是平铺的每张纹理的细节,而不是整个地形的细节。

顶点格式:

struct Vertex{XMFLOAT3 pos;XMFLOAT2 Tex;XMFLOAT3 normal;XMFLOAT4 color;};


加载ColorMap的代码:
//从ColorMap的左下角开始加载bool TerrainClass::LoadColorMap(std::wstring ColorMapFileName){//GDIplus库Gdiplus::Bitmap* texture;//(ColorMap)颜色纹理高度和宽度float mColorMapHeight, mColorMapWidth;//下标int index = 0;Gdiplus::GdiplusStartupInput gdiplusstartupinput;Gdiplus::Color color;ULONG_PTR gdiplustoken;Gdiplus::GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);//读取颜色贴图texture = new Gdiplus::Bitmap(ColorMapFileName.c_str());//获取纹理分辨率的宽度和高度mColorMapHeight = texture->GetHeight();mColorMapWidth = texture->GetWidth();for (int i = mColorMapHeight-1; i >=0; --i){for (int j = 0; j <mColorMapWidth; ++j){//获取相应j行i列像素,注意这里下标从0开始texture->GetPixel(j, i, &color);    mHeightMap[index]->b = (float)color.GetB()/255.0f;    mHeightMap[index]->g = (float)color.GetG()/255.0f;  //这里颜色的值缩小为0.0f-1.0f之间    mHeightMap[index]->r = (float)color.GetR()/255.0f;++index;}}delete texture;Gdiplus::GdiplusShutdown(gdiplustoken);return true;}


ColorMap:



渲染地形的Shader代码:
Texture2D TerrainTexture:register(t0);  //纹理资源SamplerState SampleType:register(s0);   //采样方式//VertexShadercbuffer CBMatrix:register(b0){matrix World;matrix View;matrix Proj;matrix WorldInvTranspose;};cbuffer CBLight:register(b1){float4 AmbientColor;float4 DiffuseColor;float3 LightDir;float pad;};struct VertexIn{float3 Pos:POSITION;float2 Tex:TEXCOORD0;float3 normal:NORMAL;float4 color:COLOR;};struct VertexOut{float4 Pos:SV_POSITION;float2 Tex:TEXCOORD0;float3 normal_W:NORMAL;float4 color:COLOR;};VertexOut VS(VertexIn ina){VertexOut outa;outa.Pos = mul(float4(ina.Pos, 1.0f), World);outa.Pos = mul(outa.Pos, View);outa.Pos = mul(outa.Pos, Proj);outa.normal_W = mul(float4(ina.normal, 0.0f), WorldInvTranspose).xyz;//规格化顶点法向量outa.normal_W = normalize(outa.normal_W);//顶点的纹理坐标outa.Tex = ina.Tex;//顶点的颜色outa.color = ina.color;return outa;}float4 PS(VertexOut outa) : SV_Target{float4 color;    float4 TexColor;    float3 InvLightDir;float DiffuseFactor;     color = AmbientColor;//对纹理进行采样TexColor = TerrainTexture.Sample(SampleType, outa.Tex);//求出光的反方向,并进行规格化InvLightDir = -normalize(LightDir);//求出漫反射因子DiffuseFactor = saturate(dot(InvLightDir, outa.normal_W));//增加漫反射光颜色color += DiffuseFactor*DiffuseColor;color = saturate(color);color = color*TexColor*outa.color*2.0f;return color;}




二,代码的纠错

地形加载(HeightMap)和ColorMap应该是从左下角开始的,加载高度图的代码改正:

//24位高度图的像素为24位,R=G=B都为8位bool TerrainClass::LoadHeightMap(std::wstring HeightMapFileName){//GDIplus库Gdiplus::Bitmap* texture;Gdiplus::GdiplusStartupInput gdiplusstartupinput;Gdiplus::Color color;ULONG_PTR gdiplustoken;Gdiplus::GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);//读取纹理texture = new Gdiplus::Bitmap(HeightMapFileName.c_str());//获取纹理分辨率的宽度和高度mTerrainHeight = texture->GetHeight();    mTerrainWidth = texture->GetWidth();for (int i = mTerrainHeight-1; i >=0; --i){for (int j = 0; j <mTerrainWidth; ++j){//获取相应数组[i][j]的像素,注意这里下标从0开始texture->GetPixel(j, i, &color);HeightMap* mHeightMapPixel = new HeightMap();mHeightMapPixel->x = (float)j;mHeightMapPixel->y = (float)color.GetR();  //0-255mHeightMapPixel->z = (float)(mTerrainHeight-1-i);mHeightMap.push_back(mHeightMapPixel);}}delete texture;Gdiplus::GdiplusShutdown(gdiplustoken);return true;}



原来的地形显示是这样的:





用了ColorMap之后:




源代码链接如下:
http://download.csdn.net/detail/qq_29523119/9737808
0 0
原创粉丝点击