// restore re-activates the display device // bool Display::restore() { bool rc = false; if (d3dd) { HRESULT hr; hr = d3dd->TestCooperativeLevel(); if (hr == D3DERR_DEVICENOTRESET) // reset the display device rc = d3dd->Reset(&d3dpp) == D3D_OK; else if (hr == S_OK) rc = true; } if (rc) { // reacquire sprite manager references to video memory if (scrManager) scrManager->OnResetDevice(); } // complete the restoration if (rc) { setupProjection(); setupLighting(); setupBlending(); } return rc; }
bool PrimitiveMaterialD3D::execute() { DisplayDeviceD3D * pDeviceD3D = (DisplayDeviceD3D *)m_pDevice; if (! pDeviceD3D ) return false; LPDIRECT3DDEVICE9 pD3DD = pDeviceD3D->m_pD3DD; if (! pD3DD ) return false; // disable culling if doubleSided flag is true, enable CCW culling if false if ( pD3DD->SetRenderState( D3DRS_CULLMODE, m_DoubleSided ? D3DCULL_NONE : D3DCULL_CCW ) != D3D_OK) return false; setupBlending(); if ( m_nPass == DisplayDevice::PRIMARY ) { // write enabled for primary render pass pD3DD->SetRenderState( D3DRS_ZWRITEENABLE, D3DZB_TRUE ); pD3DD->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); } else { // no write for secondary and background passes pD3DD->SetRenderState( D3DRS_ZWRITEENABLE, D3DZB_FALSE ); pD3DD->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); } DisplayDeviceD3D::LightMap & lights = pDeviceD3D->m_Lights; // we use fixed function if lighting if disabled.. if ( DisplayDevice::sm_bUseFixedFunction || !m_LightEnable || lights.size() == 0 || m_Blending == PrimitiveMaterial::ADDITIVE ) { pDeviceD3D->m_bUsingFixedFunction = true; // enable/disable lighting if ( pD3DD->SetRenderState( D3DRS_LIGHTING, m_LightEnable && lights.size() > 0 ) != D3D_OK ) return false; // enable/disable specular highlighting if ( pD3DD->SetRenderState( D3DRS_SPECULARENABLE, (m_LightEnable && m_SpecularPower > 0.0f && sm_bEnableSpecular) ? TRUE : FALSE ) != D3D_OK) return false; D3DMATERIAL9 d3dm; d3dm.Diffuse = makeD3DCOLORVALUE( m_Diffuse ); d3dm.Ambient = makeD3DCOLORVALUE( m_Ambient ); d3dm.Emissive = makeD3DCOLORVALUE( m_Emissive ); d3dm.Specular = makeD3DCOLORVALUE( m_Specular ); d3dm.Power = m_SpecularPower; // apply shader if one has been set manually, needed for the HDR bloom effects.. if ( m_pShader.valid() && m_pShader != pDeviceD3D->m_pDefaultShader ) m_pShader->apply( pDeviceD3D ); else pDeviceD3D->clearShaders(); // set the material properties if ( pD3DD->SetMaterial( &d3dm ) != D3D_OK ) return false; if (! setupTextureStatges() ) return false; if (! executeChildren() ) return false; } else { // turn off fixed function lighting.. if ( pD3DD->SetRenderState( D3DRS_LIGHTING, FALSE ) != D3D_OK ) return false; // update our pixel/vertex shaders if needed.. if ( m_bUpdateShaders || !m_pShader.valid() || m_pShader->released() ) { m_bUpdateShaders = false; m_pShader = NULL; if ( m_sShader.length() > 0 ) m_pShader = pDeviceD3D->getShader( m_sShader ); if (! m_pShader.valid() ) m_pShader = pDeviceD3D->m_pDefaultShader; } if ( !m_pShader.valid() || m_pShader->released() ) return false; pDeviceD3D->m_bUsingFixedFunction = false; pDeviceD3D->m_pMatShader = m_pShader; // setup shader constants for this material.. m_pShader->setConstant( "vMatAmbient", m_Ambient ); m_pShader->setConstant( "vMatDiffuse", m_Diffuse ); m_pShader->setConstant( "vMatEmissive", m_Emissive ); m_pShader->setConstant( "vMatSpecular", m_Specular ); m_pShader->setConstant( "fMatSpecularPower", m_SpecularPower ); // set global ambient light for the first lighting pass.. m_pShader->setConstant( "vGlobalAmbient", pDeviceD3D->m_cAmbientLight ); m_pShader->setConstant( "bEnableAmbient", true ); m_pShader->setConstant( "szShadowMap", pDeviceD3D->m_szShadowMap ); if (! setupTextureStatges() ) return false; DisplayDeviceD3D::ShadowPassList::iterator iShadowPass = pDeviceD3D->m_ShadowPassList.begin(); // set to alpha blending for the first pass... pD3DD->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE); pD3DD->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); pD3DD->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA); // we need to make a render pass for each light in the scene int nLightCount = 0; for( DisplayDeviceD3D::LightMap::iterator iLight = lights.begin(); iLight != lights.end(); ++iLight, ++nLightCount ) { if ( nLightCount >= sm_nMaxLights ) break; D3DLIGHT9 & light = iLight->second; m_pShader->setConstant( "nLightType", (int)light.Type ); if ( light.Type != D3DLIGHT_DIRECTIONAL ) m_pShader->setConstant( "vLightPosition", light.Position ); if ( light.Type != D3DLIGHT_POINT ) m_pShader->setConstant( "vLightDirection", light.Direction ); m_pShader->setConstant( "vLightDiffuse", light.Diffuse ); m_pShader->setConstant( "vLightSpecular", light.Specular ); m_pShader->setConstant( "vLightAmbient", light.Ambient ); if ( light.Type == D3DLIGHT_POINT ) { Vector3 vAttenation( light.Attenuation0, light.Attenuation1, light.Attenuation2 ); m_pShader->setConstant( "vAttenuation", vAttenation ); } if ( iShadowPass != pDeviceD3D->m_ShadowPassList.end() ) { DisplayDeviceD3D::ShadowPass & pass = *iShadowPass; // yes we have a shadow map.. m_pShader->setConstant( "bEnableShadowMap", true ); m_pShader->setConstant( "mLightView", pass.m_LightView ); m_pShader->setConstant( "mLightProj", pass.m_LightProj ); // put our shadow map into slot 7, reserved specially for shadow maps.. pD3DD->SetTexture( 7, pass.m_pShadowMap ); pD3DD->SetSamplerState( 7, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ); pD3DD->SetSamplerState( 7, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ); pD3DD->SetSamplerState( 7, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); // IMPORTANT: Turn off all filtering on the shadow map, the shader does the filtering.. pD3DD->SetSamplerState( 7, D3DSAMP_MINFILTER, D3DTEXF_POINT ); pD3DD->SetSamplerState( 7, D3DSAMP_MIPFILTER, D3DTEXF_POINT ); ++iShadowPass; } else m_pShader->setConstant( "bEnableShadowMap", false ); // apply the shader and upload all constants for rendering.. if (! m_pShader->apply( pDeviceD3D ) ) return false; // render geometry.. if (! executeChildren() ) return false; if ( nLightCount == 0 ) { // after the first light, switch to additive blending mode.. pD3DD->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA ); pD3DD->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE ); // disable ambient in the shader, so the colors don't accumulate per light.. m_pShader->setConstant( "bEnableAmbient", false ); } } } return true; }
// setup creates the display device according to the context // parameters and associates the device with the application window // (HWND)hwnd // bool Display::setup(void* hwnd) { bool rc = false; // store address of main application window this->hwnd = (HWND)hwnd; // set the D3D presentation parameters UINT adapter; D3DFORMAT d3dFormat; ZeroMemory(&d3dpp, sizeof d3dpp); d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferCount = 1; d3dpp.EnableAutoDepthStencil = TRUE; D3DDISPLAYMODE d3ddm; if (!runInWindow) { D3DFORMAT Format[] = D3D_DOC_FORMATS; d3dFormat = Format[pixel]; if (FAILED(d3d->EnumAdapterModes(display, d3dFormat, mode, &d3ddm))) { error(L"Display::10 Failed to get selected display mode"); error(L"Display::11 Defaulting to windowed mode"); runInWindow = true; } else { adapter = display; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.FullScreen_RefreshRateInHz = d3ddm.RefreshRate; width = d3ddm.Width; height = d3ddm.Height; } } if (runInWindow) { adapter = D3DADAPTER_DEFAULT; d3d->GetAdapterDisplayMode(adapter, &d3ddm); d3dFormat = d3ddm.Format; d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = WND_WIDTH; d3dpp.BackBufferHeight = WND_HEIGHT; d3dpp.BackBufferFormat = d3dFormat; width = WND_WIDTH; height = WND_HEIGHT; } aspect = (float) width / height; context->set(GF_FR_ASP, aspect); // find the best format for depth buffering and stenciling // D3DDEVTYPE devtype; if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D32; // depth buffer devtype = D3DDEVTYPE_HAL; // HAL device } else if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // depth buffer devtype = D3DDEVTYPE_HAL; // HAL Device } // if the above attempts fail, use the REF (software emulation) device // with a 32-bit depth buffer rather than the HAL (hardware accelerated) // device else if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_REF, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D32; // depth buffer devtype = D3DDEVTYPE_REF; // REF Device } // if all else fails, use the REF (software emulation) with a 16-bit // depth buffer, hoping that it will work. (If it doesn't, we are out // of luck anyway.) else { d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // depth buffer devtype = D3DDEVTYPE_REF; // REF Device } // extract the device capabilities and configure the limits D3DCAPS9 caps; d3d->GetDeviceCaps(adapter, devtype, &caps); // hardware or software vertex processing? DWORD behaviorFlags; if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0) behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; else behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; // retrieve the Interface to the D3D display device if (d3dd) error(L"Display::11 Pointer to Direct3D interface is not NULL"); else if (FAILED(d3d->CreateDevice(adapter, devtype, (HWND)hwnd, behaviorFlags, &d3dpp, &d3dd))) error(L"Display::12 Failed to create Direct3D device"); else { // maximum number of lights supported by the display device maxLights = caps.MaxActiveLights ? caps.MaxActiveLights : MAX_ACTIVE_LIGHTS; // set anisotropic filtering to the maximum available on the device if (FAILED(d3dd->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, caps.MaxAnisotropy - 1))) error(L"Display::17 Failed to set up anisotropic filtering"); // create a sprite COM object to manage the drawing of the hud texture // and the drawing of the text item fonts if (!scrManager && FAILED(D3DXCreateSprite(d3dd, &scrManager))) error(L"Display::18 Failed to create the sprite manager"); // setup successful APILight::connectsThrough(d3dd); d3dd->AddRef(); APITexture::connectsThrough(d3dd); d3dd->AddRef(); APIGraphic::connectsThrough(d3dd); d3dd->AddRef(); APIText::connectsThrough(d3dd); d3dd->AddRef(); APITexture::isManagedBy(scrManager); scrManager->AddRef(); APIText::isManagedBy(scrManager); scrManager->AddRef(); APITexture::hasClientArea(width, height); APIText::hasClientArea(width, height); rc = true; } // complete the setup if (rc) { setupProjection(); setupLighting(); setupBlending(); } return rc; }
// setup creates the display device according to the context // parameters and associates the device with the application window // (HWND)hwnd // bool Display::setup(void* hwnd) { bool rc = false; // store address of main application window this->hwnd = (HWND)hwnd; // set the D3D presentation parameters UINT adapter; D3DFORMAT d3dFormat; ZeroMemory(&d3dpp, sizeof d3dpp); d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferCount = 1; d3dpp.EnableAutoDepthStencil = TRUE; D3DDISPLAYMODE d3ddm; if (!runInWindow) { D3DFORMAT Format[] = D3D_DOC_FORMATS; d3dFormat = Format[pixel]; if (FAILED(d3d->EnumAdapterModes(display, d3dFormat, mode, &d3ddm))) { error(L"Display::10 Failed to get selected display mode"); error(L"Display::11 Defaulting to windowed mode"); runInWindow = true; } else { adapter = display; d3dpp.BackBufferWidth = d3ddm.Width; d3dpp.BackBufferHeight = d3ddm.Height; d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.FullScreen_RefreshRateInHz = d3ddm.RefreshRate; width_ = d3ddm.Width; height_ = d3ddm.Height; } } if (runInWindow) { adapter = D3DADAPTER_DEFAULT; d3d->GetAdapterDisplayMode(adapter, &d3ddm); d3dFormat = d3ddm.Format; d3dpp.Windowed = TRUE; d3dpp.BackBufferWidth = WND_WIDTH; d3dpp.BackBufferHeight = WND_HEIGHT; d3dpp.BackBufferFormat = d3dFormat; width_ = WND_WIDTH; height_ = WND_HEIGHT; } aspect = (float) width_ / height_; // find the best format for depth buffering and stenciling // D3DDEVTYPE devtype; if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D32; // depth buffer devtype = D3DDEVTYPE_HAL; // HAL device } else if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_HAL, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // depth buffer devtype = D3DDEVTYPE_HAL; // HAL Device } // if the above attempts fail, use the REF (software emulation) device // with a 32-bit depth buffer rather than the HAL (hardware accelerated) // device else if (D3D_OK == d3d->CheckDeviceFormat(adapter, D3DDEVTYPE_REF, d3dFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32)) { d3dpp.AutoDepthStencilFormat = D3DFMT_D32; // depth buffer devtype = D3DDEVTYPE_REF; // REF Device } // if all else fails, use the REF (software emulation) with a 16-bit // depth buffer, hoping that it will work. (If it doesn't, we are out // of luck anyway.) else { d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // depth buffer devtype = D3DDEVTYPE_REF; // REF Device } // extract the device capabilities and configure the limits D3DCAPS9 caps; d3d->GetDeviceCaps(adapter, devtype, &caps); DWORD behaviorFlags; // hardware or software vertex processing? if ((caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || caps.VertexShaderVersion < D3DVS_VERSION(1,1)) behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; else behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; // retrieve the Interface to the D3D display device if (d3dd) error(L"Display::11 Pointer to Direct3D interface is not NULL"); else if (FAILED(d3d->CreateDevice(adapter, devtype, (HWND)hwnd, behaviorFlags, &d3dpp, &d3dd))) error(L"Display::12 Failed to create Direct3D device"); else { // maximum number of lights supported by the display device maxLights = caps.MaxActiveLights ? caps.MaxActiveLights : 8; // set anisotropic filtering to the maximum available on the device if (FAILED(d3dd->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, caps.MaxAnisotropy - 1))) error(L"Display::13 Failed to set up anisotropic filtering"); // create a sprite COM object to manage the drawing of the hud texture // and the drawing of the text item fonts if (!spriteManager_ && FAILED(D3DXCreateSprite(d3dd, &spriteManager_))) error(L"Display::14 Failed to create the font manager"); // setup successful rc = true; } //setup fog if (caps.RasterCaps & D3DPRASTERCAPS_FOGRANGE) { //configure fog distances and thickness float fogStart = FOGSTART_DEFAULT; float fogEnd = FOGEND_DEFAULT; //enable fog d3dd->SetRenderState(D3DRS_FOGENABLE,TRUE); //enable ranged base fog d3dd->SetRenderState(D3DRS_RANGEFOGENABLE,TRUE); //configure fog color d3dd->SetRenderState(D3DRS_FOGCOLOR,FOGCOLOR_DEFAULT); //set fog to be vertex fog using linear fog formula d3dd->SetRenderState(D3DRS_FOGVERTEXMODE,D3DFOG_LINEAR); //set fog distances and thickness d3dd->SetRenderState(D3DRS_FOGSTART,*(DWORD*)(&fogStart)); d3dd->SetRenderState(D3DRS_FOGEND,*(DWORD*)(&fogEnd)); } // complete the setup if (rc) { setupProjection(); setupLighting(); setupBlending(); } return rc; }