EDIT: Also added screenshots.
Here's the code sample. You need two monitors. Move the windows around until the entities start displaying incorretly.
I'm using Ogre 1.9 compiled with Visual Studio 2013, sitting on nVidia 347.52 drivers.
TestProj.h
Code: Select all
#pragma once
#include <OgreRoot.h>
#include <OgreFrameListener.h>
class TestProj : public Ogre::FrameListener
{
protected:
Ogre::Root* mRoot;
Ogre::RenderWindow* mWindows[2];
Ogre::SceneManager* mSceneMgrs[2];
Ogre::Camera* mCameras[2];
HWND mHwnd;
public:
TestProj();
~TestProj();
TestProj(const TestProj&a) = delete;
TestProj& operator=(const TestProj&a) = delete;
bool go();
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
protected:
bool initOgre(void);
void createCameras(void);
void createScenes();
};
TestProj.cpp
Code: Select all
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#include "TestProj.h"
#include <Ogre.h>
HINSTANCE globInst;
TestProj::TestProj() : mRoot(NULL), mHwnd(NULL)
{
for (int i = 0; i < 2; i++)
{
mCameras[i] = NULL;
mSceneMgrs[i] = NULL;
mWindows[i] = NULL;
}
}
TestProj::~TestProj()
{
for (int i = 0; i < 2; i++)
{
if (mSceneMgrs[i])
mRoot->destroySceneManager(mSceneMgrs[i]);
if (mWindows[i])
mRoot->destroyRenderTarget(mWindows[i]);
}
if (mRoot)
delete mRoot;
}
bool TestProj::initOgre()
{
Ogre::String pluginCfg, resCfg;
#ifdef _DEBUG
pluginCfg = "plugins_d.cfg";
resCfg = "resources_d.cfg";
#else
pluginCfg = "plugins.cfg";
resCfg = "resources.cfg";
#endif
//1.Init Ogre root
mRoot = new Ogre::Root(pluginCfg);
//2.Parse & load config
Ogre::ConfigFile cfg;
cfg.load(resCfg);
Ogre::ConfigFile::SectionIterator seci = cfg.getSectionIterator();
Ogre::String secName, typeName, archName;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
archName, typeName, secName);
}
}
//3.Init render system
Ogre::RenderSystem* rs = mRoot->getRenderSystemByName("Direct3D9 Rendering Subsystem");
if (!rs)
return false;
rs->setConfigOption("Full Screen", "No");
rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit colour");
rs->setConfigOption("Multi device memory hint", "Auto hardware buffers management");
rs->setConfigOption("Resource Creation Policy", "Create on all devices");
mRoot->setRenderSystem(rs);
return true;
}
bool TestProj::go()
{
if (!initOgre())
return false;
//Create windows
mWindows[0] = mRoot->initialise(true, "Window 1");
mWindows[0]->setDeactivateOnFocusChange(false);
Ogre::NameValuePairList opt;
opt["left"] = std::to_string(2000);
opt["top"] = std::to_string(200);
mWindows[1] = Ogre::Root::getSingleton().createRenderWindow("test", 800, 600, false, &opt);
mWindows[1]->setDeactivateOnFocusChange(false);
//Init resources
// Set default mipmap level (note: some APIs ignore this)
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
//Create scenes
for (int i = 0; i < 2; i++)
{
mSceneMgrs[i] = mRoot->createSceneManager(Ogre::ST_GENERIC);
}
createCameras();
createScenes();
//run
mRoot->addFrameListener(this);
mRoot->startRendering();
return true;
}
bool TestProj::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
if (mWindows[0]->isClosed() || mWindows[1]->isClosed())
return false;
return true;
}
void TestProj::createCameras(void)
{
for (int i = 0; i < 2; i++)
{
mCameras[i] = mSceneMgrs[i]->createCamera("PlayerCam");
// Position it at 500 in Z direction
mCameras[i]->setPosition(Ogre::Vector3(0, 0, 80));
// Look back along -Z
mCameras[i]->lookAt(Ogre::Vector3(0, 0, -300));
mCameras[i]->setNearClipDistance(0.01f);
Ogre::Viewport* vp = mWindows[i]->addViewport(mCameras[i]);
vp->setBackgroundColour(Ogre::ColourValue(0, 0, 0));
vp->setOverlaysEnabled(false);
// Alter the camera aspect ratio to match the viewport
mCameras[i]->setAspectRatio(
Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));
}
}
void TestProj::createScenes()
{
//create two identical scenes
for (int i = 0; i < 2; i++)
{
Ogre::SceneNode * rootNode;
rootNode = mSceneMgrs[i]->getRootSceneNode();
mSceneMgrs[i]->setAmbientLight(Ogre::ColourValue(0.1f, 0.1f, 0.1f));
Ogre::Light* dirLight;
dirLight = mSceneMgrs[i]->createLight();
dirLight->setType(Ogre::Light::LightTypes::LT_DIRECTIONAL);
dirLight->setDirection(Ogre::Vector3(0.8f, -0.7f, 0.1f));
dirLight->setDiffuseColour(Ogre::ColourValue(0.7f, 0.7f, 0.7f));
rootNode->createChildSceneNode()->attachObject(dirLight);
Ogre::Entity * head;
Ogre::SceneNode* headNode;
head = mSceneMgrs[i]->createEntity("ogrehead.mesh");
head->setMaterialName("BaseWhite");
head->setRenderQueueGroup(Ogre::RENDER_QUEUE_MAIN);
headNode = rootNode->createChildSceneNode();
headNode->attachObject(head);
headNode->setPosition(Ogre::Vector3(-20.0f, 0.0f, 0.0f));
}
//add a program shaded entity to one of the scenes
Ogre::Entity * penguin;
Ogre::SceneNode * penguinNode;
penguin = mSceneMgrs[1]->createEntity("penguin", "penguin.mesh");
penguin->setRenderQueueGroup(Ogre::RENDER_QUEUE_6);
penguin->setMaterialName("SimpleShader");
penguinNode = mSceneMgrs[1]->getRootSceneNode()->createChildSceneNode();
penguinNode->attachObject(penguin);
penguinNode->setPosition(Ogre::Vector3(30.0f, 0.0f, 0.0f));
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
int main(int argc, char *argv[])
#endif
{
globInst = hInst;
// Create application object
TestProj app;
try {
app.go();
}
catch (Ogre::Exception& e) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
I could submit a patch, but would like someone to at least reproduce this
The plan would be to:
1. Keep vertexProgramBound and fragmentProgramBound per device
2. Override isGpuProgramBound in OgreD3D9RenderSystem to query the active device
3. Rewrite all references to mVertexProgramBound and mFragmentProgramBound in OgreD3D9RenderSystem to also query the device (this is the tricky part)