新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     >>计算机科学论坛<<     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 高级纹理映射技术(4) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 15771 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: 高级纹理映射技术(4) 举报  打印  推荐  IE收藏夹 
       本主题类别: Description Logics    
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 高级纹理映射技术(4)

    凹凸纹理映射

    关于凹凸映射的原理请参阅凹凸映射(Bump Map)实现原理

    凹凸纹理映射是一种纹理混合方法,它可以创建三维物体复杂的纹理外观表面。普通的纹理映射只能模拟比较平滑的三维物体表面,难以显示表面高低起伏、凹凸不平的效果。凹凸纹理映射能够通过一张表示物体表面凹凸程度的高度图(称为凹凸纹理),对另一张表示物体表面环境映射的纹理图的纹理坐标进行相应的干扰,经过干扰的纹理坐标将应用于环境映射,从而产生凹凸不平的显示效果。凹凸纹理映射通常由三张纹理映射图组成,第一张纹理图表示物体表面原始纹理颜色,第二张凹凸纹理图表示物体表面凹凸的高度起伏值,用来对下一张环境纹理图坐标进行干扰,第三张纹理图表示周围镜面反射或漫反射光照的环境光照映射图。凹凸纹理映射的纹理映射流程如下图所示:

    按此在新窗口浏览图片

    检查硬件设备

    在使用凹凸纹理映射之前,应查询当前的Direct3D设备是否支持D3DTEXOPCAPS_BUMPENVMAP或D3DTEXOPCAPS_BUMPENVMAPLUMINANCE多层纹理混合,以及当前设备是否支持3层纹理映射。

    BOOL SupportsBumpMapping(){    D3DCAPS9 d3dCaps;    d3dDevice->GetDeviceCaps( &d3dCaps );
        // Does this device support the two bump mapping blend operations?    if ( 0 == d3dCaps.TextureOpCaps & ( D3DTEXOPCAPS_BUMPENVMAP | D3DTEXOPCAPS_BUMPENVMAPLUMINANCE ))        return FALSE;
        // Does this device support up to three blending stages?    if( d3dCaps.MaxTextureBlendStages < 3 )        return FALSE;
        return TRUE;}
    如果当前硬件不支持上面的任何一项,程序框架会自动转而使用参考设备。

    凹凸纹理生成

    Direct3D的凹凸纹理被用来表示物体表面相邻像素的高度差,它的每个纹理元素由表示水平相邻像素高度差的Du、表示垂直相邻像素高度差的Dv以及表示该点亮度的L组成(某些凹凸纹理像素格式可以不包含L)。下表列出了Direct3D支持的凹凸纹理像素格式:

    凹凸纹理像素格式 说明
    D3DFMT_V8U8 每个像素由16位整数表示,分别由8位整数表示Du和Dv
    D3DFMT_L6V5U5 每个像素由16位整数表示,6位整数表示L,分别由5位整数表示Du和Dv
    D3DFMT_X8L8V8U8 每个像素由32位整数表示,包括8位保留位、8位L、8位Du、8位Dv
    D3DFMT_V16U16 每个像素由32位整数表示,分别由16位整数表示Du和Dv
    D3DFMT_Q8W8V8U8 每个像素由32位整数表示,分别由8位整数表示Q、W、V、U
    D3DFMT_CxV8U8 压缩像素格式,每个像素由16位整数表示,即8位Du和8位Dv,另外C = sqrt(1 - Du2 - Dv2  )

    通常情况下,可以载入一张表示物体表面图像高度的纹理图,通过计算高度图水平相邻和垂直相邻元素的高度差来生成凹凸纹理,也可以通过程序生成凹凸纹理,这里根据纹理图来生成凹凸纹理,代码如下:

    //--------------------------------------------------------------------------------------// Create bump texture from height map texture.//--------------------------------------------------------------------------------------HRESULT CreateBumpTexture(IDirect3DDevice9* device){ HRESULT hr;
     D3DSURFACE_DESC surface_desc; g_height_map_texture->GetLevelDesc(0, &surface_desc);
     V_RETURN(device->CreateTexture(surface_desc.Width, surface_desc.Height, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED,           &g_bump_map_texture, NULL));
     D3DLOCKED_RECT locked_rect; g_height_map_texture->LockRect(0, &locked_rect, NULL, 0);
     DWORD src_pitch   = (DWORD) locked_rect.Pitch; BYTE* src_row_top = (BYTE*) locked_rect.pBits; BYTE* src_row_cur = src_row_top; BYTE* src_row_bot = src_row_top + src_pitch * (surface_desc.Height - 1);
     g_bump_map_texture->LockRect(0, &locked_rect, NULL, 0);
     DWORD dest_pitch   = (DWORD) locked_rect.Pitch; BYTE* dest_row_top = (BYTE*) locked_rect.pBits; BYTE* dest_row_cur = dest_row_top;
     // iterate through all lines for(DWORD y = 0; y < surface_desc.Height; y++) {  BYTE* src_pixel_cur;  BYTE* src_pixel_up;  BYTE* src_pixel_below;    BYTE* dest_pixel;
      src_pixel_cur = src_row_cur;
      if(y == 0)   src_pixel_up = src_row_bot;  else   src_pixel_up = src_row_cur - src_pitch;
      if(y == surface_desc.Height - 1)   src_pixel_below = src_row_top;  else   src_pixel_below = src_row_cur + src_pitch;
      dest_pixel = dest_row_cur;
      // iterate through all columns in current line  for(DWORD x = 0; x < surface_desc.Width; x++)  {   BYTE src_pixel_left, src_pixel_right;
       if(x == 0)    src_pixel_left = *(src_row_cur + (surface_desc.Width - 4));   else    src_pixel_left = *(src_pixel_cur - 4);
       if(x == surface_desc.Width - 1)    src_pixel_right = *src_row_cur;   else    src_pixel_right = *(src_pixel_cur + 4);
       BYTE du = BYTE(src_pixel_left - src_pixel_right);   BYTE dv = BYTE(src_pixel_up   - src_pixel_below);
       // the luminance bump value   BYTE u_lumi = (*src_pixel_cur > 1) ? 63 : 127;
       *dest_pixel++ = du;   *dest_pixel++ = dv;   *dest_pixel++ = u_lumi;   *dest_pixel++ = 0;
       // move one pixel to the right   src_pixel_cur   += 4;   src_pixel_up     += 4;   src_pixel_below += 4;     }
      // move to the next line  src_row_cur  += src_pitch;  dest_row_cur += dest_pitch; }
     g_bump_map_texture->UnlockRect(0); g_height_map_texture->UnlockRect(0);
     return S_OK;}

    凹凸纹理设置

    凹凸纹理映射通常使用3层纹理:物体原始纹理、由原始纹理高度图生成的凹凸纹理、环境纹理,对应于多层纹理混合的0、1、2层。指定当前纹理层状态为D3DTOP_BUMPENVMAP或D3DTOP_BUMPENVMAPLUMINANCE可设置当前纹理层为凹凸纹理,例如:

    pd3dDevice->SetTexture(1, g_bump_map_texture);pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,     D3DTOP_BUMPENVMAP);

    pd3dDevice->SetTexture(1, g_bump_map_texture);pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,     D3DTOP_BUMPENVMAPLUMINANCE);
    纹理状态D3DTOP_BUMPENVMAP和D3DTOP_BUMPENVMAPLUMINANCE表示两种不同的凹凸纹理映射方法。纹理状态D3DTOP_BUMPENVMAPLUMINANCE表示在凹凸纹理中包含凹凸纹理亮度值L,L将与下一纹理层的纹理颜色相乘作为最后输出的纹理颜色。纹理状态D3DTOP_BUMPENVMAP默认亮度值L为1,即不改变下一纹理层的纹理颜色。

    这里分别使用了3层纹理贴图,如下所示:

    按此在新窗口浏览图片
    原始纹理

    按此在新窗口浏览图片
    原始纹理高度图

    按此在新窗口浏览图片
    环境纹理贴图

    Direct3D可设置凹凸纹理矩阵,对凹凸纹理中的每个纹理元素值(Dv、Du,即对于下一纹理层中的每个纹理坐标的扰动值)进行坐标变换:

    Du' = Du * M00 + Dv * M10

    Dv' = Dv * M01 + Dv * M11

    凹凸纹理的每个纹理元素Dv、Du与一个2 x 2的凹凸矩阵相乘,其结果Dv、Du对下一纹理层中的每个纹理元素的纹理坐标产生该数值代表的坐标扰动。2 x 2的凹凸矩阵值可由函数IDirect3DDevice9::SetTextureStageState()设置,将它的第一个参数设置为纹理层序号,第二个参数设置为D3DTSS_BUMPENVMAT00或D3DTSS_BUMPENVMAT01或D3DTSS_BUMPENVMAT10或D3DTSS_BUMPENVMAT11,分别表示凹凸矩阵的4个矩阵元素,第三个参数设置为该矩阵元素的值。纹理坐标扰动Dv、Du或Dv'、Du'的范围介于-1 ~ +1之间。

    如果使用D3DTOP_BUMPENVMAPLUMINANCE计算凹凸纹理,Direct3D将使用下列方程计算凹凸纹理的亮度值L'(L'为0~255的整数,它将被用来与下一纹理层的颜色相乘,作为最后输出的纹理颜色值)。

    L' = L * S + O

    其中,L为凹凸纹理元素中的亮度L值,比例系数S和偏移系数O可改变最终的亮度值。S和O可由函数IDirect3DDevice9::SetTexureStageState()设置,将它的第一个参数设置为纹理层序号,第二个参数设置为D3DTSS_BUMPENVLSCALE或D3DTSS_BUMPENVLOFFSET,分别表示凹凸纹理映射的比例系数S和偏移系数O,将第三个参数设置为相应的系数值。

    设置凹凸纹理状态的代码如下所示:

    // set texture color blend method for stage 0 (base texture)

    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);

    pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

    // set texture color blend method for stage 1 (bump map texture)

    pd3dDevice->SetTexture(1, g_bump_map_texture);

    pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);

    pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
    pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);

    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVMAT00, F2DW(0.8f));
    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVMAT01, F2DW(0.0f));
    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVMAT10, F2DW(0.0f));
    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVMAT11, F2DW(0.8f));

    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVLSCALE, F2DW(4.0f));
    pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVLOFFSET, F2DW(0.0f));

    pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

    // set texture color blend method for stage 2 (environment map texture)

    D3DXMATRIX mat;

    mat._11 = 0.5f; mat._12 = 0.0f; mat._13 = 0.0f; mat._14 = 0.0f;
    mat._21 = 0.0f; mat._22 = -0.5f; mat._23 = 0.0f; mat._24 = 0.0f;
    mat._31 = 0.0f; mat._32 = 0.0f; mat._33 = 1.0f; mat._34 = 0.0f;
    mat._41 = 0.5f; mat._42 = 0.5f; mat._43 = 0.0f; mat._44 = 1.0f;

    pd3dDevice->SetTransform(D3DTS_TEXTURE2, &mat);

    pd3dDevice->SetTexture(2, g_env_map_texture);

    pd3dDevice->SetTextureStageState(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
    pd3dDevice->SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_SPHEREMAP);
    pd3dDevice->SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    pd3dDevice->SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_CURRENT);
    pd3dDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_ADD);

    pd3dDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
    pd3dDevice->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

    按此在新窗口浏览图片
    原始纹理图

    按此在新窗口浏览图片
    经过凹凸纹理映射后


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2008/12/10 8:24:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/12 8:40:14

    本主题贴数6,分页: [1]

     *树形目录 (最近20个回帖) 顶端 
    主题:  高级纹理映射技术(4)(9726字) - 卷积内核,2008年12月10日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(14191字) - 卷积内核,2008年12月10日
        回复:  要渲染看起来真实的场景,最好是使用高分辨率而且颜色丰富的纹理,但这样的纹理可能会耗费大量的内存,例..(5181字) - 卷积内核,2008年12月10日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(16166字) - 卷积内核,2008年12月10日
        回复:  [B]立体纹理[/B]立体纹理(volume texture)是一组应用到二维图元(如一个三角..(15590字) - 卷积内核,2008年12月10日
        回复:  主程序:#include "dxstdafx.h"#include "resource.h..(21235字) - 卷积内核,2008年12月10日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    93.750ms