以文本方式查看主题 - 计算机科学论坛 (http://bbs.xml.org.cn/index.asp) -- 『 C/C++编程思想 』 (http://bbs.xml.org.cn/list.asp?boardid=61) ---- 高级纹理映射技术(4) (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=70312) |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:24:00 AM -- 高级纹理映射技术(4) 凹凸纹理映射 关于凹凸映射的原理请参阅凹凸映射(Bump Map)实现原理。 凹凸纹理映射是一种纹理混合方法,它可以创建三维物体复杂的纹理外观表面。普通的纹理映射只能模拟比较平滑的三维物体表面,难以显示表面高低起伏、凹凸不平的效果。凹凸纹理映射能够通过一张表示物体表面凹凸程度的高度图(称为凹凸纹理),对另一张表示物体表面环境映射的纹理图的纹理坐标进行相应的干扰,经过干扰的纹理坐标将应用于环境映射,从而产生凹凸不平的显示效果。凹凸纹理映射通常由三张纹理映射图组成,第一张纹理图表示物体表面原始纹理颜色,第二张凹凸纹理图表示物体表面凹凸的高度起伏值,用来对下一张环境纹理图坐标进行干扰,第三张纹理图表示周围镜面反射或漫反射光照的环境光照映射图。凹凸纹理映射的纹理映射流程如下图所示:
检查硬件设备 在使用凹凸纹理映射之前,应查询当前的Direct3D设备是否支持D3DTEXOPCAPS_BUMPENVMAP或D3DTEXOPCAPS_BUMPENVMAPLUMINANCE多层纹理混合,以及当前设备是否支持3层纹理映射。 BOOL SupportsBumpMapping(){ D3DCAPS9 d3dCaps; d3dDevice->GetDeviceCaps( &d3dCaps );
凹凸纹理生成 Direct3D的凹凸纹理被用来表示物体表面相邻像素的高度差,它的每个纹理元素由表示水平相邻像素高度差的Du、表示垂直相邻像素高度差的Dv以及表示该点亮度的L组成(某些凹凸纹理像素格式可以不包含L)。下表列出了Direct3D支持的凹凸纹理像素格式: 凹凸纹理像素格式 说明 通常情况下,可以载入一张表示物体表面图像高度的纹理图,通过计算高度图水平相邻和垂直相邻元素的高度差来生成凹凸纹理,也可以通过程序生成凹凸纹理,这里根据纹理图来生成凹凸纹理,代码如下: //--------------------------------------------------------------------------------------// Create bump texture from height map texture.//--------------------------------------------------------------------------------------HRESULT CreateBumpTexture(IDirect3DDevice9* device){ HRESULT hr; 凹凸纹理设置 凹凸纹理映射通常使用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); 这里分别使用了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->SetSamplerState(0, D3DSAMP_MAGFILTER, 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_BUMPENVMAT00, F2DW(0.8f)); pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVLSCALE, F2DW(4.0f)); pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, 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; pd3dDevice->SetTransform(D3DTS_TEXTURE2, &mat); pd3dDevice->SetTexture(2, g_env_map_texture); pd3dDevice->SetTextureStageState(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); pd3dDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:25:00 AM -- 主程序: #pragma warning(disable : 4127 4995 4996) #define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0) #define IDC_TOGGLE_FULLSCREEN 1 const D3DXCOLOR FONT_COLOR(1.0f, 0.5f, 0.25f, 1.0f); ID3DXFont* g_font; CDXUTDialogResourceManager g_dlg_resource_manager; ID3DXMesh* g_mesh; IDirect3DTexture9* g_env_map_texture; inline DWORD F2DW(float f) { return *((DWORD*) &f); } //-------------------------------------------------------------------------------------- IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, // check whether device support bump textue mapping // check whether device support 3 level texture stage blend return true; static bool is_first_time = true; if(is_first_time) // if using reference device, then pop a warning message box. return true; //-------------------------------------------------------------------------------------- D3DSURFACE_DESC surface_desc; V_RETURN(device->CreateTexture(surface_desc.Width, surface_desc.Height, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, DWORD src_pitch = (DWORD) locked_rect.Pitch; g_bump_map_texture->LockRect(0, &locked_rect, NULL, 0); DWORD dest_pitch = (DWORD) locked_rect.Pitch; // iterate through all lines src_pixel_cur = src_row_cur; if(y == 0) if(y == surface_desc.Height - 1) dest_pixel = dest_row_cur; // iterate through all columns in current line if(x == 0) if(x == surface_desc.Width - 1) BYTE du = BYTE(src_pixel_left - src_pixel_right); // the luminance bump value *dest_pixel++ = du; // move one pixel to the right // move to the next line g_bump_map_texture->UnlockRect(0); return S_OK; //-------------------------------------------------------------------------------------- LPWSTR w_last_back_slash = wcsrchr(wbuf, '\\'); if(w_last_back_slash) //-------------------------------------------------------------------------------------- V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice)); D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, V_RETURN(D3DXCreateTextureFromFile(pd3dDevice, L"HeightMap.bmp", &g_height_map_texture)); V_RETURN(D3DXLoadMeshFromXW(L"SphereEarth.x", D3DXMESH_MANAGED, pd3dDevice, NULL, &material_buffer, NULL, D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer(); for(DWORD i = 0; i < g_num_materials; i++) // .x file do not save ambient data, so set it here. WCHAR wfilename[MAX_PATH]; g_mesh_textures[i] = NULL; if(xmaterials[i].pTextureFilename != NULL && lstrlen(wfilename) > 0) material_buffer->Release(); return S_OK; V_RETURN(g_dlg_resource_manager.OnResetDevice()); // set dialog position and size g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0); // setup view matrix D3DXMATRIX mat_view; D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up); // set projection matrix // set texture color blend method for stage 0 (base texture) // 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_BUMPENVMAT00, F2DW(0.8f)); pd3dDevice->SetTextureStageState(1, D3DTSS_BUMPENVLSCALE, F2DW(4.0f)); pd3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, 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; pd3dDevice->SetTransform(D3DTS_TEXTURE2, &mat); pd3dDevice->SetTexture(2, g_env_map_texture); pd3dDevice->SetTextureStageState(2, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); pd3dDevice->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); return S_OK; //-------------------------------------------------------------------------------------- release_com(g_text_sprite); delete[] g_mesh_materials; if(g_mesh_textures) delete[] g_mesh_textures; release_com(g_font); //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // show frame and device states // show helper information if(g_show_help) text_helper.End(); //-------------------------------------------------------------------------------------- if(g_settings_dlg.IsActive()) // Clear the render target and the zbuffer // Render the scene RenderText(); V(g_button_dlg.OnRender(fElapsedTime)); V( pd3dDevice->EndScene() ); if(g_settings_dlg.IsActive()) *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam); return 0; //-------------------------------------------------------------------------------------- case IDC_TOGGLE_REF: case IDC_CHANGE_DEVICE: //-------------------------------------------------------------------------------------- g_button_dlg.SetCallback(OnGUIEvent); int x = 35, y = 10, width = 125, height = 22; g_button_dlg.AddButton(IDC_TOGGLE_FULLSCREEN, L"Toggle full screen", x, y, width, height); //-------------------------------------------------------------------------------------- // Set the callback functions // Initialize DXUT and create the desired Win32 window and Direct3D device for the application // Start the render loop // TODO: Perform any application-level cleanup here return DXUTGetExitCode();
[B][URL=http://www.cppblog.com/Files/changingnow/BumpTextureMapping.rar]下载示例工程[/URL][/B] |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:26:00 AM -- 立体纹理 立体纹理(volume texture)是一组应用到二维图元(如一个三角形或一条直线)的三维纹理元素的集合,可以使用立体纹理实现一些特殊效果,如迷雾、爆炸等。当对一个图元使用立体纹理时,它的每个顶点都需要一组三元纹理坐标。当绘制该图元时,它中间的每个像素都将用立体纹理中的一些纹理元素的颜色值进行填充,这与二维纹理映射的情况相似。 立体纹理以薄片为单元组织起来,可以把它想象成将(宽 x 高)的二维表面转换成(宽 x 高 x 深)的三维立体,每个薄片是单独的一行,立体纹理可以有一系列级别,每一级都较上一级缩小一倍,如下图所示: 要创建立体纹理,首先必须检查显卡是否支持立体纹理: // check whether device support volume textureif((pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) == 0) return false; struct sCustomVertex{ float x, y, z; float u, v, w;}; #define D3DFVF_TEXCOORDSIZEN(CoordIndex) #define D3DFVF_TEXCOORDSIZE1(CoordIndex) (D3DFVF_TEXTUREFORMAT1 << (CoordIndex*2 + 16)) #define D3DFVF_TEXCOORDSIZE2(CoordIndex) (D3DFVF_TEXTUREFORMAT2) #define D3DFVF_TEXCOORDSIZE3(CoordIndex) (D3DFVF_TEXTUREFORMAT3 << (CoordIndex*2 + 16)) #define D3DFVF_TEXCOORDSIZE4(CoordIndex) (D3DFVF_TEXTUREFORMAT4 << (CoordIndex*2 + 16)) #define D3DFVF_TEXTUREFORMAT1 3 // one floating point value#define D3DFVF_TEXTUREFORMAT2 0 // two floating point values#define D3DFVF_TEXTUREFORMAT3 1 // three floating point values#define D3DFVF_TEXTUREFORMAT4 2 // four floating point values DWORD dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE1(0) | // Uses 1D texture coordinates for texture coordinate set 1 (index 0). D3DFVF_TEXCOORDSIZE2(1); // And 2D texture coordinates for texture coordinate set 2 (index 1). 接着,为每个顶点指定数据,创建顶点缓冲区并填充它: // create vertex buffer and fill data Creates a volume texture resource. HRESULT CreateVolumeTexture( UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle); 示例代码如下: HRESULT hr; V_RETURN(device->CreateVolumeTexture(width, height, depth, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, 接着调用IDirect3DVolumeTexture9::LockBox()来锁定立体纹理顶点缓冲区,该函数的声明如下: Locks a box on a volume texture resource. HRESULT LockBox( UINT Level, D3DLOCKED_BOX * pLockedVolume, CONST D3DBOX * pBox, DWORD Flags); Remarks D3DLOCKED_BOX typedef struct D3DLOCKED_BOX { int RowPitch; int SlicePitch; void * pBits;} D3DLOCKED_BOX, *LPD3DLOCKED_BOX; D3DBOX typedef struct D3DBOX { UINT Left; UINT Top; UINT Right; UINT Bottom; UINT Front; UINT Back;} D3DBOX, *LPD3DBOX; The restrictions on side ordering observed for D3DBOX are left to right, top to bottom, and front to back. 示例代码如下: D3DLOCKED_BOX locked_box;g_volume_texture->LockBox(0, &locked_box, NULL, 0); Unlocks a box on a volume texture resource. HRESULT UnlockBox( UINT Level); 为了生成立体纹理,还必须改变纹理的w坐标: //--------------------------------------------------------------------------------------// Handle updates to the scene//--------------------------------------------------------------------------------------void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ){ // change w coordinate of volume texture // set textue and stream source and vertex formatpd3dDevice->SetTexture(0, g_volume_texture);pd3dDevice->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));pd3dDevice->SetFVF(D3DFVF_CUSTOM_VERTEX); 立体纹理和普通二维纹理的主要区别是:顶点纹理坐标是三维的,纹理对象指针的类型不同,立体纹理的创建也不同,而立体纹理在使用上和普通二维纹理基本相同。 在示例程序中,立体纹理是由程序生成的,比较复杂。Direct3D提供了辅助函数D3DXCreateVolumeTextureFromFile()来从图片文件中生成立体纹理,该函数的声明如下: Creates a volume texture from a file. HRESULT D3DXCreateVolumeTextureFromFile( LPDIRECT3DDEVICE9 pDevice, LPCTSTR pSrcFile, LPDIRECT3DVOLUMETEXTURE9 * ppVolumeTexture); D3DERR_NOTAVAILABLE The function is equivalent to D3DXCreateVolumeTextureFromFileEx(pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, ppVolumeTexture). This function supports the following file formats: .bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, and .tga. See D3DXIMAGE_FILEFORMAT. Mipmapped textures automatically have each level filled with the loaded texture. When loading images into mipmapped textures, some devices are unable to go to a 1x1 image and this function will fail. If this happens, then the images need to be loaded manually. Note that a resource created with this function will be placed in the memory class denoted by D3DPOOL_MANAGED. Filtering is automatically applied to a texture created using this method. The filtering is equivalent to D3DX_FILTER_TRIANGLE | D3DX_FILTER_DITHER in D3DX_FILTER. 通过文件创建立体纹理时文件格式必须是立体纹理格式,对于普通格式的图片文件,可以通过DirectX提供的纹理工具"DirectX Texture Tool"转换成立体纹理格式的文件。 |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:26:00 AM -- 主程序: #pragma warning(disable : 4127 4995 4996) #define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0) #define IDC_TOGGLE_FULLSCREEN 1 struct sCustomVertex #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)) const D3DXCOLOR FONT_COLOR(1.0f, 0.5f, 0.25f, 1.0f); ID3DXFont* g_font; CDXUTDialogResourceManager g_dlg_resource_manager; IDirect3DVertexBuffer9* g_vertex_buffer; //-------------------------------------------------------------------------------------- IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, // check whether device support volume texture return true; static bool is_first_time = true; if(is_first_time) // if using reference device, then pop a warning message box. return true; //-------------------------------------------------------------------------------------- V_RETURN(device->CreateVolumeTexture(width, height, depth, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DLOCKED_BOX locked_box; for(UINT w = 0; w < depth; w++) for(UINT v = 0; v < height; v++) float du = (u - 7.5f) / 7.5f; if(scale > 1.0f) DWORD r = (DWORD)((w << 4) * scale); ((DWORD*) locked_box.pBits)[u] = 0xFF000000 + (r << 16) + (g << 8) + b; locked_box.pBits = (BYTE*) locked_box.pBits + locked_box.RowPitch; locked_box.pBits = slice_start + locked_box.SlicePitch; g_volume_texture->UnlockBox(0); return S_OK; //-------------------------------------------------------------------------------------- V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice)); D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, sCustomVertex vertices[] = pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_MANAGED, &g_vertex_buffer, NULL); void* ptr; return CreateVolumeTexture(pd3dDevice); V_RETURN(g_dlg_resource_manager.OnResetDevice()); // set dialog position and size g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0); // setup world matrix // setup view matrix D3DXMATRIX mat_view; D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up); // set projection matrix // set textue and stream source and vertex format // set texture color blend method return S_OK; //-------------------------------------------------------------------------------------- release_com(g_text_sprite); release_com(g_font); //-------------------------------------------------------------------------------------- sCustomVertex* ptr; for(int i = 0; i < 4; i++) g_vertex_buffer->Unlock(); //-------------------------------------------------------------------------------------- // show frame and device states // show helper information if(g_show_help) text_helper.End(); //-------------------------------------------------------------------------------------- if(g_settings_dlg.IsActive()) // Clear the render target and the zbuffer // Render the scene V(g_button_dlg.OnRender(fElapsedTime)); if(g_settings_dlg.IsActive()) *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam); return 0; //-------------------------------------------------------------------------------------- case IDC_TOGGLE_REF: case IDC_CHANGE_DEVICE: //-------------------------------------------------------------------------------------- g_button_dlg.SetCallback(OnGUIEvent); int x = 35, y = 10, width = 125, height = 22; g_button_dlg.AddButton(IDC_TOGGLE_FULLSCREEN, L"Toggle full screen", x, y, width, height); //-------------------------------------------------------------------------------------- // Set the callback functions // Initialize DXUT and create the desired Win32 window and Direct3D device for the application // Start the render loop // TODO: Perform any application-level cleanup here return DXUTGetExitCode();
[B][URL=http://www.cppblog.com/Files/changingnow/VolumeTexture.rar]下载示例工程[/URL][/B] |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:27:00 AM -- 要渲染看起来真实的场景,最好是使用高分辨率而且颜色丰富的纹理,但这样的纹理可能会耗费大量的内存,例如,一张每像素16位颜色的256 x 256纹理将使用128KB的内存。如果在该纹理中使用多级渐进纹理,还需要额外的43KB内存。一个使用50张这种纹理的场景将需要8MB的内存,如果需要更强的真实性,可以使用每像素32位颜色的512 x 512纹理,但那就需要8倍的内存。 为了减少纹理消耗的系统带宽和内存空间,Direct3D支持纹理压缩和实时解压,即DXT纹理压缩。压缩后的纹理被存储在Direct3D纹理指针中,当Direct3D渲染物体时,Direct3D引擎自动对纹理进行解压。应用DXT压缩纹理不仅可以节省内存空间,而且能有效地降低纹理传输带宽,提高图形系统的整体性能。 随着DirectX对纹理压缩格式的推广,目前大部分显卡都支持DXT压缩纹理,而且DXT压缩纹理在图形质量和运行速度之间取得了很好的平衡。
DXT纹理压缩格式 DXT是一种DirectDraw表面,它以压缩形式存储图形数据,该表面可以节省大量的系统带宽和内存。即使不直接使用DXT表面渲染,也可以通过DXT格式创建纹理的方法节省磁盘空间。Direct3D提供了D3DFMT_DXT1 ~ D3DFMT_DXT5共5种压缩纹理格式。其中,D3DFMT_DXT1支持15位RGB和1位alpha图形格式,D3DFMT_DXT2、D3DFMT_DXT3支持12位RGB和4位alpha,D3DFMT_DXT4、D3DFMT_DXT5则采取了线性插值方式生成alpha。 DXT1格式的压缩比例是4 : 1(4x4块16位RGB纹理元素可压缩为64位,2个16位RGB565值和16个2位索引),这样的压缩比并不很高,但足以有效地将3D加速卡用于存储纹理的容量提高4倍,如下图所示: Direct3D支持5中DXT格式压缩: FOURCC Description Alpha premultiplied?
使用DXT压缩纹理 使用DXT压缩纹理前,必须先调用IDirect3D9::CheckDeviceFormat(),将表面格式设置为D3DFMT_DXT1 ~ D3DFMT_DXT5中的任意值,查询当前设备是否支持DXT压缩纹理: // check whether device support DXT compressed textureif(FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1))) return false; 在使用函数IDirect3DDevice9::CreateTexture()创建纹理时,将参数Format设置为压缩纹理格式D3DFMT_DXT1 ~ D3DFMT_DXT5中的任意值,可以创建指定压缩格式的纹理,也可以通过函数D3DXCreateTextureFromFileEx()从磁盘文件中生成DXT压缩纹理: V_RETURN(D3DXCreateTextureFromFileExW(pd3dDevice, L"texture.jpg", 0, 0, 5, 0, D3DFMT_DXT1, D3DPOOL_MANAGED, 可以通过DirectX SDK提供的纹理编辑工具"DirectX Texture Editor",创建压缩格式的纹理文件(后缀为DDS的纹理文件),或将其他格式的纹理文件转换为压缩格式的纹理文件。 在创建好压缩纹理之后,就可以和前面一样设置纹理及各项纹理渲染状态,最后进行渲染。如果当前设备支持DXT压缩纹理,那么在使用DXT纹理渲染图形时,Direct3D引擎会自动进行纹理压缩,如果当前设备不支持DXT压缩纹理,这时使用DXT压缩纹理和使用普通的非压缩纹理完全相同。 当使用大量纹理贴图渲染复杂场景时,通过使用DXT压缩纹理可以有效提高程序运行性能。
纹理管理 如果显卡中只有64MB的视频内存,就应该考虑将哪些纹理加载和保留在内存中。可以编写一个算法让计算机来自动考虑这些问题,那么这个算法的任务是什么呢?它需要跟踪可用的纹理内存总数,并了解哪些纹理是经常用到的,而哪些纹理是很少用到的。至少,这个纹理管理算法必须能决定哪些现有的纹理资源可以通过一张纹理图来重新加载,以及应该销毁哪些表面,然后由新的纹理资源取而代之。 Direct3D有一个自动的纹理管理系统,当通过CreateTexture()创建一个纹理对象时,将Pool参数指定为D3DPOOL_MANAGED,就是向Direct3D请求该系统的支持。纹理管理器通过一个时间戳来跟踪纹理的使用情况,这个时间戳用于记录每个纹理对象最后被使用的时间。纹理管理器通过"最近最少使用"算法来决定哪些纹理应从视频内存中移除,若有两个纹理对象同时满足移除条件,则根据纹理属性来做进一步的判断。如果它们具有相同的优先级,则移除最近最少使用的纹理,如果它们具有相同的时间戳,则移除低优先级的纹理。 通过为纹理表面调用IDirect3DResource9::SetPriority()函数,可以给托管的纹理赋予一个优先级,该函数声明如下: Assigns the resource-management priority for this resource. DWORD SetPriority( DWORD PriorityNew); Remarks Priorities are used to determine when managed resources are to be removed from memory. A resource assigned a low priority is removed before a resource with a high priority. If two resources have the same priority, the resource that was used more recently is kept in memory; the other resource is removed. Managed resources have a default priority of 0.
原图:
DXT压缩后: |
-- 作者:卷积内核 -- 发布时间:12/10/2008 8:27:00 AM -- 主程序: #pragma warning(disable : 4127) #define IDC_TOGGLE_FULLSCREEN 1 #define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0) struct sCustomVertex #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_TEX1) ID3DXFont* g_font; CDXUTDialogResourceManager g_dlg_resource_manager; IDirect3DVertexBuffer9* g_vertex_buffer; //-------------------------------------------------------------------------------------- IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, // check whether device support DXT compressed texture return true; static bool is_first_time = true; if(is_first_time) // if using reference device, then pop a warning message box. return true; V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice)); D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, V_RETURN(D3DXCreateTextureFromFileExW(pd3dDevice, L"texture.jpg", 0, 0, 5, 0, D3DFMT_DXT1, D3DPOOL_MANAGED, // create vertex buffer and fill data sCustomVertex vertices[] = pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_MANAGED, &g_vertex_buffer, NULL); void* ptr; return S_OK; V_RETURN(g_dlg_resource_manager.OnResetDevice()); // set dialog position and size g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0); // setup view matrix D3DXMATRIX mat_view; D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up); // set projection matrix // set texture and texture stage state and sample state pd3dDevice->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex)); return S_OK; //-------------------------------------------------------------------------------------- release_com(g_text_sprite); release_com(g_font); //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // show frame and device states // show helper information if(g_show_help) text_helper.End(); //-------------------------------------------------------------------------------------- if(g_settings_dlg.IsActive()) // Clear the render target and the zbuffer // Render the scene V( pd3dDevice->EndScene() ); if(g_settings_dlg.IsActive()) *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam); return 0; //-------------------------------------------------------------------------------------- case IDC_TOGGLE_REF: case IDC_CHANGE_DEVICE: //-------------------------------------------------------------------------------------- g_button_dlg.SetCallback(OnGUIEvent); int x = 35, y = 10, width = 125, height = 22; g_button_dlg.AddButton(IDC_TOGGLE_FULLSCREEN, L"Toggle full screen", x, y, width, height); //-------------------------------------------------------------------------------------- // Set the callback functions // Initialize DXUT and create the desired Win32 window and Direct3D device for the application // Start the render loop // TODO: Perform any application-level cleanup here return DXUTGetExitCode();
[B][URL=http://www.cppblog.com/Files/changingnow/DXTTexture.rar]下载示例工程[/URL][/B] |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
312.988ms |