It is for Windows/DirectX9/HAL-device type/FullScreen only.
With example that i have provided at the end of the post,
press 'R' to switch resolutions, press 'alt-tab' to jump out of app
and again to return to test device "recovery".
Some of code is copied from irrlicht "RT" as it is specific to
"alt-tabbing", and "room" uses shader from "shaders" example.
From DX help, something like "as of DX9 shaders doesn't need to be
released propertly before calling IDirect3DDevice9::Reset()"
so i put it as a test also.
This isn't tested thruoutly, so it might contain terrible bugs
and some things might be done better but as i am a noob i am
open for suggestions if you have any.
This is tested on WinXPSP2, MSVC++2005 Express,
DX SDK (June 2006) and Irrlicht 1.3.1 (not SVN).
Following things i have change for this in irrlicht source code,
open ../include/IrrCompileConfig.h and comment following
(some of them are already commented but i'll list them,
note: might work with some of them but i didnt need them):
Code: Select all
//#define _IRR_COMPILE_WITH_DIRECT3D_8_
//#define _IRR_COMPILE_WITH_OPENGL_
//#define _IRR_COMPILE_WITH_BURNINGSVIDEO_
//#define _IRR_COMPILE_WITH_X11_
//#define _IRR_LINUX_X11_RANDR_
//#define _IRR_COMPILE_WITH_ZLIB_
//#define _IRR_USE_NON_SYSTEM_ZLIB_
//#define _IRR_COMPILE_WITH_LIBPNG_
//#define _IRR_USE_NON_SYSTEM_LIB_PNG_
//#define BURNINGVIDEO_RENDERER_BEAUTIFUL
//#define BURNINGVIDEO_RENDERER_FAST
//#define BURNINGVIDEO_RENDERER_ULTRA_FAST
//#define IRRLICHT_FAST_MATHCode: Select all
virtual void SetResolutionAndFSAA(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newRes, u16 newFSAA = 0) = 0;Code: Select all
virtual void ResetDevice(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newResolution, u16 newFSAA) = 0;Code: Select all
virtual void ResetDevice(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newResolution, u16 newFSAA);Code: Select all
void CNullDriver::ResetDevice(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newResolution, u16 newFSAA)
{
// do nothing
}Code: Select all
virtual void ResetDevice(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newResolution, u16 newFSAA);Code: Select all
void CD3D9Driver::ResetDevice(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newResolution, u16 newFSAA)
{
HRESULT hr = NULL;
if(DeviceLost)
{
Sleep(100);
hr = pID3DDevice->TestCooperativeLevel();
if(hr != D3DERR_DEVICENOTRESET)
return;
}
DWORD qualityLevel = NULL;
D3DMULTISAMPLE_TYPE AAtype[15] =
{
D3DMULTISAMPLE_2_SAMPLES,
D3DMULTISAMPLE_3_SAMPLES,
D3DMULTISAMPLE_4_SAMPLES,
D3DMULTISAMPLE_5_SAMPLES,
D3DMULTISAMPLE_6_SAMPLES,
D3DMULTISAMPLE_7_SAMPLES,
D3DMULTISAMPLE_8_SAMPLES,
D3DMULTISAMPLE_9_SAMPLES,
D3DMULTISAMPLE_10_SAMPLES,
D3DMULTISAMPLE_11_SAMPLES,
D3DMULTISAMPLE_12_SAMPLES,
D3DMULTISAMPLE_13_SAMPLES,
D3DMULTISAMPLE_14_SAMPLES,
D3DMULTISAMPLE_15_SAMPLES,
D3DMULTISAMPLE_16_SAMPLES
};
present.Windowed = FALSE;
present.BackBufferWidth = newResolution.Width;
present.BackBufferHeight = newResolution.Height;
if(newFSAA > 1 && newFSAA < 17)
{
hr = pID3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, present.BackBufferFormat, FALSE,
AAtype[newFSAA - 2], &qualityLevel);
if(hr = D3D_OK)
{
present.MultiSampleType = AAtype[newFSAA - 2];
present.MultiSampleQuality = qualityLevel - 1;
present.SwapEffect = D3DSWAPEFFECT_DISCARD;
}
}
else
{
present.MultiSampleType = D3DMULTISAMPLE_NONE;
present.MultiSampleQuality = NULL;
present.SwapEffect = D3DSWAPEFFECT_FLIP;
}
OnLostDeviceCallback();
hr = pID3DDevice->Reset(&present);
if(hr != D3D_OK)
{
os::Printer::log("Device Reset Failed!", ELL_WARNING);
DeviceLost = true;
return;
}
os::Printer::log("Device Reset Succesfull!", ELL_WARNING);
ResetRenderStates = true;
LastVertexType = (E_VERTEX_TYPE)-1;
setVertexShader(EVT_STANDARD);
setRenderStates3DMode();
setFog(FogColor, LinearFog, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);
setAmbientLight(AmbientLight);
OnResetDeviceCallback();
CNullDriver::OnResize(
core::dimension2d<s32>(present.BackBufferWidth, present.BackBufferHeight));
DeviceLost = false;
}Code: Select all
bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color)
{
CNullDriver::beginScene(backBuffer, zBuffer, color);
HRESULT hr;
if (!pID3DDevice)
return false;
if (DeviceLost)
{
return false;
}
DWORD flags = 0;
if (backBuffer)
flags |= D3DCLEAR_TARGET;
if (zBuffer)
flags |= D3DCLEAR_ZBUFFER;
if (StencilBuffer)
flags |= D3DCLEAR_STENCIL;
hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0);
if (FAILED(hr))
os::Printer::log("DIRECT3D9 clear failed.", ELL_WARNING);
hr = pID3DDevice->BeginScene();
if (FAILED(hr))
{
os::Printer::log("DIRECT3D9 begin scene failed.", ELL_WARNING);
return false;
}
DeviceLost = false;
return true;
}
...
void CD3D9Driver::OnResize(const core::dimension2d<s32>& size)
{
if (!pID3DDevice)
return;
DeviceLost = true;
}class CCursorControl and add public func. to it:
Code: Select all
void ResetCC(core::dimension2d<s32> newSize)
{
WindowSize.Width = newSize.Width;
WindowSize.Height = newSize.Height;
InvWindowSize.Width = 1.0f / newSize.Width;
InvWindowSize.Height = 1.0f / newSize.Height;
BorderX = 0;
BorderY = 0;
}Code: Select all
virtual void SetResolutionAndFSAA(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newRes, u16 newFSAA = 0);Code: Select all
void CIrrDeviceWin32::SetResolutionAndFSAA(
void (*OnLostDeviceCallback)(),
void (*OnResetDeviceCallback)(),
core::dimension2d<s32> newRes, u16 newFSAA)
{
getVideoDriver()->ResetDevice(
OnLostDeviceCallback,
OnResetDeviceCallback,
newRes, newFSAA);
getWin32CursorControl()->ResetCC(
core::dimension2d<s32>(newRes.Width, newRes.Height));
}
...
// delete content of this function:
void CIrrDeviceWin32::resizeIfNecessary()
{
}"Rebuild solution" instead "Build". Hopefully i didnt forgat some function
to list here but if you got stuck i'll try and help.
and here is the example (dont forget to copy newly created .dll into your
project/exe folder also):
main.cpp
Code: Select all
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
#define NULA 0
IrrlichtDevice* device = NULA;
video::IVideoDriver* driver = NULA;
scene::IBillboardSceneNode* bill = NULA;
video::ITexture* rtTexture = NULA;
static s32 index = NULA;
core::dimension2d<s32> screenRes[3] =
{
core::dimension2d<s32>(640, 480),
core::dimension2d<s32>(800, 600),
core::dimension2d<s32>(1024, 768)
};
void DestroyerFunc();
void RaiseDeadFunc();
class MyEventReceiver : public IEventReceiver
{
public:
bool OnEvent(SEvent event)
{
if(event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.Key == KEY_ESCAPE &&
!event.KeyInput.PressedDown)
{
device->closeDevice();
return true;
}
if(event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.Key == KEY_KEY_R &&
!event.KeyInput.PressedDown)
{
device->SetResolutionAndFSAA(
DestroyerFunc, RaiseDeadFunc,
screenRes[index]);
index++;
if(index > 2)
index = NULA;
return true;
}
return false;
}
};
class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:
virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
video::IVideoDriver* driver = services->getVideoDriver();
core::matrix4 invWorld = driver->getTransform(video::ETS_WORLD);
invWorld.makeInverse();
services->setVertexShaderConstant("mInvWorld", invWorld.pointer(), 16);
core::matrix4 worldViewProj;
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
worldViewProj *= driver->getTransform(video::ETS_VIEW);
worldViewProj *= driver->getTransform(video::ETS_WORLD);
services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
core::vector3df pos = bill->getPosition();
services->setVertexShaderConstant("mLightPos", reinterpret_cast<f32*>(&pos), 3);
video::SColorf col(0.4f, 0.4f, 0.4f, 1.0f);
services->setVertexShaderConstant("mLightColor", reinterpret_cast<f32*>(&col), 4);
core::matrix4 world = driver->getTransform(video::ETS_WORLD);
world = world.getTransposed();
services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
}
};
int main()
{
MyEventReceiver receiver;
SIrrlichtCreationParameters param;
param.AntiAlias = false;
param.Bits = 32;
param.DriverType = video::EDT_DIRECT3D9;
param.EventReceiver = &receiver;
param.Fullscreen = false;
param.HighPrecisionFPU = true;
param.Stencilbuffer = true;
param.Vsync = false;
param.WindowSize = screenRes[index];
device = createDeviceEx(param);
driver = device->getVideoDriver();
gui::IGUIEnvironment* guid = device->getGUIEnvironment();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIFont* font = guid->getFont("fontcourier.bmp");
gui::IGUIStaticText* text = guid->addStaticText(
L"", core::rect<s32>(30, 30, 350, 60),
true, false, 0, -1, true);
text->setOverrideColor(video::SColor(255, 96, NULA, NULA));
text->setOverrideFont(font);
text->setBackgroundColor(video::SColor(255, 128, 128, 128));
c8* shaderFileName = "d3d9.hlsl";
s32 shaderMaterial;
video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
MyShaderCallBack* mc = new MyShaderCallBack();
shaderMaterial = gpu->addHighLevelShaderMaterialFromFiles(
shaderFileName, "vertexMain", video::EVST_VS_1_1,
shaderFileName, "pixelMain", video::EPST_PS_2_0,
mc, video::EMT_SOLID);
mc->drop();
video::ITexture* texture = driver->getTexture("rockwall.bmp");
scene::IAnimatedMesh* room = smgr->getMesh("room.3ds");
smgr->getMeshManipulator()->makePlanarTextureMapping(room->getMesh(NULA), 0.003f);
scene::IAnimatedMeshSceneNode* aroom = smgr->addAnimatedMeshSceneNode(room);
aroom->setMaterialTexture(NULA, texture);
aroom->setMaterialType((video::E_MATERIAL_TYPE)shaderMaterial);
video::ITexture* billTexture = driver->getTexture("particlered.bmp");
bill = smgr->addBillboardSceneNode();
bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setMaterialTexture(0, billTexture);
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
scene::ISceneNodeAnimator* rotAnim = smgr->createFlyCircleAnimator(
core::vector3df(0.0f, 200.0f, 0.0f), 100.0f, 0.001f, core::vector3df(0.0f, 1.0f, 0.0f));
bill->addAnimator(rotAnim);
rotAnim->drop();
scene::IAnimatedMesh* fairy = smgr->getMesh("faerie.md2");
scene::IAnimatedMeshSceneNode* afairy = smgr->addAnimatedMeshSceneNode(fairy);
afairy->setMaterialFlag(video::EMF_LIGHTING, false);
afairy->setMaterialTexture(0, driver->getTexture("faerie2.bmp"));
afairy->setPosition(core::vector3df(0.0f, 150.0f, 30.0f));
RaiseDeadFunc();
scene::ISceneNode* test = smgr->addCubeSceneNode(40.0f);
test->setPosition(core::vector3df(-100.f, 150.f, 50.0f));
test->setMaterialFlag(video::EMF_LIGHTING, false);
test->setMaterialTexture(0, rtTexture);
scene::ICameraSceneNode* fpsCam = smgr->addCameraSceneNodeFPS();
fpsCam->setPosition(core::vector3df(0.0f, 190.0f, -100.0f));
fpsCam->setTarget(core::vector3df(0.0f, 150.0f, 1.0f));
scene::ICameraSceneNode* fixedCam = smgr->addCameraSceneNode(
0, core::vector3df(30.0f, 170.0f, 0.0f),
core::vector3df(afairy->getPosition()));
video::SColor bsClearColor = video::SColor(NULA);
video::SColor rtClearColor = video::SColor(NULA);
while(device->run())
{
if(driver->beginScene(true, true, bsClearColor))
{
if(rtTexture)
{
driver->setRenderTarget(rtTexture, true, true, rtClearColor);
test->setVisible(false);
smgr->setActiveCamera(fixedCam);
smgr->drawAll();
driver->setRenderTarget(0);
test->setVisible(true);
smgr->setActiveCamera(fpsCam);
}
smgr->drawAll();
guid->drawAll();
core::stringw str;
str += L"FPS[";
str += driver->getFPS();
str += L"]";
str += L" Resolution: ";
str += driver->getScreenSize().Width;
str += L"x";
str += driver->getScreenSize().Height;
text->setText(str.c_str());
driver->endScene();
}
else
{
device->SetResolutionAndFSAA(
DestroyerFunc, RaiseDeadFunc, screenRes[index]);
}
}
DestroyerFunc();
device->drop();
return 0;
}
void DestroyerFunc()
{
device->getLogger()->log("OnLostDeviceCallback() Called!", ELL_WARNING);
if(rtTexture)
{
driver->removeTexture(rtTexture);
rtTexture->drop();
rtTexture = NULA;
}
}
void RaiseDeadFunc()
{
device->getLogger()->log("OnResetDeviceCallback() Called!", ELL_WARNING);
rtTexture = driver->createRenderTargetTexture(
core::dimension2d<s32>(128, 128));
}For the end i would like to point few problematic things (that i know of for now
and/or/will fix):
1. Camera target resets to (0, 0, 0) when alt-tabbing. (maybie save cam target pos
just befor device reset)
2. My card only supports max 4x AA so i could not try others.
3. I'v read somewhere that RT and AA doesnt fit together.
4. Could add changing screen refresh rate too.
If you have comments/corrections/addons i would like to hear them.
Hope you find this usefull. Enjoy!
Belfegor.