Added shader based MyGUI render manager to allow using Ogre's next generation render systems.

pull/16/head
scrawl 12 years ago
parent ec7a8f1add
commit 4daaa4030d

@ -44,6 +44,9 @@ set(MATERIAL_FILES
watersim_common.h
watersim.mat
watersim.shaderset
mygui.mat
mygui.shader
mygui.shaderset
)
copy_all_files(${CMAKE_CURRENT_SOURCE_DIR}/water "${OpenMW_BINARY_DIR}/resources/water/" "${WATER_FILES}")

@ -0,0 +1,25 @@
material MyGUI/NoTexture
{
pass
{
vertex_program mygui_vertex
fragment_program mygui_fragment
shader_properties
{
has_texture false
}
}
}
material MyGUI/OneTexture
{
pass
{
vertex_program mygui_vertex
fragment_program mygui_fragment
shader_properties
{
has_texture true
}
}
}

@ -0,0 +1,45 @@
#include "core.h"
#define TEXTURE @shPropertyBool(has_texture)
#ifdef SH_VERTEX_SHADER
SH_BEGIN_PROGRAM
#if TEXTURE
shVertexInput(float2, uv0)
shOutput(float2, UV)
#endif
shColourInput(float4)
shOutput(float4, colourPassthrough)
SH_START_PROGRAM
{
shOutputPosition = float4(shInputPosition.xyz, 1.f);
#if TEXTURE
UV.xy = uv0;
#endif
colourPassthrough = colour;
}
#else
SH_BEGIN_PROGRAM
#if TEXTURE
shSampler2D(diffuseMap)
shInput(float2, UV)
#endif
shInput(float4, colourPassthrough)
SH_START_PROGRAM
{
#if TEXTURE
shOutputColour(0) = shSample(diffuseMap, UV.xy) * colourPassthrough;
#else
shOutputColour(0) = colourPassthrough;
#endif
}
#endif

@ -0,0 +1,15 @@
shader_set mygui_vertex
{
source mygui.shader
type vertex
profiles_cg vs_2_0 vp40 arbvp1
profiles_hlsl vs_3_0 vs_2_0
}
shader_set mygui_fragment
{
source mygui.shader
type fragment
profiles_cg ps_3_0 ps_2_x ps_2_0 fp40 arbfp1
profiles_hlsl ps_3_0 ps_2_0
}

@ -2,11 +2,18 @@
#include <MyGUI_Gui.h>
#include <MyGUI_OgrePlatform.h>
#include <MyGUI_Timer.h>
#include <cassert>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgreMaterial.hpp>
using namespace OEngine::GUI;
namespace MyGUI
{
/*
* As of MyGUI 3.2.0, MyGUI::OgreDataManager::isDataExist is unnecessarily complex
* this override fixes the resulting performance issue.
@ -20,6 +27,532 @@ public:
}
};
/*
* As of MyGUI 3.2.0, rendering with shaders is not supported.
* We definitely need this though to run in GL3 core / DX11 at all.
* To make matters worse, subclassing OgreRenderManager doesn't seem to be possible here. :/
*/
class ShaderBasedRenderManager : public RenderManager,
public IRenderTarget,
public Ogre::WindowEventListener,
public Ogre::RenderQueueListener,
public Ogre::RenderSystem::Listener
{
// флаг для обновления всех и вся
bool mUpdate;
IntSize mViewSize;
Ogre::SceneManager* mSceneManager;
VertexColourType mVertexFormat;
// окно, на которое мы подписываемся для изменения размеров
Ogre::RenderWindow* mWindow;
// вьюпорт, с которым работает система
unsigned short mActiveViewport;
Ogre::RenderSystem* mRenderSystem;
Ogre::TextureUnitState::UVWAddressingMode mTextureAddressMode;
Ogre::LayerBlendModeEx mColorBlendMode, mAlphaBlendMode;
RenderTargetInfo mInfo;
typedef std::map<std::string, ITexture*> MapTexture;
MapTexture mTextures;
bool mIsInitialise;
bool mManualRender;
size_t mCountBatch;
// ADDED
Ogre::GpuProgram* mVertexProgramNoTexture;
Ogre::GpuProgram* mVertexProgramOneTexture;
Ogre::GpuProgram* mFragmentProgramNoTexture;
Ogre::GpuProgram* mFragmentProgramOneTexture;
public:
ShaderBasedRenderManager& getInstance()
{
return *getInstancePtr();
}
ShaderBasedRenderManager* getInstancePtr()
{
return static_cast<ShaderBasedRenderManager*>(RenderManager::getInstancePtr());
}
ShaderBasedRenderManager() :
mUpdate(false),
mSceneManager(nullptr),
mWindow(nullptr),
mActiveViewport(0),
mRenderSystem(nullptr),
mIsInitialise(false),
mManualRender(false),
mCountBatch(0)
{
}
void initialise(Ogre::RenderWindow* _window, Ogre::SceneManager* _scene)
{
MYGUI_PLATFORM_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
MYGUI_PLATFORM_LOG(Info, "* Initialise: " << getClassTypeName());
mColorBlendMode.blendType = Ogre::LBT_COLOUR;
mColorBlendMode.source1 = Ogre::LBS_TEXTURE;
mColorBlendMode.source2 = Ogre::LBS_DIFFUSE;
mColorBlendMode.operation = Ogre::LBX_MODULATE;
mAlphaBlendMode.blendType = Ogre::LBT_ALPHA;
mAlphaBlendMode.source1 = Ogre::LBS_TEXTURE;
mAlphaBlendMode.source2 = Ogre::LBS_DIFFUSE;
mAlphaBlendMode.operation = Ogre::LBX_MODULATE;
mTextureAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP;
mTextureAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP;
mTextureAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP;
mSceneManager = nullptr;
mWindow = nullptr;
mUpdate = false;
mRenderSystem = nullptr;
mActiveViewport = 0;
Ogre::Root* root = Ogre::Root::getSingletonPtr();
if (root != nullptr)
setRenderSystem(root->getRenderSystem());
setRenderWindow(_window);
setSceneManager(_scene);
// ADDED
sh::MaterialInstance* mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/NoTexture");
sh::Factory::getInstance()._ensureMaterial("MyGUI/NoTexture", "Default");
mVertexProgramNoTexture = static_cast<sh::OgreMaterial*>(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0)
->getVertexProgram()->_getBindingDelegate();
mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/OneTexture");
sh::Factory::getInstance()._ensureMaterial("MyGUI/OneTexture", "Default");
mVertexProgramOneTexture = static_cast<sh::OgreMaterial*>(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0)
->getVertexProgram()->_getBindingDelegate();
mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/NoTexture");
sh::Factory::getInstance()._ensureMaterial("MyGUI/NoTexture", "Default");
mFragmentProgramNoTexture = static_cast<sh::OgreMaterial*>(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0)
->getFragmentProgram()->_getBindingDelegate();
mat = sh::Factory::getInstance().getMaterialInstance("MyGUI/OneTexture");
sh::Factory::getInstance()._ensureMaterial("MyGUI/OneTexture", "Default");
mFragmentProgramOneTexture = static_cast<sh::OgreMaterial*>(mat->getMaterial())->getOgreTechniqueForConfiguration("Default")->getPass(0)
->getFragmentProgram()->_getBindingDelegate();
MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully initialized");
mIsInitialise = true;
}
void shutdown()
{
MYGUI_PLATFORM_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
MYGUI_PLATFORM_LOG(Info, "* Shutdown: " << getClassTypeName());
destroyAllResources();
setSceneManager(nullptr);
setRenderWindow(nullptr);
setRenderSystem(nullptr);
MYGUI_PLATFORM_LOG(Info, getClassTypeName() << " successfully shutdown");
mIsInitialise = false;
}
void setRenderSystem(Ogre::RenderSystem* _render)
{
// отписываемся
if (mRenderSystem != nullptr)
{
mRenderSystem->removeListener(this);
mRenderSystem = nullptr;
}
mRenderSystem = _render;
// подписываемся на рендер евент
if (mRenderSystem != nullptr)
{
mRenderSystem->addListener(this);
// формат цвета в вершинах
Ogre::VertexElementType vertex_type = mRenderSystem->getColourVertexElementType();
if (vertex_type == Ogre::VET_COLOUR_ARGB)
mVertexFormat = VertexColourType::ColourARGB;
else if (vertex_type == Ogre::VET_COLOUR_ABGR)
mVertexFormat = VertexColourType::ColourABGR;
updateRenderInfo();
}
}
Ogre::RenderSystem* getRenderSystem()
{
return mRenderSystem;
}
void setRenderWindow(Ogre::RenderWindow* _window)
{
// отписываемся
if (mWindow != nullptr)
{
Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
mWindow = nullptr;
}
mWindow = _window;
if (mWindow != nullptr)
{
Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
windowResized(mWindow);
}
}
void setSceneManager(Ogre::SceneManager* _scene)
{
if (nullptr != mSceneManager)
{
mSceneManager->removeRenderQueueListener(this);
mSceneManager = nullptr;
}
mSceneManager = _scene;
if (nullptr != mSceneManager)
{
mSceneManager->addRenderQueueListener(this);
}
}
void setActiveViewport(unsigned short _num)
{
mActiveViewport = _num;
if (mWindow != nullptr)
{
Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
// рассылка обновлений
windowResized(mWindow);
}
}
void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
{
Gui* gui = Gui::getInstancePtr();
if (gui == nullptr)
return;
if (Ogre::RENDER_QUEUE_OVERLAY != queueGroupId)
return;
Ogre::Viewport* viewport = mSceneManager->getCurrentViewport();
if (nullptr == viewport
|| !viewport->getOverlaysEnabled())
return;
if (mWindow->getNumViewports() <= mActiveViewport
|| viewport != mWindow->getViewport(mActiveViewport))
return;
mCountBatch = 0;
static Timer timer;
static unsigned long last_time = timer.getMilliseconds();
unsigned long now_time = timer.getMilliseconds();
unsigned long time = now_time - last_time;
onFrameEvent((float)((double)(time) / (double)1000));
last_time = now_time;
//begin();
setManualRender(true);
onRenderToTarget(this, mUpdate);
//end();
// сбрасываем флаг
mUpdate = false;
}
void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation)
{
}
void eventOccurred(const Ogre::String& eventName, const Ogre::NameValuePairList* parameters)
{
if (eventName == "DeviceLost")
{
}
else if (eventName == "DeviceRestored")
{
// обновить всех
mUpdate = true;
}
}
IVertexBuffer* createVertexBuffer()
{
return new OgreVertexBuffer();
}
void destroyVertexBuffer(IVertexBuffer* _buffer)
{
delete _buffer;
}
// для оповещений об изменении окна рендера
void windowResized(Ogre::RenderWindow* _window)
{
if (_window->getNumViewports() > mActiveViewport)
{
Ogre::Viewport* port = _window->getViewport(mActiveViewport);
#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
Ogre::OrientationMode orient = port->getOrientationMode();
if (orient == Ogre::OR_DEGREE_90 || orient == Ogre::OR_DEGREE_270)
mViewSize.set(port->getActualHeight(), port->getActualWidth());
else
mViewSize.set(port->getActualWidth(), port->getActualHeight());
#else
mViewSize.set(port->getActualWidth(), port->getActualHeight());
#endif
// обновить всех
mUpdate = true;
updateRenderInfo();
onResizeView(mViewSize);
}
}
void updateRenderInfo()
{
if (mRenderSystem != nullptr)
{
mInfo.maximumDepth = mRenderSystem->getMaximumDepthInputValue();
mInfo.hOffset = mRenderSystem->getHorizontalTexelOffset() / float(mViewSize.width);
mInfo.vOffset = mRenderSystem->getVerticalTexelOffset() / float(mViewSize.height);
mInfo.aspectCoef = float(mViewSize.height) / float(mViewSize.width);
mInfo.pixScaleX = 1.0f / float(mViewSize.width);
mInfo.pixScaleY = 1.0f / float(mViewSize.height);
}
}
void doRender(IVertexBuffer* _buffer, ITexture* _texture, size_t _count)
{
if (getManualRender())
{
begin();
setManualRender(false);
}
// ADDED
if (_texture)
{
Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mVertexProgramOneTexture);
Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mFragmentProgramOneTexture);
}
else
{
Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mVertexProgramNoTexture);
Ogre::Root::getSingleton().getRenderSystem()->bindGpuProgram(mFragmentProgramNoTexture);
}
if (_texture)
{
OgreTexture* texture = static_cast<OgreTexture*>(_texture);
Ogre::TexturePtr texture_ptr = texture->getOgreTexture();
if (!texture_ptr.isNull())
{
mRenderSystem->_setTexture(0, true, texture_ptr);
mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE);
}
}
OgreVertexBuffer* buffer = static_cast<OgreVertexBuffer*>(_buffer);
Ogre::RenderOperation* operation = buffer->getRenderOperation();
operation->vertexData->vertexCount = _count;
mRenderSystem->_render(*operation);
++ mCountBatch;
}
void begin()
{
// set-up matrices
mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
mRenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY);
#if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
Ogre::OrientationMode orient = mWindow->getViewport(mActiveViewport)->getOrientationMode();
mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY * Ogre::Quaternion(Ogre::Degree(orient * 90.f), Ogre::Vector3::UNIT_Z));
#else
mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
#endif
// initialise render settings
mRenderSystem->setLightingEnabled(false);
mRenderSystem->_setDepthBufferParams(false, false);
mRenderSystem->_setDepthBias(0, 0);
mRenderSystem->_setCullingMode(Ogre::CULL_NONE);
mRenderSystem->_setFog(Ogre::FOG_NONE);
mRenderSystem->_setColourBufferWriteEnabled(true, true, true, true);
mRenderSystem->unbindGpuProgram(Ogre::GPT_FRAGMENT_PROGRAM);
mRenderSystem->unbindGpuProgram(Ogre::GPT_VERTEX_PROGRAM);
mRenderSystem->setShadingType(Ogre::SO_GOURAUD);
// initialise texture settings
mRenderSystem->_setTextureCoordCalculation(0, Ogre::TEXCALC_NONE);
mRenderSystem->_setTextureCoordSet(0, 0);
mRenderSystem->_setTextureUnitFiltering(0, Ogre::FO_LINEAR, Ogre::FO_LINEAR, Ogre::FO_NONE);
mRenderSystem->_setTextureAddressingMode(0, mTextureAddressMode);
mRenderSystem->_setTextureMatrix(0, Ogre::Matrix4::IDENTITY);
#if OGRE_VERSION < MYGUI_DEFINE_VERSION(1, 6, 0)
mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0);
#else
mRenderSystem->_setAlphaRejectSettings(Ogre::CMPF_ALWAYS_PASS, 0, false);
#endif
mRenderSystem->_setTextureBlendMode(0, mColorBlendMode);
mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode);
mRenderSystem->_disableTextureUnitsFrom(1);
// enable alpha blending
mRenderSystem->_setSceneBlending(Ogre::SBF_SOURCE_ALPHA, Ogre::SBF_ONE_MINUS_SOURCE_ALPHA);
// always use wireframe
// TODO: add option to enable wireframe mode in platform
mRenderSystem->_setPolygonMode(Ogre::PM_SOLID);
}
void end()
{
}
ITexture* createTexture(const std::string& _name)
{
MapTexture::const_iterator item = mTextures.find(_name);
MYGUI_PLATFORM_ASSERT(item == mTextures.end(), "Texture '" << _name << "' already exist");
OgreTexture* texture = new OgreTexture(_name, OgreDataManager::getInstance().getGroup());
mTextures[_name] = texture;
return texture;
}
void destroyTexture(ITexture* _texture)
{
if (_texture == nullptr) return;
MapTexture::iterator item = mTextures.find(_texture->getName());
MYGUI_PLATFORM_ASSERT(item != mTextures.end(), "Texture '" << _texture->getName() << "' not found");
mTextures.erase(item);
delete _texture;
}
ITexture* getTexture(const std::string& _name)
{
MapTexture::const_iterator item = mTextures.find(_name);
if (item == mTextures.end())
{
Ogre::TexturePtr texture = (Ogre::TexturePtr)Ogre::TextureManager::getSingleton().getByName(_name);
if (!texture.isNull())
{
ITexture* result = createTexture(_name);
static_cast<OgreTexture*>(result)->setOgreTexture(texture);
return result;
}
return nullptr;
}
return item->second;
}
bool isFormatSupported(PixelFormat _format, TextureUsage _usage)
{
return Ogre::TextureManager::getSingleton().isFormatSupported(
Ogre::TEX_TYPE_2D,
OgreTexture::convertFormat(_format),
OgreTexture::convertUsage(_usage));
}
void destroyAllResources()
{
for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
{
delete item->second;
}
mTextures.clear();
}
#if MYGUI_DEBUG_MODE == 1
bool checkTexture(ITexture* _texture)
{
for (MapTexture::const_iterator item = mTextures.begin(); item != mTextures.end(); ++item)
{
if (item->second == _texture)
return true;
}
return false;
}
#endif
const IntSize& getViewSize() const
{
return mViewSize;
}
VertexColourType getVertexFormat()
{
return mVertexFormat;
}
const RenderTargetInfo& getInfo()
{
return mInfo;
}
size_t getActiveViewport()
{
return mActiveViewport;
}
Ogre::RenderWindow* getRenderWindow()
{
return mWindow;
}
bool getManualRender()
{
return mManualRender;
}
void setManualRender(bool _value)
{
mManualRender = _value;
}
size_t getBatchCount() const
{
return mCountBatch;
}
};
}
void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging, const std::string& logDir)
{
assert(wnd);
@ -41,8 +574,8 @@ void MyGUIManager::setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool
// Set up OGRE platform (bypassing OgrePlatform). We might make this more generic later.
mLogManager = new LogManager();
mRenderManager = new OgreRenderManager();
mDataManager = new FixedOgreDataManager();
mRenderManager = new MyGUI::ShaderBasedRenderManager();
mDataManager = new MyGUI::FixedOgreDataManager();
LogManager::getInstance().setSTDOutputEnabled(logging);

@ -8,7 +8,7 @@ namespace MyGUI
class Gui;
class LogManager;
class OgreDataManager;
class OgreRenderManager;
class ShaderBasedRenderManager;
}
namespace Ogre
@ -25,7 +25,7 @@ namespace GUI
MyGUI::Gui *mGui;
MyGUI::LogManager* mLogManager;
MyGUI::OgreDataManager* mDataManager;
MyGUI::OgreRenderManager* mRenderManager;
MyGUI::ShaderBasedRenderManager* mRenderManager;
Ogre::SceneManager* mSceneMgr;

Loading…
Cancel
Save