昨天在写shadowMap的时候,渲染其中一辆绿色的轿车的时候,总是渲染不对,要么全白,要么全黑,白思不得其解,原来材质颜色需要搭配光照来能显现出来,如果关闭了光照渲染功能将成白色,如果打开光照渲染功能却没有灯光将成黑色.当然贴图就没这个问题,没开灯光渲染功能的话会以贴图原来的样子显示
为了今出类似的情况,写篇博文,以防今后遇到类似问题.
/*------------------------------------------------------------ ShadowMap.cpp -- achieve shadow map (c) Seamanj.2014/4/22 ------------------------------------------------------------*/ //phase1 : add scene(floor and pillars bonded together: .x file) //phase2 : add camera //phase3 : add car #include "DXUT.h" #include "resource.h" #define phase1 1 #define phase2 1 #define phase3 1 #if phase1 #include "SDKmesh.h" // CDXUTXFileMesh要用 CDXUTXFileMesh g_Scene; D3DVERTEXELEMENT9 g_aVertDecl[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }, { 0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; #endif #if phase2 #include "DXUTcamera.h" //CModelViewerCamera g_Camera; CFirstPersonCamera g_Camera; #endif #if phase3 CDXUTXFileMesh g_Car; D3DMATERIAL9 InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p) { D3DMATERIAL9 mtrl; mtrl.Ambient = a; mtrl.Diffuse = d; mtrl.Specular = s; mtrl.Emissive = e; mtrl.Power = p; return mtrl; } const D3DXCOLOR GREEN( D3DCOLOR_XRGB( 0, 255, 0) ); const D3DXCOLOR BLACK( D3DCOLOR_XRGB( 0, 0, 0) ); const D3DMATERIAL9 GREEN_MTRL = InitMtrl(GREEN, GREEN, GREEN, BLACK, 2.0f); #endif #if phase1 //-------------------------------------------------------------------------------------- // Load mesh from file and convert vertices to our format //-------------------------------------------------------------------------------------- HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, LPCWSTR wszName, CDXUTXFileMesh& Mesh ) { HRESULT hr; if( FAILED( hr = Mesh.Create( pd3dDevice, wszName ) ) ) return hr; hr = Mesh.SetVertexDecl( pd3dDevice, g_aVertDecl ); return hr; } #endif //-------------------------------------------------------------------------------------- // Rejects any D3D9 devices that aren't acceptable to the app by returning false //-------------------------------------------------------------------------------------- bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed, void* pUserContext ) { // Typically want to skip back buffer formats that don't support alpha blending IDirect3D9* pD3D = DXUTGetD3D9Object(); 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, void* pUserContext ) { #if phase2 pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; #endif return true; } //-------------------------------------------------------------------------------------- // Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED) // and aren't tied to the back buffer size //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { #if phase1 // Load the scene object if( FAILED( LoadMesh( pd3dDevice, L"BasicColumnScene.x", g_Scene ) ) ) return DXUTERR_MEDIANOTFOUND; #endif #if phase2 // Setup the camera's view parameters D3DXVECTOR3 vecEye( 0.0f, 0.0f, -5.0f ); D3DXVECTOR3 vecAt ( 0.0f, 0.0f, 0.0f ); g_Camera.SetViewParams( &vecEye, &vecAt ); //FLOAT fObjectRadius=1; //摄像机缩放的3个参数 //g_Camera.SetRadius( fObjectRadius * 3.0f, fObjectRadius * 0.5f, fObjectRadius * 10.0f ); g_Camera.SetEnablePositionMovement( true ); #endif #if phase3 // Load the car if( FAILED( LoadMesh( pd3dDevice, L"car.x", g_Car ) ) ) return DXUTERR_MEDIANOTFOUND; #endif return S_OK; } //-------------------------------------------------------------------------------------- // Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT) // or that are tied to the back buffer size //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { #if phase2 pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); //关闭光照处理, 默认情况下启用光照处理 pd3dDevice->SetRenderState( D3DRS_LIGHTING, true ); //注意处理材质的时候把灯光计算开启,不然全白色,哎,又浪费我2个小时!!! //当然只开灯光计算不行,还得有灯光,不然全黑色 D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Ambient = (const D3DXCOLOR)D3DCOLOR_XRGB(255, 255, 255) * 0.6f; light.Diffuse =(const D3DXCOLOR) D3DCOLOR_XRGB(255, 255, 255); light.Specular = (const D3DXCOLOR)D3DCOLOR_XRGB(255, 255, 255) * 0.6f; light.Direction = D3DXVECTOR3(1.0f, -0.0f, 0.25f); pd3dDevice->SetLight(0, &light); pd3dDevice->LightEnable(0, true); //Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams( D3DX_PI / 2, fAspectRatio, 0.1f, 5000.0f ); //g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); //g_Camera.SetButtonMasks( MOUSE_LEFT_BUTTON, MOUSE_WHEEL, MOUSE_RIGHT_BUTTON ); g_Camera.SetScalers(0.01f, 5.0f); #endif return S_OK; } //-------------------------------------------------------------------------------------- // 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 phase2 g_Camera.FrameMove( fElapsedTime ); #endif } //-------------------------------------------------------------------------------------- // Render the scene using the D3D9 device //-------------------------------------------------------------------------------------- void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ) { HRESULT hr; // Clear the render target and the zbuffer V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) ); // Render the scene if( SUCCEEDED( pd3dDevice->BeginScene() ) ) { #if phase2 // Set world matrix D3DXMATRIX M; D3DXMatrixIdentity( &M ); // M = identity matrix pd3dDevice->SetTransform(D3DTS_WORLD, &M) ; // Set view matrix D3DXMATRIX view = *g_Camera.GetViewMatrix() ; pd3dDevice->SetTransform(D3DTS_VIEW, &view) ; // Set projection matrix D3DXMATRIX proj = *g_Camera.GetProjMatrix() ; pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj) ; #endif #if phase1 pd3dDevice->SetRenderState( D3DRS_LIGHTING, false ); LPD3DXMESH pMeshObj; pMeshObj = g_Scene.GetMesh(); // Iterate through each subset and render with its texture for( DWORD m = 0; m < g_Scene.m_dwNumMaterials; ++m ) { V( pd3dDevice->SetTexture(0, g_Scene.m_pTextures[m])); V( pMeshObj->DrawSubset( m ) ); } #endif #if phase3 D3DXMatrixIdentity( &M ); // M = identity matrix D3DXMatrixTranslation(&M, 0, 2.35f, 0); pd3dDevice->SetTransform(D3DTS_WORLD, &M) ; pd3dDevice->SetRenderState( D3DRS_LIGHTING, true ); pMeshObj = g_Car.GetMesh(); for( DWORD m = 0; m < g_Car.m_dwNumMaterials; ++m ) { pd3dDevice->SetMaterial(&g_Car.m_pMaterials[m]); if( g_Car.m_pTextures[m] ) V( pd3dDevice->SetTexture(0, g_Car.m_pTextures[m])); V( pMeshObj->DrawSubset( m ) ); } #endif V( pd3dDevice->EndScene() ); } } //-------------------------------------------------------------------------------------- // Handle messages to the application //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ) { #if phase2 g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); #endif return 0; } //-------------------------------------------------------------------------------------- // Release D3D9 resources created in the OnD3D9ResetDevice callback //-------------------------------------------------------------------------------------- void CALLBACK OnD3D9LostDevice( void* pUserContext ) { } //-------------------------------------------------------------------------------------- // Release D3D9 resources created in the OnD3D9CreateDevice callback //-------------------------------------------------------------------------------------- void CALLBACK OnD3D9DestroyDevice( void* pUserContext ) { #if phase1 g_Scene.Destroy(); #endif #if phase3 g_Car.Destroy(); #endif } //-------------------------------------------------------------------------------------- // Initialize everything and go into a render loop //-------------------------------------------------------------------------------------- INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, 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 DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable ); DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice ); DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice ); DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender ); DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice ); DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackFrameMove( OnFrameMove ); // TODO: Perform any application-level initialization here // Initialize DXUT and create the desired Win32 window and Direct3D device for the application DXUTInit( true, true ); // Parse the command line and show msgboxes DXUTSetHotkeyHandling( true, true, true ); // handle the default hotkeys DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen DXUTCreateWindow( L"3D_Shader_ShadowMap" ); DXUTCreateDevice( true, 1024, 768 ); // Start the render loop DXUTMainLoop(); // TODO: Perform any application-level cleanup here return DXUTGetExitCode(); }