天天看點

D3D基礎知識複習(二)

這些是DX6的一些知識,不過還有些學習的價值。原文位址:http://17de.com/library/d3d_6im/d3dim6_8.htm

這一部分内容是關于Direct3D裝置用途及使用的一些概述,包括以下内容:

    • 1. 什麼是Direct3D裝置
    • 2. Direc3D裝置類型
    • 3. 裝置接口
    • 4. 使用裝置
    • 5. 仿真模式
    • 6. AGP表面與Direct3D裝置
    • 7. 執行緩沖

  Direct3D裝置是Direct3D渲染的組成部分。它用來封裝(encapsulate)和存儲(store)渲染狀态。另外,一個Direct3D裝置還執行變換和燈光操作,以及将一幅圖象光栅處理(rasterize)到一個DirectDraw表面。在結構上,Direct3D裝置包含了一個變換子產品(transformation module),一個燈光子產品(lighting module),和一個光栅子產品(rasterizing module),如下圖所示:

D3D基礎知識複習(二)

  Direct3D允許程式使用定制變換和燈光子產品來忽略Direct3D裝置的變換和燈光子產品。詳細内容見“頂點格式”。

  Direct3D立即模式裝置支援三種接口:IDirect3Ddevice,IDirect3DDevice2,和IDirect3DDevice3。IDirect3Ddevice接口提供使用執行緩沖進行程式設計的方法。IDirect3DDevice2接口提出DrawPrimitive方法。IDirect3DDevice3擴充了DrawPrimitive的功能。DrawPrimitive方法提供了首選的渲染途徑。這三個接口有一些公共的方法用于各種程式類型,并且這些方法使三個接口都提供的。有關這兩種渲染途徑的詳細内容見“渲染”部分。

  在DirectX 5.0中的IDirect3DDevice2接口介紹之前,Direct3D裝置是DirectDrawSurface對象的接口。IDirect3DDevice2接口實作了一個裝置對象模型(device-object model),在這個模型中,Direct3Ddevice對象與DirectDraw表面是完全分離的。IDirect3DDevice3接口使用并擴充了這一裝置對象模型。因為它們獨立于DirectDraw表面并且有獨立的生存期,Direct3D 裝置對象在不同的時間可以使用不同的DirectDraw表面來作為渲染目标。有關渲染目标的詳細内容見IDirect3DDevice3::SetRenderTarget。

這一部分介紹Direct3D裝置和它的每一種類型。

    • 2.1 關于裝置類型
    • 2.2 HAL裝置
    • 2.3 MMX裝置
    • 2.4 RGB裝置
    • 2.5 Ramp裝置

  注:D3d.h頭檔案為參考光栅(reference rasterizer)定義了一個第五裝置辨別符(IID_IDirect3DrefDevice)。這個參考光栅不是為正式程式設計的,它隻被用于參考或特征示範時使用。它不能用通常的方法來列舉,你必須在HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Direct3D/Drivers注冊鍵(registry key)中設定一個名為EnumReference的值,這樣才能被列舉。

  Direct3D支援四種類型的裝置。程式建立的Direct3D裝置必須與所使用的硬體相比對。Direct3D提供兩種渲染能力,一種是通過3-D硬體,另一種是對3-D硬體功能的軟體方針。是以,Direct3D提供的裝置對于硬體通路和軟體仿真都予以支援。

  硬體加速裝置比軟體仿真裝置有更好的性能。

  除了參考光栅(reference rasterizer)之外,軟體裝置并不支援硬體裝置的所具有的特性。例如,軟體裝置就不支援同時将一個紋理分派到兩個以上的紋理stage(texture 平台)。程式應該對裝置能力經常進行查詢以确定支援哪些特性。

  如果程式運作的計算機的顯示擴充卡支援Direct3D,那麼程式就可以用它來進行3-D操作。Direct3D相容加速卡在硬體中實作了所有或部分的變換、燈光和光栅子產品。

  應用程式不能直接通路3-D加速卡。他們要調用Direct3D的函數和方法。Direct3D通過HAL來通路硬體。如果程式運作的計算機支援HAL,那麼使用HAL裝置就能獲得最好的性能。

  為了建立一個HAL裝置,程式要調用IDirect3D3::CreateDevice,并且将IID_IDirect3DHALDevice作為它的低一個參數。詳細内容見“建立一個Direct3D裝置”。

  注:與軟體仿真裝置(MMX, RGB,參考光栅和傳統的ramp裝置)不同的是,硬體裝置不能在8-bit渲染目标表面上進行渲染。

  MMX是一套特殊的指令集,一些微處理器提供對它的支援,并由此而獲得了更好的多媒體和三維處理性能。如果安裝了MMX,那麼Direct3D會使用MMX來提高渲染速度。

  MMX裝置不象HAL裝置那樣,它并不是硬體加速裝置。變換、燈光和光栅子產品都是由軟體來執行的。但是,MMX裝置提供了比其它的軟體仿真裝置更好的性能。

  如果程式使用的是Direct3D2接口,那麼它就必須明确的建立一個MMX裝置。但是,從IDirect3D3接口開始,MMX和RGB裝置将執行同樣的特性設定。如果程式需要建立一個RGB裝置并且微處理器支援MMX技術的話,那麼Direct3D将自動建立一個MMX裝置。

  引用IDirect3D3::CreateDevice方法,将IID_IDirect3DMMXDevice作為第一個參數,這樣就可以建立一個MMX裝置。有關建立Direct3D裝置的詳細内容見“建立一個Direct3D裝置”。如果程式要求建立一個MMX裝置,然而計算機并不支援MMX技術,那麼CreateDevice方法就會失敗。

  如果計算機不提供對三維操作的硬體加速,那麼程式可以使用軟體來對三維硬體進行仿真。如果你的計算機不支援MMX技術,但卻有足夠的處理能力,那麼程式就可以使用RGB裝置。RGB裝置通過軟體來仿真3-D硬體的色彩處理功能。因為RGB裝置要通過軟體來進行仿真,是以它的速度就要比HAL裝置慢,也要比MMX裝置慢。詳細内容見“仿真模式”。

  如果你所使用的機器支援MMX技術,那麼當程式建立一個RGB裝置時,IDirect3D3接口會自動建立一個MMX裝置。

  程式使用IDirect3D3::CreateDevice函數來建立一個RGB裝置,同時要将IID_IDirect3DRGBDevice作為它的第一個參數。

  注:ramp軟體仿真驅動器在DirectX中已經被廢除了,DirectX 6.0以及後續版本對它均不再提供支援。使用IDirect3D3不能建立一個Direct3D ramp裝置,也不能使用IDirect3DDevice3接口來查詢一個已經存在的ramp裝置。簡單來說,ramp裝置不支援任何的多紋理融合操作。要想實作對這些特性的方針,就必須使用MMX或RGB軟體仿真裝置。

  一個ramp裝置是一個軟體仿真裝置,它可以提供單色光。如果你的計算機沒有足夠的處理能力來使用其它的Direct3D裝置,那麼你可以選擇使用ramp裝置。詳細内容見“仿真模式”。

  Ramp裝置主要是為了為傳統的DirectX程式提供支援。一般而言,沒有足夠的處理能力來支援RGB裝置的計算機也是不适于3-D程式的。

  程式通過調用IDirect3D2::CreateDevice方法來建立ramp裝置,同時要将IID_IDirect3DrampDevice作為第一個參數。

  使用裝置接口,主要是用來操作一個Direct3Ddevice對象的渲染狀态、燈光狀态以及執行渲染操作。盡管裝置支援三個裝置接口(IDirect3DDevice, IDirect3DDevice2,和IDirect3DDevice3),但是你的程式中并不需要使用多個裝置接口。使用那種接口,要有所使用的渲染方法來決定,即DrawPrimitive方法或執行緩沖方法。下面我們來讨論一下這三種接口以及它們所代表的渲染方法:

  IDirect3Ddevice支援使用執行緩沖來進行渲染,它是Direct3D程式最初使用的方法。這個接口在後來的DirecX版本中是相容的,但是DrawPrimitive渲染結構更容易使用。我們推薦使用IDirect3DDevice3接口來編制新的應用程式。

  所有Direct3D裝置類型都支援IDirect3Ddevice接口。

  最新的兩個裝置接口是IDirect3DDevice3和IDirect3DDevice2,它們都支援DrawPrimitive 渲染方法和執行緩沖。DrawPrimitive方法大大簡化了準備和渲染頂點的過程,并被認為是首選的渲染方法。

  如果你的程式使用DrawPrimitive方法,那麼最好使用最新版本的裝置接口。符合COM 标準的向後相容性的Direct3D支援所有的接口版本,但我們還是推薦使用最新的版本,這樣就可以利用到一些新的特性,并且能提高程式的性能。

  DirectX 5.0中建立的IDirect3DDevice2接口首次提出了DrawPrimitive渲染結構。基于DrawPrimitive的渲染方法比執行緩沖更容易使用,并且提供了用于Direct3D程式設計的更直接的形式。詳細内容見“渲染”部分。所有的Direct3D裝置類型都支援IDirect3DDevice2接口。

  象IDirect3DDevice2接口一樣,IDirect3DDevice3接口也支援DrawPrimitive方法。相應于IDirect3D3接口,IDirect3DDevice2接口提供了增強的特性集,它包括多紋理融合、頂點緩沖以及增強的3-D幾何渲染管道。IDirect3DDevice3接口也提供了IDirect3DDevice2接口中的同樣的方法。同時它也為IDirect3DDevice3::SetRenderState方法增加了一些新的渲染狀态以支援多紋理融合。

  所有的Direct3D裝置類型都支援IDirect3DDevice3接口。

這一部分我們将讨論如何在立即模式中使用Direct3D裝置。

    • 4.1 枚舉Direct3D裝置
    • 4.2 建立Direct3D裝置
    • 4.3 設定變換
    • 4.4 渲染
    • 4.5 燈光狀态

這一部分我們來讨論列舉Direct3D裝置時的兩個主要的任務。

    • 4.1.1 開始裝置枚舉
    • 4.1.2 選擇一個被枚舉的裝置

  程式可以對所使用的硬體進行查詢,這樣就可以确定它支援哪種Direct3D裝置。完成這一任務最重要的API函數是IDirect3D3::EnumDevices,它用來枚舉所有硬體可能支援的Direct3D裝置。它使用D3DenumDevicesCallback函數來選擇要使用的裝置。D3DenumDevicesCallback函數由你在程式中來提供。注意:因為這個回調函數是由程式提供的,是以它的名字可以任意來取。

  下面的代碼展示了枚舉和選擇Direct3D裝置的過程。在這個例子中,裝置枚舉回調函數被命名為EnumDeviceCallback。一個指向EnumDeviceCallback的指針被傳遞給IDirect3D3::EnumDevices方法,它為每個正在被枚舉的裝置調用EnumDeviceCallback函數。

// In this code fragment, the variable lpd3d contains a valid 

// pointer to the IDirect3D3 interface that the application obtained

// prior to executing this code.

BOOL fDeviceFound = FALSE; 

hRes = lpd3d->EnumDevices(EnumDeviceCallback, &fDeviceFound); 

if (FAILED(hRes)) 

{

 // Code to handle the error goes here.

}

if (!fDeviceFound) 

 // Code to handle the error goes here.

  D3DenumDevicesCallback函數被每一個安裝在系統中的Direct3D裝置所引用。當它被調用時,它的第一個參數将作為正在被枚舉的裝置的全局統一辨別符(GUID)。GUID的值将是IID_IDirect3DHALDevice,IID_IDirect3DMMXDevice,IID_IDirect3DRGBDevice或IID_IDirect3DrampDevice。D3DenumDevicesCallback函數最适合你的程式的那個裝置。

  D3DenumDevicesCallback函數的第二和第三個參數為字元串,它包含了裝置的名稱和使用者友好的描述。

  第四個參數指向一個D3DDEVICEDESC結構體,它包含了裝置的硬體性能的有關資訊。即使被列舉的裝置是一個HAL裝置,具體的硬體也不一定支援所有的Direct3D API所提供的性能。

  D3DenumDevicesCallback的第五個參數包含了一個指向D3DDEVICEDESC結構體的指針,它用來描述你所使用的機器的軟體仿真性能。這一資訊與你要使用的軟體仿真裝置(MMX, RGB,或RAMP裝置)有關。

  最後一個參數是一個程式定義的值。你的程式将這個參數傳遞給IDirect3D3::EnumDevices方法。它于此将這個值傳遞給D3DenumDevicesCallback函數。

  下面的代碼描述了如何建立一個D3DenumDevicesCallback函數。在這個例子中,程式提供的回調函數名為EnumDeviceCallback。EnumDeviceCallback函數使用下面的算法來選擇一個适合的Direct3D裝置:

  1. 放棄所有不适合目前顯示深度的裝置。
  2. 放棄所有不能處理Gouraud-明暗處理三角形的裝置。
  3. 如果一個硬體裝置符合第一和第二點,那麼就使用這個裝置。但是如果程式正處于debug模式,那麼它不會使用硬體裝置。
  4. 另外,盡量使用Mono/Ramp模式的軟體渲染裝置,而不要使用RGB裝置;如果不使用MMX裝置,那麼Mono會更快。

  EnumDeviceCallback函數的代碼如下所示:

// This function is written with the assumption that the following

// global variables are declared in the program.

// DWORD dwDeviceBitDepth = 0; 

// GUID guidDevice; 

// char szDeviceName[MAX_DEVICE_NAME]; 

// char szDeviceDesc[MAX_DEVICE_DESC]; 

// D3DDEVICEDESC d3dHWDeviceDesc; 

// D3DDEVICEDESC d3dSWDeviceDesc; 

static HRESULT WINAPI 

EnumDeviceCallback(LPGUID lpGUID, 

          LPSTR lpszDeviceDesc, 

          LPSTR lpszDeviceName, 

          LPD3DDEVICEDESC lpd3dHWDeviceDesc, 

          LPD3DDEVICEDESC lpd3dSWDeviceDesc, 

          LPVOID lpUserArg) 

 BOOL fIsHardware; 

 LPD3DDEVICEDESC lpd3dDeviceDesc; 

 // If there is no hardware support the color model is zero. 

 fIsHardware = (lpd3dHWDeviceDesc->dcmColorModel != 0); 

 lpd3dDeviceDesc = (fIsHardware ? lpd3dHWDeviceDesc : lpd3dSWDeviceDesc); 

 // Does the device render at the depth we want? 

 if ((lpd3dDeviceDesc->dwDeviceRenderBitDepth & dwDeviceBitDepth) == 0) 

 { 

  // If not, skip this device. 

  return D3DENUMRET_OK; 

 } 

 // The device must support Gouraud-shaded triangles. 

 if (D3DCOLOR_MONO == lpd3dDeviceDesc->dcmColorModel) 

 { 

  if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps&D3DPSHADECAPS_COLORGOURAUDMONO)) 

  { 

   // No Gouraud shading. Skip this device. 

   return D3DENUMRET_OK; 

  } 

 } 

 else 

 { 

  if (!(lpd3dDeviceDesc->dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDRGB)) 

  { 

   // No Gouraud shading. Skip this device. 

   return D3DENUMRET_OK; 

  } 

 } 

 // If a software device was found on a previous invocation

 // of this callback function.

 if (!fIsHardware && *lpUserArg && (D3DCOLOR_RGB == lpd3dDeviceDesc->dcmColorModel)) 

 {

  // If this is software RGB and we already have found 

  // a software monochromatic renderer, we are not 

  // interested. Skip this device. 

  return D3DENUMRET_OK; 

 }

 //

 // This is a device we are interested in. Save the details. 

 //

 *lpUserArg = TRUE; 

 CopyMemory(&guidDevice, lpGUID, sizeof(GUID)); 

 strcpy(szDeviceDesc, lpszDeviceDesc); 

 strcpy(szDeviceName, lpszDeviceName); 

 CopyMemory(&d3dHWDeviceDesc, lpd3dHWDeviceDesc, 

 sizeof(D3DDEVICEDESC)); 

 CopyMemory(&d3dSWDeviceDesc, lpd3dSWDeviceDesc, 

 sizeof(D3DDEVICEDESC)); 

 // If this is a hardware device, we have found 

 // what we are looking for. 

 if (fIsHardware) 

  return D3DENUMRET_CANCEL; 

 // Otherwise, keep looking. 

 return D3DENUMRET_OK; 

  建立一個裝置時,必須要選擇Direct3D程式使用執行緩沖還是DrawPrimitive方法。這一選擇将決定在建立一個裝置時程式需要獲得哪種類型的接口指針。如果選擇使用執行緩沖,那麼程式就必須得到一個指向IDirect3Ddevice接口的指針。如果選擇DrawPrimitive方法,程式必須得到一個指向IDirect3DDevice3接口的指針。

下面的讨論将向我們展示如何來建立一個裝置:

    • 4.2.1 建立使用執行緩沖的裝置
      • 4.2.2 建立使用DrawPrimitive方法的裝置

  注:一些通用的硬體裝置要求渲染目标與深度緩沖表面使用相同的顔色深度。在這些硬體上,如果程式在渲染目标表面使用16-bit色,那麼相應的深度緩存也必須使用16-bit色。如果使用32-bit的渲染目标表面,那麼深度緩存也必須是32-bits,如果需要的話,也可以使用8-bits的模闆緩沖。

  如果程式運作的硬體有這樣的要求,而你的程式又不能滿足這一要求,那麼,任何想要使用這樣不相适應的表面來建立一個渲染裝置的嘗試都将失敗。你可以使用DirectDraw的IDirectDraw4::GetDeviceIdentifier方法來追蹤有這一限制的硬體。

  要使用執行緩沖方法,程式必須先在正常方式下初始化DirectDraw,并得到一個指向IDirect3D3接口的指針。詳細内容見“得到(retrive)一個IDirect3D3接口”。程式還應建立一個包含DDSCAPS_3DDEVICE能力的表面。關于建立表面的内容見“建立表面”部分。然後,對這個表面調用IUnknown::QueryInterface方法,得到一個指向IDirect3Ddevice接口的指針。使用IDirect3DDevice::CreateExecuteBuffer來建立一個執行緩沖,并得到一個指向IDirect3DexecuteBuffer接口的指針。下面左圖描述了這一過程:

D3D基礎知識複習(二)

       

D3D基礎知識複習(二)

  使用DrawPrimitive方法,程式也必須先在正常方式下初始化DirectDraw對象,并得到一個指向IDirect3D3接口。然後,調用IDirect3D3::CreateDevice方法建立一個Direct3D裝置。這一方法傳遞給程式一個指向IDirect3DDevice3接口的指針。

上面右圖描述了這一過程:

代碼如下:

LPDIRECTDRAW lpDD; // DirectDraw Interface

LPDIRECT3D3 lpD3D; // Direct3D3 Interface

LPDIRECTDRAWSURFACE4 lpddsRender; // Rendering surface

LPDIRECT3DDEVICE3 lpd3dDevice; // D3D Device

// Create DirectDraw interface.

// Use the current display driver.

hResult = DirectDrawCreate (NULL, &lpDD, NULL); 

if (FAILED (hResult))

{

 // Code to handle the error goes here.

}

// Get an IDirect3D3 interface

hResult = lpDD->QueryInterface (IID_IDirect3D3, (void **)&lpD3D);

if (FAILED (hResult))

{

 // Code to handle the error goes here.

}

//

// Code for the following tasks is omitted for clarity.

//

// Applications will need to set the cooperative level at this point.

// Full-screen applications will probably need to set the display  mode.

// The primary surface should be created here.

// The rendering surface must be created at this point. It is 

// assumed in this code fragment that, once created, the rendering

// surface is pointed to by the variable lpddsRender. 

// If a z-buffer is being used, it should be created here.

// Direct3D device enumeration can be done at this point.

hResult = lpD3D->CreateDevice (IID_IDirect3DHALDevice,

              lpddsRender, 

              &lpd3dDevice,

              NULL);

  上面的例子中引用了IDirect3D3::CreateDevice方法來建立一個Direct3D裝置。在這個例子中,如果調用成功的話,就建立了一個Direct3D HAL裝置。

  要注意的時,程式中建立的DirectDraw渲染表面不允許作為一個Direct3D的渲染目标來建立。要這樣做,就必須向IDirectDraw4::CreateSurface方法傳遞一個DDSURFACEDESC2結構體。DDSURFACEDESC2結構體由一個名為ddsCaps的成員,它是一個DDSCAPS類型的結構體。DDSCAPS結構體又包含了一個名為dwCaps的成員,在使用IDirectDraw4::CreateSurface方法時,它必須被設定為DDSCAPS_3DDEVICE。

  當使用硬體加速渲染裝置時,我們所使用的渲染目标表面必須在顯存中來建立(使用DDSCAPS_VIDEOMEMORY标志),否則,在系統記憶體中來建立(使用DDSCAPS_SYSTEMMEMORY标志)。

  使用IDirect3DDevice3::SetTransform 方法來應用變換。例如,你可以使用如下的代碼來設定視變換:

HRESULT hr

D3DMATRIX view;

// Fill in the view matrix. 

hr = lpDev->SetTransform(D3DTRANSFORMSTATE_VIEW, &view);

if(FAILED(hr))

 return hr;

  調用IDirect3DDevice3::SetTransform方法時,它的第一個參數有三種可能的設定:D3DTRANSFORMSTATE_WORLD, D3DTRANSFORMSTATE_VIEW,和D3DTRANSFORMSTATE_PROJECTION。這三種變換狀态在D3DTRANSFORMSTATETYPE枚舉類型中進行定義。

4.4.6 渲染狀态

這一部分我們将介紹有關紋理狀态的内容,并将它與紋理stage(texture 平台)狀态進行比較。
  • 關于渲染狀态
  • 目前紋理
  • 反走樣狀态 Antialiasing States
  • 紋理尋址狀态 Texture Addressing State
  • 紋理Wrapping狀态 Texture Wrapping State
  • 紋理邊界 Texture Borders
  • 紋理透視狀态 Texture Perspective State
  • 紋理過濾狀态 Texture Filtering State
  • 輪廓和填充狀态 Outline and Fill States
  • 明暗處理狀态 Shading State
  • 霧化狀态 Fog State
  • Alpha狀态
  • 紋理融合狀态 Texture Blending State
  • Culling狀态 Culling State
  • 深度緩沖狀态 Depth Buffering State
  • 平滑狀态 Ramp State
  • 子像素修正狀态 Subpixel Correction State
  • 平面掩模狀态 Plane Masking State
  • 顔色碼狀态 Color Keying State
  • 渲染指令批處理狀态 Render Command Batching State
  • 模闆緩沖狀态 Stencil Buffer State

  注意,我們這裡所列出的内容是在使用IDirect3DDevice3接口時,對渲染狀态的控制。使用IDirect3Ddevice接口的執行緩沖時,渲染狀态用D3DOP_STATERENDER操作碼來進行控制。

  1. 關于渲染狀态

  裝置渲染狀态控制着Direct3D裝置的光栅子產品(rasterization module)的行為。通過對渲染狀态的改變,我們可以得到諸如明暗處理的應用,霧化效果的使用等等光栅操作。

  程式通過引用IDirect3DDevice3::SetRenderState方法來控制渲染狀态的其他特性。D3DRENDERSTATETYPE枚舉類型用來聲明所有可能的渲染狀态。程式将D3DRENDERSTATETYPE的第一個參數傳遞給IDirect3DDevice3::SetRenderState方法。

  渲染狀态同時控制紋理的類型和紋理過濾器如何工作。對于DirectX 6.0和以後的版本,所有與紋理相關的渲染狀态都被IDirect3DDevice3::SetTexture平台State方法提供的相應特性所取代了。被替換的渲染方法仍然起作用,但是被用于影響satge 0中相應的狀态。為了提高性能,我們應該盡量使用SetTexture平台State 方法中的特性。下面列出了被替換的渲染狀态,并列出了相應的新的紋理子產品提供的狀态:

D3DRENDERSTATE_TEXTUREADDRESS

被D3DTSS_ADDRESS, D3DTSS_ADDRESSU, D3DTSS_ADDRESSV紋理stage狀态所取代。

D3DRENDERSTATE_BORDERCOLOR

被D3DTSS_BORDERCOLOR紋理stage狀态取代。

D3DRENDERSTATE_TEXTUREMAG

被D3DTSS_MAGFILTER紋理stage狀态取代。

D3DRENDERSTATE_TEXTUREMIN

被D3DTSS_MINFILTER紋理stage狀态取代。MIPMAP縮小過濾(Mipmap minification filtering)被D3DTSS_MIPFILTER取代。

D3DRENDERSTATE_TEXTUREMAPBLEND

被D3DTSS_COLOROP and D3DTSS_ALPHAOP紋理stage狀态取代。

    • 目前紋理

      預設情況下,Direct3D不對圖元使用任何紋理。當程式選擇了一個紋理作為目前紋理時,它通知Direct3D裝置将這個紋理應用到所有從此時起要渲染的圖元上。如果要求場景中的每個圖元都有自己的紋理,那麼就要在每個圖元被渲染之前對紋理進行設定。

      IDirect3D2接口需要使用紋理句柄。在IDirect3D3接口中,紋理被作為獨立的對象進行建立。程式通過IDirect3DTexture2接口來通路紋理的功能。如何獲得指向IDirect3DTexture2接口的指針的有關内容見“獲得一個紋理接口指針”部分。程式可以使用紋理指針來指派8個目前使用的紋理。詳細内容見“配置設定目前紋理”

      如果程式使用紋理句柄,它必須将D3DRENDERSTATE_TEXTUREHANDLE作為第一個參數傳遞給IDirect3DDevice3::SetRenderState。第二個參數就是紋理句柄。

      程式如果将NULL作為第二個參數傳遞給IDirect3DDevice3::SetRenderState方法,将使紋理操作無效。

    • 反走樣狀态

      反走樣是一種使螢幕上的直線和邊緣看起來更加平滑的方法。Direct3D支援兩種反走樣方法,即邊緣反走樣(edge antialiasing)和全場景反走樣(full-scene antialiasing)。詳細内容見“通用技術與特殊效果”中的“反走樣”部分。

      預設情況下,Direct3D不适用反走樣。D3DRENDERSTATE_ANTIALIAS渲染狀态可以被設定為 D3DANTIALIASMODE中的一個成員,它可以使全場景反走樣有效。(預設情況下的D3DANTIALIAS_NONE使全場景反走樣無效。)

      要使邊緣反走樣有效(它需要進行第二次渲染周遊),需要将D3DRENDERSTATE_EDGEANTIALIAS設定為TRUE。要使它無效,要将D3DRENDERSTATE_EDGEANTIALIAS設定為FALSE。

    • 紋理尋址狀态

      U、V紋理尋址狀态(由D3DRENDERSTATE_TEXTUREADDRESS, D3DRENDERSTATE_TEXTUREADDRESSU和D3DRENDERSTATE_TEXTUREADDRESSV渲染狀态設定)已經被IDirect3DDevice3接口提供的紋理尋址特性所取代。但是,使用IDirect3DDevice2接口的程式仍然可以使用先前的紋理尋址模式。

      這兩種紋理尋址模式的讨論見“設定和恢複紋理尋址模式”。

    • 紋理Wrapping狀态

      U、V紋理Wrapping渲染狀态D3DRENDERSTATE_WRAPU和D3DRENDERSTATE_WRAPV被D3DRENDERSTATE_WRAP0到D3DRENDERSTATE_WRAP7渲染狀态所取代。

      這些新的渲染狀态,在進行裝置的多紋理層疊操作時,可以用來控制不同的紋理是否執行U、V紋理Wrapping。将這些渲染狀态設定為D3DWRAP_U和D3DWRAP_V聯合标志 ,可以使Wrapping操作在對應的方向上有效;或者省略使用0值,使Wrapping操作無效。預設情況下,Wrapping操作對于紋理stage上的所有方向都是無效的。要了解有關概念,請看“紋理Wrapping”部分。

      注:盡管D3DRENDERSTATE_WRAPU和D3DRENDERSTATE_WRAPV被替換了,IDirect3DDevice3接口仍然承認它們。當把這些老的渲染狀态傳遞給IDirect3DDevice3::SetRenderState時,它們會在stage 0上影響U、V紋理Wrapping。

    • 紋理邊界

      紋理邊界顔色狀态已經被由IDirect3DDevice3::SetTexture平台State方法支援的 D3DTSS_BORDERCOLOR紋理stage狀态所取代。如果程式使用IDirect3DDevice3接口,你可以通過設定SetTexture平台State來改變每一個紋理stage的邊緣顔色。

      仍然使用IDirect3DDevice2接口的程式也可以前面那樣使用紋理邊緣顔色,在這種情況下,可以通過把D3DRENDERSTATE_BORDERCOLOR枚舉值作為第一個參數傳遞給IDirect3DDevice2::SetRenderState方法來設定或得到紋理邊界顔色紋理。第二個參數是RGBA邊緣顔色。

      詳細内容見“關于邊界顔色紋理尋址模式”。

    • 紋理透視狀态

      程式可以對紋理進行透視修正,這樣當圖元由于遠離觀察者而變小時,可以使紋理更好的與圖元相比對。見D3DRENDERSTATE_TEXTUREPERSPECTIVE。

    下面的代碼展示了紋理透視修正的過程:

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // a Direct3DDevice3.

    // Enable texture perspective.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE);

      對于IDirect3DDevice3接口,預設情況下為TRUE,使透視修正紋理映射有效。對于先前版本的接口,預設值為FALSE。要注意的是,許多的3-D擴充卡對于紋理透視修正會無條件的執行。透視修正必須使用基于w的霧化和w-buffer才會有效。詳細内容見“霧化“部分的“Eye-relative vs. Z-Based Depth”,以及“深度緩沖”部分的“使深度緩沖有效”。
    • 紋理過濾狀态

      程式如何來設定紋理過濾狀态主要要看使用何種版本的Direct3D裝置接口。如果程式使用IDirect3DDevice3接口,那麼這裡讨論的渲染狀态就會被IDirect3DDevice3::SetTexture平台State方法提供的紋理過濾選項所取代。詳細内容見“紋理過濾”部分。

      注:盡管這裡讨論的渲染狀态被紋理stage狀态替換了,但是,如果你仍要使用它們的話,IDirect3DDevice3::SetRenderState(與IDirect3DDevice2版本相對應)方法仍然有效。系統會将這些渲染狀态的效果映射到多紋理層疊的stage 0上。程式不能将老的渲染狀态與相應的紋理stage狀态相混淆,否則将出現無法預料的結果。

      如果程式使用IDirect3DDevice2接口,可以通過IDirect3DDevice2::SetRenderState方法來設定紋理過濾狀态。Direct3D支援最近點取樣(nearest point sampling),雙線性過濾(bilinear filtering),各向異性紋理過濾(anisotropic texture filtering),以及mipmap過濾(mipmap filtering)。使用D3DTEXTUREFILTER枚舉類型來選擇過濾類型。

      當程式放大一個紋理時,可以使用Direct3D裝置來選擇一種紋理過濾方法,将IDirect3DDevice2::SetRenderState方法的第一個參數設定為D3DRENDERSTATE_TEXTUREMAG枚舉值,還必須将D3DTEXTUREFILTER中的一個枚舉值作為第二個參數。 要将一個紋理縮小時,将IDirect3DDevice2::SetRenderState的第一個參數設定為D3DRENDERSTATE_TEXTUREMIN,将第二個參數設定為D3DTEXTUREFILTER中的一個枚舉值。如果程式使用軟體仿真裝置,它們必須是對D3DRENDERSTATE_TEXTUREMAG和D3DRENDERSTATE_TEXTUREMIN使用相同的過濾方法。如果使用的過濾方法不同,會導緻程式性能的降低。Direct3D硬體裝置(HAL和MMX)沒有這樣的性能限制。

      當D3DRENDERSTATE_TEXTUREMAG狀态被設定為D3DFILTER_NEAREST時,各向異性過濾處于無效狀态。隻有當D3DRENDERSTATE_TEXTUREMAG被設定為D3DFILTER_LINEAR時,各向異性過濾才有效。對于D3DRENDERSTATE_TEXTUREMIN控制下的過濾,隻有當它被設定為D3DFILTER_LINEAR、D3DFILTER_MIPLINEAR或D3DFILTER_LINEARMIPLINEAR時,各向異性過濾才有效。

      使用各向異性紋理例過濾的程式應該将過濾程度設定為一個我們需要的值。當它被設為1時,各向異性過濾是無效的,而被設定為大于1時,則是有效的。見“各向異性紋理過濾”和D3DRENDERSTATE_ANISOTROPY。

      當我們使用MIPMAP過濾時,程式可以選擇近點取樣(near-point sampling)、mipmap或是線性mipmap過濾。臨近點取樣MIPMAP按照是否與最終輸出的紋理具有最接近的分辨率這一規則來選擇MIPMAP紋理,然後使用最近點取樣來獲得顔色資訊。線性mipmap過濾則從兩個最近的mipmap中選擇一個顔色,然後在它們之間進行顔色的線性内插運算。見“用Mipmap進行紋理過濾”和D3DTEXTUREFILTER。

      程式可以通過控制mipmap LOD(level of detail)的偏移得到一種特殊的過濾效果。mipmap紋理上的正偏移可以産生一個銳度更高的混淆了的(aliased)圖象。負偏移量會使紋理圖象看起來比較模糊。詳細内容見D3DRENDERSTATE_MIPMAPLODBIAS。

    • 輪廓與填充狀态

  沒有紋理的圖元使用材質的顔色進行渲染,也可以使用頂點的顔色來渲染。可以使用D3DFILLMODE枚舉類型來選擇填充的方法。見D3DRENDERSTATE_FILLMODE。

  在填充一個圖元時,Direct3D使用标準的Windows ROP2二進制光栅操作。預設的值為R2_COPYPEN,它将像素設定為目前畫筆的顔色。詳細内容見SDK文檔中的GetROP2和SetROP2。盡管大部分的程式不需要改變這個預設值,但是程式仍然可以使用D3DRENDERSTATE_ROP2枚舉值來改變光栅填充操作。

  如果程式想要使抖動有效,那麼就必須将IDirect3DDevice3::SetRenderState的第一個參數設定為D3DRENDERSTATE_DITHERENABLE,将第二個參數設定為TRUE;要使抖動無效,就要将第二個參數設定為FALSE。

  程式也可以使用點畫填充圖案模式。見D3DRENDERSTATE_STIPPLEENABLE。使用D3DRENDERSTATE_STIPPLEPATTERN00到D3DRENDERSTATE_STIPPLEPATTERN31的枚舉值可以聲明一個32x32的點畫模式。這些枚舉值中的每一個都對應于點畫模式中的一行。舉例來說,要設定點畫模式中的第一行,就要将D3DRENDERSTATE_STIPPLEPATTERN00作為第一個參數傳遞給IDirect3DDevice3::SetRenderState。同時将點畫模式的16進制值作為第二個參數。

  有時,繪制一行的最後一個像素時,可能會造成與周圍圖元的重疊。這是可以使用D3DRENDERSTATE_LASTPIXEL枚舉值來進行控制。但是,如果我們沒有很好的預先計劃的話,最好不要使用這一設定。某些情況下,禁止對最後一個像素的渲染可能會造成在圖元之間出現縫隙。

  預設情況下,Direct3D裝置對圖元采用實輪廓(solid outline)。輪廓模式可以使用D3DLINEPATTERN結構來改變。見D3DRENDERSTATE_LINEPATTERN。

    • 明暗處理狀态

      Direct3D支援平面明暗處理和Gouraud明暗處理兩種模式。預設時使用Gouraud模式。程式可以使用D3DSHADEMODE枚舉類型來控制目前的明暗處理模式。見D3DRENDERSTATE_SHADEMODE。

    下面的代碼中将明暗處理模式設定為平面處理模式:

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // a Direct3DDevice3.

    // Set the shading state.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT);

  1. 霧化狀态
  2.   霧化效果可以使一個三維場景更加真實可信。除了模仿霧之外,它還有許多其他的用途。例如可以用來随着距離的增加不斷減小場景的清晰度,使得物體遠離觀察者時,它的細節能逐漸變得模糊。詳細内容見“霧化”部分。

      目前的Direct3D裝置允許進行霧化融合(fog blending),控制霧的顔色,操縱其他的霧化參數。通過将D3DRENDERSTATE_FOGENABLE渲染狀态設定為TRUE,可以使霧化有效。霧的顔色可以通過D3DCOLOR值來設定(霧的顔色中的alpha成分會被忽略)。見D3DRENDERSTATE_FOGCOLOR。

      有關霧的詳細内容見“霧化”部分。

    • Alpha狀态

      顔色的alpha值用來控制它的(不)透明度。Alpha融合有效将會使一個表面上的顔色、材質和紋理與另一個表面透明的進行混合。要進一步了解有關内容,見“Alpha紋理融合”與“多紋理融合”。

      Alpha融合渲染狀态:

      程式要使用D3DRENDERSTATE_ALPHABLENDENABLE枚舉值使alpha透明融合有效。Direct3D API允許多種類型的alpha融合,但要看使用者的3-D硬體是否支援這些融合類型。

      Alpha融合的類型由D3DRENDERSTATE_SRCBLEND和D3DRENDERSTATE_DESTBLEND渲染狀态來決定。源與目的融合狀态總是被成對的使用。下面的代碼展示了如何将源融合狀态設定為D3DBLEND_SRCCOLOR,以及如何目的融合狀态設定為D3DBLEND_INVSRCCOLOR。

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // an IDirect3DDevice3 interface.

    // Set the source blend state.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR);

    // Set the destination blend state.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR);

      經過上面的代碼調用,Direct3D在源顔色(要在目前位置上渲染的圖元的顔色)與目的顔色(幀緩存中的目前位置的顔色)之間執行了一次線性融合。這樣得到的效果就好像是一個彩色的玻璃。目的對象上的一些顔色看起來就象是被傳遞給了源對象,而另外的顔色則象是被吸收掉了。

      通過改變源和目的融合狀态,可以在一個有霧的或布滿灰塵的環境中得到一個具有放射性的物體的表面。例如,如果程式需要在一個霧化的環境中模拟火焰、作戰掩體、離子束或是看起來具有輻射性的物體,那麼可以将源和目的融合狀态設定為D3DBLEND_ONE。

      Alpha融合另一個用途是控制3-D場景中的光線,也被稱為光線映射(light mapping)。根據源alpha資訊,将源融合狀态設定為D3DBLEND_ZERO,将目的融合狀态設定為D3DBLEND_SRCALPHA,這樣可以使一個場景變暗。源圖元被當作一個光線映射來調節幀緩存中的内容,使得場景變暗,直到我們需要的狀态為止。這樣就會産生一種單色光的映射。

      彩色光線映射可以通過将源alpha融合狀态設定為D3DBLEND_ZERO,将目的融合狀态設定為D3DBLEND_SRCCOLOR來得到。

      Direct3D裝置提供alpha值點畫(stippling)功能,如果硬體支援的話。見D3DRENDERSTATE_STIPPLEDALPHA。如程式建立一個RGB或平滑(ramp)軟體仿真裝置,Direct3D會忽視這一枚舉值。

      Alpha測試(Alpha-test)渲染狀态:

      程式可以使用alpha測試來控制何時将像素繪制到目标表面。通過使用D3DRENDERSTATE_ALPHATESTENABLE枚舉值,程式可以對目前Direct3D裝置進行設定,進而能夠根據一個alpha測試函數來檢測每一個像素。如果測試成功,那麼像素就被繪制到目标表面。如果失敗,Direct3D就會忽略它。使用D3DRENDERSTATE_ALPHAFUNC枚舉值來選擇這個alpha測試函數。程式可以使用D3DRENDERSTATE_ALPHAREF渲染狀态,為所有的像素設定一個參考alpha值。

      Alpha測試最通常的用途是在光栅近似于透明的對象時,能夠提高程式的性能。如果正在進行光栅處理的像素的顔色資料比一個給定的像素(D3DPCMPCAPS_GREATEREQUAL)的顔色更加不透明,那麼這個像素就會被繪制,否則光栅會完全忽略這個像素,除了必須的融合這兩種顔色的過程之外。下面的程式中,如果一個給定的比較函數被支援的話,程式就會設定所需的用來提高性能的比較函數的參數。

    // This example assumes that pd3dDeviceDesc is a

    // D3DDEVICEDESC structure that was filled with a 

    // previous call to IDirect3DDevice3::GetCaps.

    if (pd3dDeviceDesc->dpcTriCaps.dwAlphaCmpCaps & D3DPCMPCAPS_GREATEREQUAL)

    {

     dev->SetRenderState( D3DRENDERSTATE_ALPHAREF, (DWORD)0x00000001);

     dev->SetRenderState( D3dRENDERSTATE_ALPHATESTENABLE, TRUE ); 

     dev->SetRenderState( D3DRS_ALPHACMP, D3DCMP_GREATEREQUAL );

    }

    // If the comparison isn't supported, render anyway. 

    // The only drawback is no performance gain.

      并非所有的硬體都支援所有的alpha測試特性。通過調用IDirect3DDevice3::GetCaps方法可以例檢查硬體的能力。得到硬體能力之後,在對想要得到的比較函數檢查D3DPRIMCAPS(包含于相應的D3DDEVICEDESC結構中)結構的dwAlphaCmpCaps成員。如果dwAlphaCmpCaps成員隻包含D3DPCMPCAPS_ALWAYS能力或是隻包含D3DPCMPCAPS_NEVER能力,那麼就表示裝置不支援alpha測試。
    • 紋理融合狀态

      程式可以控制用來進行紋理融合的方式。使用紋理句柄的程式通過調用IDirect3DDevice3::SetRenderState方法來設定紋理融合狀态,同時要将D3DRENDERSTATE_TEXTUREMAPBLEND作為它的第一個參數,将D3DTEXTUREBLEND枚舉類型中的一個值作為第二個參數。

      使用紋理接口指針的程式,在與目前紋理設定相關的紋理stage中來設定紋理融合狀态。詳細内容見“多紋理融合”。

    • Culling狀态

      Direct3D渲染圖元時,會對圖元的表面進行Culling操作。HAL和MMX裝置的Culling模式可以使用D3DCULL枚舉類型進行設定。見D3DRENDERSTATE_CULLMODE。預設情況下,Direct3D把具有反時針頂點順序的方面Culling掉。

    下面程式中設定了Culling狀态,并将反面Culling掉。

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // an IDirect3DDevice3 interface.

    // Set the culling state.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CW);

  3. 深度緩沖狀态
  4.   深度緩沖是一種用來去除隐藏的線段和表面的方法。要了解有關概念,請看“什麼是深度緩沖”部分。預設情況下,Direct3D不使用深度緩沖。通過使用D3DZBUFFERTYPE中的一個成員來聲明一個新的狀态值,程式可以将深度緩沖更新為D3DRENDERSTATE_ZENABLE渲染狀态。

      如果程式需要阻止Direct3D寫深度緩沖,那麼可以使用D3DRENDERSTATE_ZWRITEENABLE枚舉值,調用IDirect3DDevice3::SetRenderState方法,并将第二個參數聲明為FALSE。

    下面的例子顯示了如何将深度緩沖狀态設定為z-buffering有效:

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // a Direct3DDevice3.

    // Enable z-buffering.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); 

    // D3DZB_TRUE is the same as TRUE

      程式也可以使用D3DCMPFUNC枚舉類型的成員來選擇Direct3D在執行深度緩沖時使用的比較函數,見D3DRENDERSTATE_ZFUNC。

      當兩個表面的深度值相同時,z偏移量(z-biasing)可以用來顯示位于一個表面前面的那面。使用這一技術可以得到不同的效果。比如我們要繪制牆上的陰影。這時,陰影和牆具有相同的深度值。如果程式想要将陰影顯示在牆上面,那麼就可以給陰影一個z-bias,使Direct3D能夠将它們正确的顯示出來(見D3DRENDERSTATE_ZBIAS)。

    • 平滑狀态
      D3DRENDERSTATE_MONOENABLE渲染狀态現在已經不再使用了。當程式使用一個ramp裝置時,ramp燈光會自動有效。
    • 子像素修正狀态
      D3DRENDERSTATE_SUBPIXEL渲染狀态不再使用,系統會忽略掉它。
    • 平面掩模(mask)狀态

      在顔色通道(color channel)上使用位掩模(bit mask)可以得到特殊的效果。例如,我們要得到一個具有強烈紅色閃光的場景,這時,我們可以對藍色和綠色通道進行遮蔽(掩模),使它們變暗,那麼紅色通道就相應的增強了,這樣就得到了我們所需要的場景。程式還可以控制這一效果的間斷性的關閉,進而産生閃爍感。

      調用IDirect3DDevice3::SetRenderState方法可以來設定平面掩模,同時要将第一個參數設定為D3DRENDERSTATE_PLANEMASK,第二個參數就是需要的平面掩模。

      注:軟體光栅不支援D3DRENDERSTATE_PLANEMASK渲染狀态,并且硬體驅動器也經常忽略這種渲染狀态。通過使用alpha融合可以使寫顔色緩沖器無效,同時要将D3DRENDERSTATE_SRCBLEND設定為D3DBLEND_ZERO,D3DRENDERSTATE_DESTBLEND設定為D3DBLEND_ONE。

    • 顔色碼(Color Keying)狀态

      通過設定顔色碼,可以使Direct3D将碼值代表的顔色處理為透明。當Direct3D将DDSD_CKSRCBLT标志建立的紋理應用于一個圖元時,所有符合顔色碼的圖元上的像素都将不被渲染。要注意的是,不是由DDSD_CKSRCBLT标志建立的紋理不會顯示出顔色碼的效果。

      使用IDirectDrawSurface4::SetColorKey方法來設定顔色碼。我們可以通過IDirect3DDevice3::SetRenderState方法來對顔色碼進行開/關切換。要将第一個參數設定為D3DRENDERSTATE_COLORKEYENABLE。如果程式将第二個參數設定為TRUE,那麼顔色碼有效,設定為FALSE則無效,預設時為FALSE。

    // This code fragment assumes that lpD3DDevice3 is a valid pointer to

    // a Direct3DDevice3.

    // Disable color keying.

    lpD3DDevice3->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, FALSE);

  5. 渲染指令批處理狀态
  6.   預設情況下,在一個場景中對IDirect3DDevice2::DrawPrimitive和IDirect3DDevice2::DrawIndexedPrimitive的調用是成批處理的。也就是說,它們被配置設定在同一緩沖區内,并且經過一次調用一起傳遞給Direct3D裝置驅動器。場景中渲染狀态的變化也被置于同一緩沖區中。當緩沖區被充滿時,或者當引用了IDirect3DDevice2::EndScene方法時,緩沖區的内容被傳遞給裝置驅動器。這一技術可以用來提高性能。

      但是,如果程式改變的是場景而不是場景的渲染狀态,那麼這些變化有可能會出現次序上的颠倒。例如,如果在IDirect3DDevice2::DrawPrimitive或IDirect3DDevice2::DrawIndexedPrimitive調用之間,一個紋理的内容被替換了,那麼兩種情況下的圖元都可能使用新的紋理來繪制。要解決這一問題,程式可以在場景變化之前将批處理緩沖區進行重新整理。

      調用IDirect3DDevice2::SetRenderState方法可以将批處理緩沖區重新整理,同時要将D3DRENDERSTATE_FLUSHBATCH作為第一個參數,第二個參數應該是0。

      注:這一渲染狀态值對使用紋理句柄(使用IDirect3DDevice2接口)的程式有效。當使用IDirect3DDevice3接口進行渲染時(也包括使用執行緩沖時),使用批處理的圖元被隐含的重新整理了。

    • 模闆緩沖狀态

  程式使用模闆緩沖來決定一個像素是否被寫到渲染目标表面。詳細内容見“模闆緩沖”部分。

  通過調用IDirect3DDevice3::SetRenderState方法可以決定模闆是否有效,同時要将D3DRENDERSTATE_STENCILENABLE作為第一個參數。第二個參數設定為TRUE或FALSE,決定它是否有效。

  調用IDirect3DDevice3::SetRenderState方法可以來設定一個比較函數,Direct3D用這個比較函數來執行模闆測試(stencil test)。同時要将第一個參數設定為D3DRENDERSTATE_STENCILFUNC,将D3DCMPFUNC枚舉類型的一個成員設定為第二個參數。

  模闆參考值(stencil reference value)使一個在模闆緩沖中模闆函數用來進行測試的值。預設時,模闆參考值為0。程式可以用IDirect3DDevice3::SetRenderState對它進行設定。将D3DRENDERSTATE_STENCILREF作為第一個參數,将新的參考值作為第二個參數。

  Direct3D對每個像素執行模闆測試之前,它會對模闆參考值和模闆掩模值進行一個逐位的AND運算。得到的結果再用模闆比較函數與模闆緩沖的内容進行比較。程式可以設定模闆掩模。使用IDirect3DDevice3::SetRenderState方法,并将第一個參數設定為D3DRENDERSTATE_STENCILMASK,将第二個參數設定為新的模闆掩模。

  為了設定模闆測試失敗時Direct3D采取的行動,可以引用IDirect3DDevice3::SetRenderState方法,并将第一個參數設定為D3DRENDERSTATE_STENCILFAIL,第二個參數必須是D3DSTENCILOP枚舉類型的一個成員。

  程式還可以設定當模闆測試通過而z-buffer測試失敗時Direct3D的響應。這時可以調用IDirect3DDevice3::SetRenderState方法,并将D3DRENDERSTATE_STENCILZFAIL作為第一個參數,将一個D3DSTENCILOP枚舉類型的成員作為第二個參數。

  另外,程式也可以設定當模闆測試和z-buffer測試都通過時的Direct3D的響應。我們可以使用IDirect3DDevice3::SetRenderState方法,将D3DRENDERSTATE_STENCILPASS作為第一個參數,将一個D3DSTENCILOP枚舉類型的成員作為第二個參數。

上一篇: d3d基礎入門