Directx11教程(43) 纹理映射(13)动态纹理映射

     本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变水面的纹理坐标,实现水面纹理波动的效果。

      地形(山谷)以及水面都是基于网格的平面。

      对于地形,修改顶点类型为:

struct VertexType
    {
    D3DXVECTOR3 position;
    D3DXVECTOR3 normal;
    D3DXVECTOR2 texture; //纹理坐标
    D3DXVECTOR4 Kd; //材质的漫反射系数
    D3DXVECTOR4 Ks; //材质的高光系数
    };

    假设m,n为网格行数、列数,则纹理坐标计算如下:

float du = 10.0f / (n-1);
float dv = 10.0f / (m-1)

// 计算纹理坐标.
vertices[i*n+j].texture.x = j*du;
vertices[i*n+j].texture.y = i*dv;

其中du,dv中的10.0f,是我们把纹理坐标扩大10倍,大于[0,1]的纹理坐标会用wrap的方式使用纹理,这样在一个grid内,可以多次使用贴图,避免出现网格很大,而我们的纹理图片比较小,从而避免过度magnification的情形。

下面2个图是用10.0和2.0的比较结果,第一个图是2.0:

image

image

水面的纹理坐标计算方式和山谷基本相同,但是我们会在update函数中根据dt动态改变坐标,这样会实现水面漂移的效果。

    // 更新顶点缓冲.
    float du = 5.0f / (m_NumCols-1);
    float dv = 5.0f / (m_NumRows-1);

    //我们根据时间动态计算纹理坐标
    static float mWaterTexOffsetX = 0;
    static float mWaterTexOffsetY = 0;
   
    mWaterTexOffsetY += 0.1f*dt;
    mWaterTexOffsetX = 0.25f*sinf(4.0f*mWaterTexOffsetY);

    vertices[i*m_NumCols+j].texture.x = j*du + mWaterTexOffsetX;
    vertices[i*m_NumCols+j].texture.y = i*dv + mWaterTexOffsetY;


      当然,我们也通过矩阵的方式,来缩放、平移以及旋转纹理坐标,这样的话,就需要定义个shader常量矩阵,在shader中用它来乘以纹理坐标,实现我们想要的效果。纹理旋转经常用来实现动态粒子的效果,比如火焰等等。

     最后,我们在GraphicsClass中,调用光照纹理渲染类,就可以得到最终结果:

//用light shader texture渲染
result = m_LightTexShader->Render(m_D3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
    light, material, camera,m_TexManager->createTex(m_D3D->GetDevice(),string("grass.dds")));

result = m_LightTexShader->Render(m_D3D->GetDeviceContext(), m_WaterModel->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix,
    light, material, camera,m_TexManager->createTex(m_D3D->GetDevice(),string("water2.dds")));

完整的代码请参考:

工程文件myTutorialD3D11_38

代码下载:

https://files.cnblogs.com/mikewolf2002/d3d1127-28.zip

https://files.cnblogs.com/mikewolf2002/pictures.zip

原文地址:https://www.cnblogs.com/mikewolf2002/p/2493648.html