基本上就是SAMPLE里面DOT3PRODUCT的缩水版
直接上代码吧,原理很简单,只需要在多重纹理阶段设置成
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
就OK了,不需要手动计算纹理空间。目前还没发将多张纹理混合在一起。在慢慢尝试下
/*************************************************************
*
* ◢█████◣ ◢██████◣
* ◢◤ ◥◣ ◢◤ ◥◣
* ◤ ◥◣ ◢◤ █
* ▎ ◢█◣ ◥◣◢◤ ◢█◣ █
* ◣ ◢◤ ◥◣ ◢◣ ◥◣ ◢
* ◥██◤ ◢◤ ◥◣ ◥█◤
* █ ● ● █
* █ 〃 ▄ 〃 █
* ◥◣ ╚╩╝ ◢◤
* ◥█▅▃▃ ▃▃▅█◤
* ◢◤ ◥◣
* █ █
* ◢◤▕ ▎◥◣
* ▕▃◣◢▅▅▅◣◢▃▎
*
* \brief
* \author wangxu (email:wangxu627@gmail.com)
* \date 2012.1.5
* \details
*
************************************************************/
#include "DXUT.h"
#include "DXUTmisc.h"
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
D3DXMATRIX g_World;
D3DXMATRIX g_View;
D3DXMATRIX g_Projection;
LPDIRECT3DTEXTURE9 m_pFileBasedNormalMap;
LPDIRECT3DTEXTURE9 g_pColorMap;
D3DXVECTOR3 m_vLight;
IDirect3DVertexBuffer9* g_pVB;
struct CUSTOMVERTEX
{
D3DXVECTOR3 vPos;
DWORD diffuse;
// DWORD specular;
D3DXVECTOR2 vTex;
static const DWORD FVF;
};
const DWORD CUSTOMVERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE /*| D3DFVF_SPECULAR */| D3DFVF_TEX1;
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,
bool bWindowed,void* pUserContext );
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, CONST D3DSURFACE_DESC* pBufferSurfaceDesc,
void* pUserContext );
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );
void CALLBACK OnD3D9DestroyDevice( void* pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext );
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void CALLBACK OnMouse( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down,
bool bSideButton2Down, INT nMouseWheelDelta, INT xPos, INT yPos, void* pUserContext);
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
//-----------------------------------------------------------------------------
// Name: VectortoRGBA()
// Desc: Turns a normalized vector into RGBA form. Used to encode vectors into
// a height map.
//-----------------------------------------------------------------------------
DWORD VectortoRGBA( const D3DXVECTOR3* v, FLOAT fHeight )
{
DWORD r = (DWORD)( 127.0f * v->x + 128.0f );
DWORD g = (DWORD)( 127.0f * v->y + 128.0f );
DWORD b = (DWORD)( 127.0f * v->z + 128.0f );
DWORD a = (DWORD)( 255.0f * fHeight );
return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
}
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
// DXUT will create and use the best device (either D3D9 or D3D10)
// that is available system depending on which D3D callbacks set below
// Set DXUT callbacks
DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackKeyboard( OnKeyboard );
DXUTSetCallbackMouse( OnMouse ,true );
DXUTSetCallbackFrameMove( OnFrameMove );
DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
DXUTCreateWindow( L"DirectX9Plus -- wangxu" );
DXUTCreateDevice( true, 640, 480 );
DXUTMainLoop(); // Enter into the DXUT render loop
return DXUTGetExitCode();
}
//--------------------------------------------------------------------------------------
// Reject any D3D9 devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,
bool bWindowed,void* pUserContext )
{
return true;
}
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that aren't dependant on the back buffer
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, CONST D3DSURFACE_DESC* pBufferSurfaceDesc,
void* pUserContext )
{
HRESULT hr = S_OK;
D3DXVECTOR3 v(1,1,1);
D3DXVec3Normalize( &v, &v );
pd3dDevice->CreateVertexBuffer(4 * sizeof(CUSTOMVERTEX),D3DUSAGE_WRITEONLY,CUSTOMVERTEX::FVF,D3DPOOL_MANAGED,
&g_pVB,NULL);
CUSTOMVERTEX* pVData;
g_pVB->Lock(0,0,(void**)&pVData,0);
pVData[0].vPos = D3DXVECTOR3(-1.0f,-1.0f,-1.0f);
// pVData[0].specular = 0x40400000;
pVData[0].diffuse = VectortoRGBA( &v, 1.0f );
pVData[0].vTex = D3DXVECTOR2( 0.0f, 0.0f);
pVData[1].vPos = D3DXVECTOR3( 1.0f,-1.0f,-1.0f);
// pVData[1].specular = 0x40400000;
pVData[1].diffuse = VectortoRGBA( &v, 1.0f );
pVData[1].vTex = D3DXVECTOR2( 1.0f, 0.0f);
pVData[2].vPos = D3DXVECTOR3(-1.0f, 1.0f,-1.0f);
// pVData[2].specular = 0x40400000;
pVData[2].diffuse = VectortoRGBA( &v, 1.0f );
pVData[2].vTex = D3DXVECTOR2( 0.0f, 1.0f);
pVData[3].vPos = D3DXVECTOR3( 1.0f, 1.0f,-1.0f);
// pVData[3].specular = 0x40400000;
pVData[3].diffuse = VectortoRGBA( &v, 1.0f );
pVData[3].vTex = D3DXVECTOR2( 1.0f, 1.0f);
g_pVB->Unlock();
m_vLight = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
D3DXCreateTextureFromFile(pd3dDevice,L"..\\Green.png",&g_pColorMap);
D3DXCreateTextureFromFile(pd3dDevice,L"..\\Demo-normal.jpg",&m_pFileBasedNormalMap);
// Initialize the world matrices
D3DXMatrixIdentity( &g_World );
// Initialize the view matrix
D3DXVECTOR3 Eye( 0.0f, 0.0f, 2.0f );
D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );
D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up );
// Update Variables that never change
D3DXMatrixPerspectiveFovLH(&g_Projection,D3DX_PI/4,640.0f/480.0f,1,100);
pd3dDevice->SetTransform(D3DTS_WORLD,&g_World);
pd3dDevice->SetTransform(D3DTS_VIEW,&g_View);
pd3dDevice->SetTransform(D3DTS_PROJECTION,&g_Projection);
pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
// pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
return S_OK;
}
//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000,1.0f, 0);
pd3dDevice->BeginScene();
DWORD dwFactor = VectortoRGBA( &m_vLight, 0.0f );
pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, dwFactor );
// Modulate the texture (the normal map) with the light vector (stored
// above in the texture factor)
// 多重纹理咋个整??
// pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
// // pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
// pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
//
// pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
// pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_TEXTURE );
// pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
//
// pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_CURRENT );
// pd3dDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
// pd3dDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_TFACTOR );
//
// pd3dDevice->SetTexture(0, g_pColorMap);
// pd3dDevice->SetTexture( 1, m_pFileBasedNormalMap );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
pd3dDevice->SetTexture(0,m_pFileBasedNormalMap);
pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
pd3dDevice->SetFVF( CUSTOMVERTEX::FVF );
pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0 ,2 );
pd3dDevice->EndScene();
pd3dDevice->Present(NULL,NULL,NULL,NULL);
}
//--------------------------------------------------------------------------------------
// Release D3D9 resources created in OnD3D9CreateDevice
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
}
//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D10 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
return true;
}
//--------------------------------------------------------------------------------------
// Handle updates to the scene. This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
if( GetFocus() )
{
POINT pt;
GetCursorPos( &pt );
ScreenToClient( DXUTGetHWND(), &pt );
m_vLight.x = -( ( ( 2.0f * pt.x ) / 640 ) - 1 );
m_vLight.y = -( ( ( 2.0f * pt.y ) / 480 ) - 1 );
m_vLight.z = 0.0f;
if( D3DXVec3Length( &m_vLight ) > 1.0f )
{
D3DXVec3Normalize( &m_vLight, &m_vLight );
}
else
{
m_vLight.z = sqrtf( 1.0f - m_vLight.x*m_vLight.x - m_vLight.y*m_vLight.y );
}
// D3DXVec3Normalize( &m_vLight, &m_vLight );
}
}
//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
void* pUserContext )
{
return 0;
}
//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
if( bKeyDown )
{
switch( nChar )
{
case VK_ESCAPE: // Change as needed
DXUTShutdown(0);
break;
}
}
}
//--------------------------------------------------------------------------------------
// Handle mouse
//--------------------------------------------------------------------------------------
void CALLBACK OnMouse( bool bLeftButtonDown, bool bRightButtonDown, bool bMiddleButtonDown, bool bSideButton1Down,
bool bSideButton2Down, INT nMouseWheelDelta, INT xPos, INT yPos, void* pUserContext)
{
}