以文本方式查看主题

-  计算机科学论坛  (http://bbs.xml.org.cn/index.asp)
--  『 C/C++编程思想 』  (http://bbs.xml.org.cn/list.asp?boardid=61)
----  高级纹理映射技术(3)  (http://bbs.xml.org.cn/dispbbs.asp?boardid=61&rootid=&id=70238)


--  作者:卷积内核
--  发布时间:12/8/2008 3:24:00 PM

--  高级纹理映射技术(3)
对一些特殊的应用需要对纹理坐标进行处理,主要包括纹理坐标自动生成和纹理坐标变换。下图显示了纹理坐标的来源、处理过程以及到达光栅处理器的过程。

按此在新窗口浏览图片

纹理坐标自动生成

在Direct3D程序中,不仅可以在模型载入阶段或渲染阶段指定物体的纹理坐标,还可以通过Direct3D渲染引擎自动生成纹理坐标,用于诸如环境映射等特殊的视觉效果。与手动设置纹理坐标相比,纹理坐标自动生成在Direct3D坐标变换和光照流水线中完成,执行速度更快。

Direct3D系统可以使用经过变换的摄像机空间顶点位置坐标、法线信息来生成纹理坐标。如果使用纹理坐标自动生成,那么在顶点中就可以不用包含纹理坐标数据,从而可以降低图形渲染时的数据传输量。纹理坐标自动生成主要用于产生一些特殊效果,在大多数情况下还是手工为每个顶点指定纹理坐标。

通过调用SetTextureStageState()并将第二个参数设置为D3DTSS_TEXCOORDINDEX来控制Direct3D系统如何自动生成纹理坐标。

D3DTSS_TEXCOORDINDEX
Index of the texture coordinate set to use with this texture stage. You can specify up to eight sets of texture coordinates per vertex. If a vertex does not include a set of texture coordinates at the specified index, the system defaults to the u and v coordinates (0,0).
When rendering using vertex shaders, each stage's texture coordinate index must be set to its default value. The default index for each stage is equal to the stage index. Set this state to the zero-based index of the coordinate set for each vertex that this texture stage uses.

Additionally, applications can include, as logical OR with the index being set, one of the constants to request that Direct3D automatically generate the input texture coordinates for a texture transformation. For a list of all the constants, see D3DTSS_TCI.

With the exception of D3DTSS_TCI_PASSTHRU, which resolves to zero, if any of the following values is included with the index being set, the system uses the index strictly to determine texture wrapping mode. These flags are most useful when performing environment mapping.

其中第三个参数可以设为下列列表中的成员:

D3DTSS_TCI
Driver texture coordinate capability flags.

#define Value Description
D3DTSS_TCI_PASSTHRU 0x00000000L Use the specified texture coordinates contained within the vertex format. This value resolves to zero.
D3DTSS_TCI_CAMERASPACENORMAL 0x00010000L Use the vertex normal, transformed to camera space, as the input texture coordinates for this stage's texture transformation.
D3DTSS_TCI_CAMERASPACEPOSITION 0x00020000L Use the vertex position, transformed to camera space, as the input texture coordinates for this stage's texture transformation.
D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR 0x00030000L Use the reflection vector, transformed to camera space, as the input texture coordinate for this stage's texture transformation. The reflection vector is computed from the input vertex position and normal vector.
D3DTSS_TCI_SPHEREMAP 0x00040000L Use the specified texture coordinates for sphere mapping.

These constants are used by D3DTSS_TEXCOORDINDEX.

D3DTSS_TEXCOORDINDEX用于指定特定纹理层使用顶点中的第几组纹理坐标,但如果指定了上表中的成员值,Direct3D将忽略顶点中的纹理坐标,转而使用自动生成的纹理坐标。

D3DTSS_TEXTURETRANSFORMFLAGS用来控制生成的纹理坐标的输出,在大多数情况下纹理坐标是二维的,即将D3DTSS_TEXTURETRANSFORMFLAGS设置为D3DTTFF_COUNT2。但当绘制线段或三维纹理时,纹理坐标可能是一维或三维的。

D3DTSS_TEXTURETRANSFORMFLAGS
Member of the D3DTEXTURETRANSFORMFLAGS enumerated type that controls the transformation of texture coordinates for this texture stage. The default value is D3DTTFF_DISABLE.
输出的纹理坐标维数由枚举类型D3DTSS_TEXTURETRANSFORMFLAGS指定,其定义如下:

Defines texture coordinate transformation values.

typedef enum D3DTEXTURETRANSFORMFLAGS{    D3DTTFF_DISABLE = 0,    D3DTTFF_COUNT1 = 1,    D3DTTFF_COUNT2 = 2,    D3DTTFF_COUNT3 = 3,    D3DTTFF_COUNT4 = 4,    D3DTTFF_PROJECTED = 256,    D3DTTFF_FORCE_DWORD = 0x7fffffff,} D3DTEXTURETRANSFORMFLAGS, *LPD3DTEXTURETRANSFORMFLAGS;
Constants
D3DTTFF_DISABLE
Texture coordinates are passed directly to the rasterizer.
D3DTTFF_COUNT1
The rasterizer should expect 1D texture coordinates. This value is used by fixed function vertex processing; it should be set to 0 when using a programmable vertex shader.
D3DTTFF_COUNT2
The rasterizer should expect 2D texture coordinates. This value is used by fixed function vertex processing; it should be set to 0 when using a programmable vertex shader.
D3DTTFF_COUNT3
The rasterizer should expect 3D texture coordinates. This value is used by fixed function vertex processing; it should be set to 0 when using a programmable vertex shader.
D3DTTFF_COUNT4
The rasterizer should expect 4D texture coordinates. This value is used by fixed function vertex processing; it should be set to 0 when using a programmable vertex shader.
D3DTTFF_PROJECTED
This flag is honored by the fixed function pixel pipeline, as well as the programmable pixel pipeline in versions ps_1_1 to ps_1_3. When texture projection is enabled for a texture stage, all four floating point values must be written to the corresponding texture register. Each texture coordinate is divided by the last element before being passed to the rasterizer. For example, if this flag is specified with the D3DTTFF_COUNT3 flag, the first and second texture coordinates are divided by the third coordinate before being passed to the rasterizer.
D3DTTFF_FORCE_DWORD
Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.
Remarks
Texture coordinates can be transformed using a 4 x 4 matrix before the results are passed to the rasterizer. The texture coordinate transforms are set by calling IDirect3DDevice9::SetTextureStageState, and by passing in the D3DTSS_TEXTURETRANSFORMFLAGS texture stage state and one of the values from D3DTEXTURETRANSFORMFLAGS. For more information about texture transforms, see Texture Coordinate Transformations (Direct3D 9).

首先,我们定义顶点结构和格式:

struct sCustomVertex{ float x, y, z;};
#define D3DFVF_CUSTOM_VERTEX D3DFVF_XYZ
接着生成顶点数据,顶点数据中没有包含纹理坐标:

// create vertex buffer and fill data
sCustomVertex vertices[] =  {    { -1.0f, -1.0f,  0.0f},    { -1.0f,  1.0f,  0.0f},    {  1.0f, -1.0f,  0.0f},    {  1.0f,  1.0f,  0.0f}};
pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_MANAGED, &g_vertex_buffer, NULL);
void* ptr;g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);memcpy(ptr, vertices, sizeof(vertices));g_vertex_buffer->Unlock();
然后让Direct3D自动生成纹理坐标:

// create texture coordinate using vertex position in camera space
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);

运行效果:

按此在新窗口浏览图片

若设置D3DTSS_TEXCOORDINDEX为以下D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR,则效果为:

按此在新窗口浏览图片

若设置D3DTSS_TEXCOORDINDEX为以下D3DTSS_TCI_SPHEREMAP,则效果为:

按此在新窗口浏览图片


--  作者:卷积内核
--  发布时间:12/8/2008 3:25:00 PM

--  
主程序:


#include "dxstdafx.h"
#include "resource.h"

#pragma warning(disable : 4127 4995 4996)

#define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

#define IDC_TOGGLE_FULLSCREEN        1
#define IDC_TOGGLE_REF                2
#define IDC_CHANGE_DEVICE            3

struct sCustomVertex
{
    float x, y, z;
};

#define D3DFVF_CUSTOM_VERTEX    D3DFVF_XYZ

const D3DXCOLOR FONT_COLOR(0.55f, 0.85f, 0.65f, 1.0f);

CDXUTDialogResourceManager    g_dlg_resource_manager;
CD3DSettingsDlg                g_settings_dlg;
CDXUTDialog                    g_button_dlg;

IDirect3DVertexBuffer9*        g_vertex_buffer;
IDirect3DTexture9*            g_texture;

ID3DXFont*        g_font;
ID3DXSprite*    g_text_sprite;
bool            g_show_help;

//--------------------------------------------------------------------------------------
// Rejects any devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
                                  D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    // Typically want to skip backbuffer formats that don't support alpha blending

    IDirect3D9* pD3D = DXUTGetD3DObject();

    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat,
                    D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed.
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )
{
    // If video card does not support hardware vertex processing, then uses sofaware vertex processing.
    if((pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0)
        pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    static bool is_first_time = true;

    if(is_first_time)
    {
        is_first_time = false;

        // if using reference device, then pop a warning message box.
        if(pDeviceSettings->DeviceType == D3DDEVTYPE_REF)
            DXUTDisplaySwitchingToREFWarning();
    }

    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_MANAGED resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice,
                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                 void* pUserContext )
{
    HRESULT    hr;

    V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice));
    V_RETURN(g_settings_dlg.OnCreateDevice(pd3dDevice));

    D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                   DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_font);

    V_RETURN(D3DXCreateTextureFromFile(pd3dDevice, L"texture.jpg",    &g_texture));
    
    // create vertex buffer and fill data

    sCustomVertex vertices[] =     
    {
        { -1.0f, -1.0f,  0.0f},
        { -1.0f,  1.0f,  0.0f},
        {  1.0f, -1.0f,  0.0f},
        {  1.0f,  1.0f,  0.0f}
    };

    pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_MANAGED, &g_vertex_buffer, NULL);

    void* ptr;
    g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);
    memcpy(ptr, vertices, sizeof(vertices));
    g_vertex_buffer->Unlock();

    return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_DEFAULT resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                void* pUserContext )
{
    HRESULT hr;

    V_RETURN(g_dlg_resource_manager.OnResetDevice());
    V_RETURN(g_settings_dlg.OnResetDevice());
    V_RETURN(g_font->OnResetDevice());
    V_RETURN(D3DXCreateSprite(pd3dDevice, &g_text_sprite));

    // set dialog position and size

    g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0);
    g_button_dlg.SetSize(170, 170);

    // setup world matrix
    D3DXMATRIX mat_world;
    D3DXMatrixIdentity(&mat_world);
    pd3dDevice->SetTransform(D3DTS_WORLD, &mat_world);

    // setup view matrix

    D3DXMATRIX mat_view;
    D3DXVECTOR3 eye(0.0f, 0.0f, -3.0f);
    D3DXVECTOR3  at(0.0f, 0.0f,  0.0f);
    D3DXVECTOR3  up(0.0f, 1.0f,  0.0f);

    D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
    pd3dDevice->SetTransform(D3DTS_VIEW, &mat_view);

    // set projection matrix
    D3DXMATRIX mat_proj;
    float aspect = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
    D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, aspect, 1.0f, 100.0f);
    pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

    pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

    // set texture color blend method, disalbe alpha blend.

    pd3dDevice->SetTexture(0, g_texture);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1,        D3DTA_TEXTURE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,            D3DTOP_SELECTARG1);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,            D3DTOP_DISABLE);

    // create texture coordinate using vertex position in camera space
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX,            D3DTSS_TCI_CAMERASPACEPOSITION);
    //pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX,            D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
    //pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX,            D3DTSS_TCI_SPHEREMAP);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS,    D3DTTFF_COUNT2);

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Release resources created in the OnResetDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnLostDevice();
    g_settings_dlg.OnLostDevice();
    g_font->OnLostDevice();

    release_com(g_text_sprite);
}


//--------------------------------------------------------------------------------------
// Release resources created in the OnCreateDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnDestroyDevice();
    g_settings_dlg.OnDestroyDevice();    

    release_com(g_font);
    release_com(g_vertex_buffer);
    release_com(g_texture);
}

//--------------------------------------------------------------------------------------
// Handle updates to the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
}

//--------------------------------------------------------------------------------------
// Render the helper information
//--------------------------------------------------------------------------------------
void RenderText()
{
    CDXUTTextHelper text_helper(g_font, g_text_sprite, 20);
    
    text_helper.Begin();

    // show frame and device states
    text_helper.SetInsertionPos(5, 5);
    text_helper.SetForegroundColor(FONT_COLOR);
    text_helper.DrawTextLine( DXUTGetFrameStats(true) );
    text_helper.DrawTextLine( DXUTGetDeviceStats() );

    // show other simple information
    text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f) );
    text_helper.DrawTextLine(L"Texture Coordinate Automatic Generate");

    // show helper information
    
    const D3DSURFACE_DESC* surface_desc = DXUTGetBackBufferSurfaceDesc();

    if(g_show_help)
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 18 * 5);
        text_helper.SetForegroundColor(FONT_COLOR);
        text_helper.DrawTextLine(L"Controls (F1 to hide):");
        
        text_helper.SetInsertionPos(40, surface_desc->Height - 18 * 4);
        text_helper.DrawTextLine(L"Quit: ESC");
    }
    else
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 15 * 4);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f) );
        text_helper.DrawTextLine(L"Press F1 for help");
    }

    text_helper.End();
}

//--------------------------------------------------------------------------------------
// Render the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.OnRender(fElapsedTime);
        return;
    }

    // Clear the render target and the zbuffer
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
        pd3dDevice->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
        pd3dDevice->SetFVF(D3DFVF_CUSTOM_VERTEX);
        pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

        RenderText();

        V(g_button_dlg.OnRender(fElapsedTime));

        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
    *pbNoFurtherProcessing = g_dlg_resource_manager.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
        return 0;
    }

    *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle keybaord event
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboardProc(UINT charater, bool is_key_down, bool is_alt_down, void* user_context)
{
    if(is_key_down)
    {
        switch(charater)
        {
        case VK_F1:
            g_show_help = !g_show_help;
            break;
        }
    }
}

//--------------------------------------------------------------------------------------
// Handle events for controls
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent(UINT event, int control_id, CDXUTControl* control, void* user_context)
{
    switch(control_id)
    {
    case IDC_TOGGLE_FULLSCREEN:
        DXUTToggleFullScreen();
        break;

    case IDC_TOGGLE_REF:
        DXUTToggleREF();
        break;

    case IDC_CHANGE_DEVICE:
        g_settings_dlg.SetActive(true);
        break;
    }
}

//--------------------------------------------------------------------------------------
// Initialize dialogs
//--------------------------------------------------------------------------------------
void InitDialogs()
{
    g_settings_dlg.Init(&g_dlg_resource_manager);
    g_button_dlg.Init(&g_dlg_resource_manager);

    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);
    g_button_dlg.AddButton(IDC_TOGGLE_REF,          L"Toggle REF (F3)",     x, y += 24, width, height);
    g_button_dlg.AddButton(IDC_CHANGE_DEVICE,      L"Change device (F2)", x, y += 24, width, height, VK_F2);    
}

//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackKeyboard(OnKeyboardProc);
   
    // TODO: Perform any application-level initialization here
    InitDialogs();

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"Texture Color And Alpha Blend" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}

[B][URL=http://www.cppblog.com/Files/changingnow/TexCoordGenerate.rar]下载示例工程[/URL][/B]


--  作者:卷积内核
--  发布时间:12/8/2008 3:26:00 PM

--  
纹理坐标变换

Direct3D提供了对生成的纹理坐标进行坐标变换的功能,与顶点坐标变换相类似,可以指定一个4x4的纹理坐标变换矩阵,把它与生成的纹理坐标相乘,然后将变换之后的纹理坐标输出至Direct3D渲染流水线。使用纹理坐标变换可以对纹理坐标进行诸如平移、旋转和缩放等三维变换。纹理坐标变换对于生成一些特殊效果是非常有用的,它不用直接修改顶点的纹理坐标。例如可以通过一个简单的平移矩阵对纹理坐标进行变换,从而使物体表面上的纹理不断变换位置,产生动画效果。纹理坐标自动生成在三维图形程序中最广泛的应用是环境映射。

可通过函数IDirect3DDevice9::SetTransform()来设置4x4的纹理坐标变换矩阵,它以D3DTS_TEXTURE0~ D3DTS_TEXTURE7作为第一个参数,表示设置纹理层0~7的纹理矩阵。下列代码对纹理层0设置了一个将纹理坐标u、v缩小到原来一半的纹理矩阵:

D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
mat._11 = 0.5f;
mat._22 = 0.5f;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat);

下面的代码将原来的纹理坐标平移(1.0, 1.0, 0)个单位。

D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
mat._41 = 1.0f;
mat._42 = 1.0f;
mat._43 = 0.0f;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat);

示例程序通过下列代码对自动生成的纹理坐标进行变换:

// texture coordinate transform

D3DXMATRIX mat_texture, mat_scale, mat_trans;

D3DXMatrixIdentity(&mat_texture);
D3DXMatrixScaling(&mat_scale, 0.5f, -0.5f, 1.0f);
D3DXMatrixTranslation(&mat_trans, 0.5f, 0.5f, 1.0f);

mat_texture = mat_texture * mat_scale * mat_trans;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat_texture);

运行效果图:

按此在新窗口浏览图片

主程序:


#include "dxstdafx.h"
#include "resource.h"

#pragma warning(disable : 4127 4995 4996)

#define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

#define IDC_TOGGLE_FULLSCREEN        1
#define IDC_TOGGLE_REF                2
#define IDC_CHANGE_DEVICE            3

struct sCustomVertex
{
    float x, y, z;
    D3DCOLOR color;
};

#define D3DFVF_CUSTOM_VERTEX    (D3DFVF_XYZ | D3DFVF_DIFFUSE)

const D3DXCOLOR FONT_COLOR(1.0f, 0.5f, 0.25f, 1.0f);

CDXUTDialogResourceManager    g_dlg_resource_manager;
CD3DSettingsDlg                g_settings_dlg;
CDXUTDialog                    g_button_dlg;

IDirect3DVertexBuffer9*        g_vertex_buffer;
IDirect3DTexture9*            g_texture;

ID3DXFont*        g_font;
ID3DXSprite*    g_text_sprite;
bool            g_show_help;

//--------------------------------------------------------------------------------------
// Rejects any devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
                                  D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    // Typically want to skip backbuffer formats that don't support alpha blending

    IDirect3D9* pD3D = DXUTGetD3DObject();

    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat,
                    D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed.
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )
{
    // If video card does not support hardware vertex processing, then uses sofaware vertex processing.
    if((pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0)
        pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    static bool is_first_time = true;

    if(is_first_time)
    {
        is_first_time = false;

        // if using reference device, then pop a warning message box.
        if(pDeviceSettings->DeviceType == D3DDEVTYPE_REF)
            DXUTDisplaySwitchingToREFWarning();
    }

    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_MANAGED resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice,
                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                 void* pUserContext )
{
    HRESULT    hr;

    V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice));
    V_RETURN(g_settings_dlg.OnCreateDevice(pd3dDevice));

    D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                   DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_font);

    V_RETURN(D3DXCreateTextureFromFile(pd3dDevice, L"texture.jpg", &g_texture));
    
    // create vertex buffer and fill data

    sCustomVertex vertices[] =     
    {
        { -1.0f, -1.0f,  0.0f,  0xFFFFFFFF},
        { -1.0f,  1.0f,  0.0f,  0xFFFFFFFF},
        {  1.0f, -1.0f,  0.0f,  0xFFFFFFFF},
        {  1.0f,  1.0f,  0.0f,  0xFFFFFFFF}
    };

    pd3dDevice->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_MANAGED, &g_vertex_buffer, NULL);

    void* ptr;
    g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);
    memcpy(ptr, vertices, sizeof(vertices));
    g_vertex_buffer->Unlock();

    return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_DEFAULT resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                void* pUserContext )
{
    HRESULT hr;

    V_RETURN(g_dlg_resource_manager.OnResetDevice());
    V_RETURN(g_settings_dlg.OnResetDevice());
    V_RETURN(g_font->OnResetDevice());
    V_RETURN(D3DXCreateSprite(pd3dDevice, &g_text_sprite));

    // set dialog position and size

    g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0);
    g_button_dlg.SetSize(170, 170);

    // setup world matrix
    D3DXMATRIX mat_world;
    D3DXMatrixIdentity(&mat_world);
    pd3dDevice->SetTransform(D3DTS_WORLD, &mat_world);

    // setup view matrix

    D3DXMATRIX mat_view;
    D3DXVECTOR3 eye(0.0f, 0.0f, -3.0f);
    D3DXVECTOR3  at(0.0f, 0.0f,  0.0f);
    D3DXVECTOR3  up(0.0f, 1.0f,  0.0f);

    D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
    pd3dDevice->SetTransform(D3DTS_VIEW, &mat_view);

    // set projection matrix
    D3DXMATRIX mat_proj;
    float aspect = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
    D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, aspect, 1.0f, 100.0f);
    pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

    pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

    // set texture color blend method, disalbe alpha blend.

    pd3dDevice->SetTexture(0, g_texture);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1,        D3DTA_TEXTURE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2,        D3DTA_DIFFUSE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,            D3DTOP_MODULATE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,            D3DTOP_DISABLE);

    // create texture coordinate using vertex position in camera space
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX,            D3DTSS_TCI_CAMERASPACEPOSITION);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS,    D3DTTFF_COUNT2);

    // texture coordinate transform

    D3DXMATRIX mat_texture, mat_scale, mat_trans;

    D3DXMatrixIdentity(&mat_texture);
    D3DXMatrixScaling(&mat_scale, 0.5f, -0.5f, 1.0f);
    D3DXMatrixTranslation(&mat_trans, 0.5f, 0.5f, 1.0f);

    mat_texture = mat_texture * mat_scale * mat_trans;
    pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat_texture);

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Release resources created in the OnResetDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnLostDevice();
    g_settings_dlg.OnLostDevice();
    g_font->OnLostDevice();

    release_com(g_text_sprite);
}


//--------------------------------------------------------------------------------------
// Release resources created in the OnCreateDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnDestroyDevice();
    g_settings_dlg.OnDestroyDevice();    

    release_com(g_font);
    release_com(g_vertex_buffer);
    release_com(g_texture);
}

//--------------------------------------------------------------------------------------
// Handle updates to the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
}

//--------------------------------------------------------------------------------------
// Render the helper information
//--------------------------------------------------------------------------------------
void RenderText()
{
    CDXUTTextHelper text_helper(g_font, g_text_sprite, 20);
    
    text_helper.Begin();

    // show frame and device states
    text_helper.SetInsertionPos(5, 5);
    text_helper.SetForegroundColor(FONT_COLOR);
    text_helper.DrawTextLine( DXUTGetFrameStats(true) );
    text_helper.DrawTextLine( DXUTGetDeviceStats() );

    // show other simple information
    //text_helper.SetForegroundColor( D3DXCOLOR(0.2f, 0.5f, 0.8f, 1.0f) );
    //text_helper.DrawTextLine(L"Texture Coordinate Transform");

    // show helper information
    
    const D3DSURFACE_DESC* surface_desc = DXUTGetBackBufferSurfaceDesc();

    if(g_show_help)
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 18 * 5);
        text_helper.SetForegroundColor(FONT_COLOR);
        text_helper.DrawTextLine(L"Controls (F1 to hide):");
        
        text_helper.SetInsertionPos(40, surface_desc->Height - 18 * 4);
        text_helper.DrawTextLine(L"Quit: ESC");
    }
    else
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 15 * 4);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f) );
        text_helper.DrawTextLine(L"Press F1 for help");
    }

    text_helper.End();
}

//--------------------------------------------------------------------------------------
// Render the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.OnRender(fElapsedTime);
        return;
    }

    // Clear the render target and the zbuffer
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
        pd3dDevice->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
        pd3dDevice->SetFVF(D3DFVF_CUSTOM_VERTEX);
        pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

        RenderText();

        V(g_button_dlg.OnRender(fElapsedTime));

        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
    *pbNoFurtherProcessing = g_dlg_resource_manager.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
        return 0;
    }

    *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle keybaord event
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboardProc(UINT charater, bool is_key_down, bool is_alt_down, void* user_context)
{
    if(is_key_down)
    {
        switch(charater)
        {
        case VK_F1:
            g_show_help = !g_show_help;
            break;
        }
    }
}

//--------------------------------------------------------------------------------------
// Handle events for controls
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent(UINT event, int control_id, CDXUTControl* control, void* user_context)
{
    switch(control_id)
    {
    case IDC_TOGGLE_FULLSCREEN:
        DXUTToggleFullScreen();
        break;

    case IDC_TOGGLE_REF:
        DXUTToggleREF();
        break;

    case IDC_CHANGE_DEVICE:
        g_settings_dlg.SetActive(true);
        break;
    }
}

//--------------------------------------------------------------------------------------
// Initialize dialogs
//--------------------------------------------------------------------------------------
void InitDialogs()
{
    g_settings_dlg.Init(&g_dlg_resource_manager);
    g_button_dlg.Init(&g_dlg_resource_manager);

    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);
    g_button_dlg.AddButton(IDC_TOGGLE_REF,          L"Toggle REF (F3)",     x, y += 24, width, height);
    g_button_dlg.AddButton(IDC_CHANGE_DEVICE,      L"Change device (F2)", x, y += 24, width, height, VK_F2);    
}

//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackKeyboard(OnKeyboardProc);
   
    // TODO: Perform any application-level initialization here
    InitDialogs();

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"Texture Coordinate Transform" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}

[B][URL=http://www.cppblog.com/Files/changingnow/TexCoordTransform.rar]下载示例工程[/URL][/B]


--  作者:卷积内核
--  发布时间:12/8/2008 3:27:00 PM

--  
三维场景中的物体不仅受光照影响,而且受周围环境的影响,可以映射出周围环境的图像,环境映射就是模拟物体光滑表面映射周围环境的一种技术。实际上,就是将一幅包含物体周围环境场景的纹理贴到物体表面上,这样就可以在一定程度上模拟出物体对周围环境的映射,而无须使用像光线跟踪算法这种复杂的计算技术。

在图形工业中有多种环境映射,下面介绍两种最常用的环境映射:立方体环境映射和球形环境映射。

立方体环境映射

立方体环境映射图有时又称为立方体映射图,是一组包含物体周围环境图像的纹理贴图,好像物体在立方体的中心。立方体环境图的每个面覆盖水平和垂直方向上各90度视角区域,一共6个面,各面的方向如下图所示:

按此在新窗口浏览图片

立方体环境映射图的6个面布局如下图所示:

按此在新窗口浏览图片

球形环境映射

球形环境映射图(或称为球形映射图)和立方体环境映射图类似,也是一幅包含周围场景图像的特殊纹理。和立方体环境映射图不同的是,球形环境映射图不直接代表物体周围的环境。球形映射图就好像通过鱼眼(fish-eye)凸透镜观察到的景象一样,是一个物体周围环境360度全方位视域的三维表现。

首先使用一张球形的背景图作为环境映射纹理,如下所示:

按此在新窗口浏览图片

接着在回调函数OnCreateDevice()中加载纹理和网格模型:

V_RETURN(D3DXCreateTextureFromFile(pd3dDevice, L"spheremap.bmp", &g_env_texture)); 
ID3DXBuffer* material_buffer;
V_RETURN(D3DXLoadMeshFromXW(L"teapot.x", D3DXMESH_MANAGED, pd3dDevice, NULL, &material_buffer, NULL,        &g_num_materials, &g_mesh));
D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();g_mesh_materials = new D3DMATERIAL9[g_num_materials];
for(DWORD i = 0; i < g_num_materials; i++){ g_mesh_materials[i] = xmaterials[i].MatD3D;
 // .x file do not save ambient data, so set it here. g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse; }
material_buffer->Release();
该网格模型的视觉效果如下所示:

按此在新窗口浏览图片

接着在回调函数OnResetDevice()中自动生成纹理坐标,并设置纹理阶段颜色混合方法:

// set texture color blend method, disalbe alpha blend.

pd3dDevice->SetTexture(0, g_env_texture);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_SPHEREMAP);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);

最后在回调函数OnFrameRender()中渲染茶壶:

// Clear the render target and the zbuffer V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );
// Render the sceneif( SUCCEEDED( pd3dDevice->BeginScene() ) ){ for(DWORD i = 0; i < g_num_materials; i++) {  pd3dDevice->SetMaterial(&g_mesh_materials[i]);  g_mesh->DrawSubset(i); }
 RenderText();
 V(g_button_dlg.OnRender(fElapsedTime));
    V( pd3dDevice->EndScene() );}
运行效果图:

按此在新窗口浏览图片

球形环境纹理映射的实现比较简单,和普通纹理映射基本相同,唯一的区别是使用自动生成的球形纹理坐标。


--  作者:卷积内核
--  发布时间:12/8/2008 3:27:00 PM

--  
主程序:


#include "dxstdafx.h"
#include "resource.h"

#pragma warning(disable : 4127 4995 4996)

#define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

#define IDC_TOGGLE_FULLSCREEN        1
#define IDC_TOGGLE_REF                2
#define IDC_CHANGE_DEVICE            3

const D3DXCOLOR FONT_COLOR(1.0f, 0.5f, 0.25f, 1.0f);

ID3DXFont*                    g_font;
ID3DXSprite*                g_text_sprite;
bool                        g_show_help;

CDXUTDialogResourceManager    g_dlg_resource_manager;
CD3DSettingsDlg                g_settings_dlg;
CDXUTDialog                    g_button_dlg;

ID3DXMesh*                    g_mesh;
D3DMATERIAL9*                g_mesh_materials;
DWORD                        g_num_materials;
IDirect3DTexture9*            g_env_texture;

//--------------------------------------------------------------------------------------
// Rejects any devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat,
                                  D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{
    // Typically want to skip backbuffer formats that don't support alpha blending

    IDirect3D9* pD3D = DXUTGetD3DObject();

    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat,
                    D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed.
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps, void* pUserContext )
{
    // If video card does not support hardware vertex processing, then uses sofaware vertex processing.
    if((pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0)
        pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    static bool is_first_time = true;

    if(is_first_time)
    {
        is_first_time = false;

        // if using reference device, then pop a warning message box.
        if(pDeviceSettings->DeviceType == D3DDEVTYPE_REF)
            DXUTDisplaySwitchingToREFWarning();
    }

    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_MANAGED resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice,
                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                 void* pUserContext )
{
    HRESULT    hr;

    V_RETURN(g_dlg_resource_manager.OnCreateDevice(pd3dDevice));
    V_RETURN(g_settings_dlg.OnCreateDevice(pd3dDevice));

    D3DXCreateFont(pd3dDevice, 18, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
                   DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_font);

    V_RETURN(D3DXCreateTextureFromFile(pd3dDevice, L"spheremap.bmp", &g_env_texture));
    
    ID3DXBuffer* material_buffer;

    V_RETURN(D3DXLoadMeshFromXW(L"teapot.x", D3DXMESH_MANAGED, pd3dDevice, NULL, &material_buffer, NULL,
                                &g_num_materials, &g_mesh));

    D3DXMATERIAL* xmaterials = (D3DXMATERIAL*) material_buffer->GetBufferPointer();
    g_mesh_materials = new D3DMATERIAL9[g_num_materials];

    for(DWORD i = 0; i < g_num_materials; i++)
    {
        g_mesh_materials[i] = xmaterials[i].MatD3D;

        // .x file do not save ambient data, so set it here.
        g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse;
    }

    material_buffer->Release();

    return S_OK;
}


//--------------------------------------------------------------------------------------
// Create any D3DPOOL_DEFAULT resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
                                const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                void* pUserContext )
{
    HRESULT hr;

    V_RETURN(g_dlg_resource_manager.OnResetDevice());
    V_RETURN(g_settings_dlg.OnResetDevice());
    V_RETURN(g_font->OnResetDevice());
    V_RETURN(D3DXCreateSprite(pd3dDevice, &g_text_sprite));

    // set dialog position and size

    g_button_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, 0);
    g_button_dlg.SetSize(170, 170);

    // setup view matrix

    D3DXMATRIX mat_view;
    D3DXVECTOR3 eye(0.0f, 300.0f, 220.0f);
    D3DXVECTOR3  at(0.0f, 0.0f,  50.0f);
    D3DXVECTOR3  up(0.0f, 0.0f,  1.0f);

    D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
    pd3dDevice->SetTransform(D3DTS_VIEW, &mat_view);

    // set projection matrix
    D3DXMATRIX mat_proj;
    float aspect = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
    D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, aspect, 1.0f, 1000.0f);
    pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);

    // setup material

    D3DMATERIAL9 material;
    ZeroMemory(&material, sizeof(D3DMATERIAL9));

    material.Diffuse.r = material.Ambient.r = 1.0f;
    material.Diffuse.g = material.Ambient.g = 1.0f;
    material.Diffuse.b = material.Ambient.b = 1.0f;
    material.Diffuse.a = material.Ambient.a = 1.0f;

    pd3dDevice->SetMaterial(&material);

    // setup light

    D3DLIGHT9 light;
    ZeroMemory(&light, sizeof(D3DLIGHT9));

    light.Type       = D3DLIGHT_DIRECTIONAL;
    light.Diffuse.r  = 1.0f;
    light.Diffuse.g  = 1.0f;
    light.Diffuse.b  = 1.0f;
    light.Range      = 1000.0f;

    D3DXVECTOR3 light_dir(10.0f, -10.0f, -10.0f);        
    D3DXVec3Normalize((D3DXVECTOR3*) &light.Direction, &light_dir);
    
    pd3dDevice->SetLight(0, &light);
    pd3dDevice->LightEnable(0, TRUE);  

    pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00FF8080);

    // set texture color blend method, disalbe alpha blend.

    pd3dDevice->SetTexture(0, g_env_texture);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1,        D3DTA_TEXTURE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2,        D3DTA_DIFFUSE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,            D3DTOP_MODULATE);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,            D3DTOP_DISABLE);
    
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX,            D3DTSS_TCI_SPHEREMAP);    
    pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS,    D3DTTFF_COUNT2);

    return S_OK;
}

//--------------------------------------------------------------------------------------
// Release resources created in the OnResetDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnLostDevice();
    g_settings_dlg.OnLostDevice();
    g_font->OnLostDevice();

    release_com(g_text_sprite);
}


//--------------------------------------------------------------------------------------
// Release resources created in the OnCreateDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
    g_dlg_resource_manager.OnDestroyDevice();
    g_settings_dlg.OnDestroyDevice();    

    delete[] g_mesh_materials;
    g_mesh_materials = NULL;

    release_com(g_font);
    release_com(g_mesh);
    release_com(g_env_texture);
}

//--------------------------------------------------------------------------------------
// Handle updates to the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
}

//--------------------------------------------------------------------------------------
// Render the helper information
//--------------------------------------------------------------------------------------
void RenderText()
{
    CDXUTTextHelper text_helper(g_font, g_text_sprite, 20);
    
    text_helper.Begin();

    // show frame and device states
    text_helper.SetInsertionPos(5, 5);
    text_helper.SetForegroundColor(FONT_COLOR);
    text_helper.DrawTextLine( DXUTGetFrameStats(true) );
    text_helper.DrawTextLine( DXUTGetDeviceStats() );

    // show helper information
    
    const D3DSURFACE_DESC* surface_desc = DXUTGetBackBufferSurfaceDesc();

    if(g_show_help)
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 18 * 5);
        text_helper.SetForegroundColor(FONT_COLOR);
        text_helper.DrawTextLine(L"Controls (F1 to hide):");
        
        text_helper.SetInsertionPos(40, surface_desc->Height - 18 * 4);
        text_helper.DrawTextLine(L"Quit: ESC");
    }
    else
    {
        text_helper.SetInsertionPos(10, surface_desc->Height - 15 * 4);
        text_helper.SetForegroundColor( D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f) );
        text_helper.DrawTextLine(L"Press F1 for help");
    }

    text_helper.End();
}

//--------------------------------------------------------------------------------------
// Render the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.OnRender(fElapsedTime);
        return;
    }

    float time = timeGetTime() / 1000.0f;

    D3DXMATRIX mat_world;    
    D3DXMatrixRotationYawPitchRoll(&mat_world, time, time, time);
    pd3dDevice->SetTransform(D3DTS_WORLD, &mat_world);

    // Clear the render target and the zbuffer
    V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
        for(DWORD i = 0; i < g_num_materials; i++)
        {
            pd3dDevice->SetMaterial(&g_mesh_materials[i]);
            g_mesh->DrawSubset(i);
        }

        RenderText();

        V(g_button_dlg.OnRender(fElapsedTime));

        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
    *pbNoFurtherProcessing = g_dlg_resource_manager.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    if(g_settings_dlg.IsActive())
    {
        g_settings_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
        return 0;
    }

    *pbNoFurtherProcessing = g_button_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
    if(*pbNoFurtherProcessing)
        return 0;

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle keybaord event
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboardProc(UINT charater, bool is_key_down, bool is_alt_down, void* user_context)
{
    if(is_key_down)
    {
        switch(charater)
        {
        case VK_F1:
            g_show_help = !g_show_help;
            break;
        }
    }
}

//--------------------------------------------------------------------------------------
// Handle events for controls
//--------------------------------------------------------------------------------------
void CALLBACK OnGUIEvent(UINT event, int control_id, CDXUTControl* control, void* user_context)
{
    switch(control_id)
    {
    case IDC_TOGGLE_FULLSCREEN:
        DXUTToggleFullScreen();
        break;

    case IDC_TOGGLE_REF:
        DXUTToggleREF();
        break;

    case IDC_CHANGE_DEVICE:
        g_settings_dlg.SetActive(true);
        break;
    }
}

//--------------------------------------------------------------------------------------
// Initialize dialogs
//--------------------------------------------------------------------------------------
void InitDialogs()
{
    g_settings_dlg.Init(&g_dlg_resource_manager);
    g_button_dlg.Init(&g_dlg_resource_manager);

    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);
    g_button_dlg.AddButton(IDC_TOGGLE_REF,          L"Toggle REF (F3)",     x, y += 24, width, height);
    g_button_dlg.AddButton(IDC_CHANGE_DEVICE,      L"Change device (F2)", x, y += 24, width, height, VK_F2);    
}

//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackDeviceCreated( OnCreateDevice );
    DXUTSetCallbackDeviceReset( OnResetDevice );
    DXUTSetCallbackDeviceLost( OnLostDevice );
    DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameRender( OnFrameRender );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackKeyboard(OnKeyboardProc);
   
    // TODO: Perform any application-level initialization here
    InitDialogs();

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"Spherical Environment Mapping" );
    DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}

[B][URL=http://www.cppblog.com/Files/changingnow/SphericalEnvMapping.rar]下载示例工程[/URL][/B]


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