Преглед на файлове

Camera & Viewport refactored and working somewhat (fixes and re-test needed)

Marko Pintera преди 11 години
родител
ревизия
b55e52c112
променени са 35 файла, в които са добавени 797 реда и са изтрити 627 реда
  1. 0 2
      BansheeCore/BansheeCore.vcxproj
  2. 0 6
      BansheeCore/BansheeCore.vcxproj.filters
  3. 0 32
      BansheeCore/Include/BsCameraProxy.h
  4. 2 7
      BansheeCore/Include/BsCoreObjectManager.h
  5. 2 4
      BansheeCore/Include/BsCorePrerequisites.h
  6. 1 6
      BansheeCore/Include/BsRenderWindow.h
  7. 18 2
      BansheeCore/Include/BsRenderer.h
  8. 0 9
      BansheeCore/Include/BsShader.h
  9. 132 49
      BansheeCore/Include/BsViewport.h
  10. 7 1
      BansheeCore/Include/BsViewportRTTI.h
  11. 0 16
      BansheeCore/Source/BsCameraProxy.cpp
  12. 1 2
      BansheeCore/Source/BsCoreObject.cpp
  13. 1 1
      BansheeCore/Source/BsCoreObjectCore.cpp
  14. 14 30
      BansheeCore/Source/BsCoreObjectManager.cpp
  15. 1 3
      BansheeCore/Source/BsRenderWindow.cpp
  16. 154 33
      BansheeCore/Source/BsViewport.cpp
  17. 0 5
      BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h
  18. 24 29
      BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp
  19. 1 1
      BansheeEditor/Include/BsGizmoManager.h
  20. 1 1
      BansheeEditor/Include/BsHandleDrawManager.h
  21. 5 5
      BansheeEditor/Source/BsGizmoManager.cpp
  22. 4 4
      BansheeEditor/Source/BsHandleDrawManager.cpp
  23. 1 30
      BansheeEngine/Include/BsCamera.h
  24. 103 57
      BansheeEngine/Include/BsCameraHandler.h
  25. 1 1
      BansheeEngine/Include/BsCameraHandlerRTTI.h
  26. 1 0
      BansheeEngine/Include/BsPrerequisites.h
  27. 0 5
      BansheeEngine/Include/BsSceneManager.h
  28. 7 1
      BansheeEngine/Source/BsCamera.cpp
  29. 208 95
      BansheeEngine/Source/BsCameraHandler.cpp
  30. 28 45
      BansheeRenderer/Include/BsBansheeRenderer.h
  31. 77 138
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  32. 0 2
      BansheeSceneManager/Source/BsBansheeSceneManager.cpp
  33. 1 1
      SBansheeEngine/Include/BsScriptCamera.h
  34. 2 2
      SBansheeEngine/Source/BsScriptCamera.cpp
  35. 0 2
      TODO.txt

+ 0 - 2
BansheeCore/BansheeCore.vcxproj

@@ -278,7 +278,6 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
-    <ClInclude Include="Include\BsCameraProxy.h" />
     <ClInclude Include="Include\BsCoreObjectCore.h" />
     <ClInclude Include="Include\BsDrawList.h" />
     <ClInclude Include="Include\BsMaterialParam.h" />
@@ -424,7 +423,6 @@
     <ClInclude Include="Source\BsMeshRTTI.h" />
   </ItemGroup>
   <ItemGroup>
-    <ClCompile Include="Source\BsCameraProxy.cpp" />
     <ClCompile Include="Source\BsCoreObjectCore.cpp" />
     <ClCompile Include="Source\BsCoreThread.cpp" />
     <ClCompile Include="Source\BsDrawList.cpp" />

+ 0 - 6
BansheeCore/BansheeCore.vcxproj.filters

@@ -492,9 +492,6 @@
     <ClInclude Include="Include\BsProfilingManager.h">
       <Filter>Header Files</Filter>
     </ClInclude>
-    <ClInclude Include="Include\BsCameraProxy.h">
-      <Filter>Header Files\Renderer</Filter>
-    </ClInclude>
     <ClInclude Include="Include\BsDrawList.h">
       <Filter>Header Files\Renderer</Filter>
     </ClInclude>
@@ -806,9 +803,6 @@
     <ClCompile Include="Source\BsDrawList.cpp">
       <Filter>Source Files\Renderer</Filter>
     </ClCompile>
-    <ClCompile Include="Source\BsCameraProxy.cpp">
-      <Filter>Source Files\Renderer</Filter>
-    </ClCompile>
     <ClCompile Include="Source\BsTextureImportOptions.cpp">
       <Filter>Source Files\Importer</Filter>
     </ClCompile>

+ 0 - 32
BansheeCore/Include/BsCameraProxy.h

@@ -1,32 +0,0 @@
-#pragma once
-
-#include "BsCorePrerequisites.h"
-#include "BsViewport.h"
-#include "BsConvexVolume.h"
-#include "BsMatrix4.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Contains Camera data used by the Renderer.
-	 */
-	class BS_CORE_EXPORT CameraProxy
-	{
-	public:
-		void calcWorldFrustum();
-
-		SPtr<RenderTargetCore> renderTarget;
-		Viewport viewport;
-		Matrix4 viewMatrix;
-		Matrix4 projMatrix;
-		Matrix4 worldMatrix;
-		INT32 priority;
-		UINT64 layer;
-		bool ignoreSceneRenderables;
-		ConvexVolume frustum;
-		ConvexVolume worldFrustum;
-		Vector3 worldPosition;
-
-		RenderQueuePtr renderQueue;
-	};
-}

+ 2 - 7
BansheeCore/Include/BsCoreObjectManager.h

@@ -137,13 +137,8 @@ namespace BansheeEngine
 		UINT64 mNextAvailableID;
 		Map<UINT64, CoreObject*> mObjects;
 
-		Vector<SimStoredSyncData> mSimSyncData;
-		UINT32 mSimSyncIdx;
-		UINT32 mSimSyncCount;
-
-		Vector<CoreStoredSyncData> mCoreSyncData;
-		UINT32 mCoreSyncIdx;
-		UINT32 mCoreSyncCount;
+		List<SimStoredSyncData> mSimSyncData;
+		List<CoreStoredSyncData> mCoreSyncData;
 
 		BS_MUTEX(mObjectsMutex);
 	};

+ 2 - 4
BansheeCore/Include/BsCorePrerequisites.h

@@ -140,12 +140,11 @@ namespace BansheeEngine
 	class VideoOutputInfo;
 	class VideoModeInfo;
 	class RenderableElement;
-	class CameraProxy;
+	class CameraHandlerCore;
 	struct MaterialProxy;
 	struct MaterialProxyPass;
 	class MeshCoreBase;
 	class MeshCore;
-	class ViewportProxy;
 	class DrawList;
 	struct SubMesh;
 	class TransientMeshCore;
@@ -156,6 +155,7 @@ namespace BansheeEngine
 	class GpuParamBlockBufferCore;
 	class GpuParamsCore;
 	class ShaderCore;
+	class ViewportCore;
 	// Asset import
 	class SpecificImporter;
 	class Importer;
@@ -250,9 +250,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<VideoModeInfo> VideoModeInfoPtr;
 	typedef std::shared_ptr<DrawList> DrawListPtr;
 	typedef std::shared_ptr<RenderQueue> RenderQueuePtr;
-	typedef std::shared_ptr<CameraProxy> CameraProxyPtr;
 	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
-	typedef std::shared_ptr<ViewportProxy> ViewportProxyPtr;
 	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;
 	typedef std::shared_ptr<ResourceMetaData> ResourceMetaDataPtr;
 }

+ 1 - 6
BansheeCore/Include/BsRenderWindow.h

@@ -112,12 +112,7 @@ namespace BansheeEngine
 	{
 	public:
 		RenderWindowCore(const RENDER_WINDOW_DESC& desc);
-		virtual ~RenderWindowCore() { }
-
-		/**
-		 * @copydoc	RenderTargetCore::destroy
-		 */
-		virtual void destroy();
+		virtual ~RenderWindowCore();
 
 		/** 
 		 * @brief	Switches the window to fullscreen mode. Child windows cannot go into fullscreen mode.

+ 18 - 2
BansheeCore/Include/BsRenderer.h

@@ -67,6 +67,22 @@ namespace BansheeEngine
 		 */
 		virtual void renderAll() = 0;
 
+		/**
+		 * @brief	Called whenever a new camera is created.
+		 *
+		 * @note	Core thread.
+		 *			Internal method.
+		 */
+		virtual void _notifyCameraAdded(const CameraHandlerCore* camera) { }
+
+		/**
+		 * @brief	Called whenever a camera is destroyed.
+		 *
+		 * @note	Core thread.
+		 *			Internal method.
+		 */
+		virtual void _notifyCameraRemoved(const CameraHandlerCore* camera) { }
+
 		/**
 		 * @brief	Activates the specified pass on the pipeline.
 		 *
@@ -97,7 +113,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		Event<void(const CameraProxy&)> onCorePreRenderViewport;
+		Event<void(const CameraHandlerCore&)> onCorePreRenderViewport;
 
 		/**
 		 * @brief	Callback that gets triggered after main render queue items are rendered,
@@ -105,6 +121,6 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		Event<void(const CameraProxy&)> onCorePostRenderViewport;
+		Event<void(const CameraHandlerCore&)> onCorePostRenderViewport;
 	};
 }

+ 0 - 9
BansheeCore/Include/BsShader.h

@@ -5,15 +5,6 @@
 
 namespace BansheeEngine
 {
-	/**
-	 * @brief	Type of shader dirty flags
-	 */
-	enum class ShaderDirtyFlag
-	{
-		Shader = 0x01, /**< Internal shader data is dirty. */
-		Proxy = 0x02 /**< Active proxy needs to be updated. */
-	};
-
 	/**
 	 * @brief Describes a single data (int, Vector2, etc.) shader parameter.
 	 *

+ 132 - 49
BansheeCore/Include/BsViewport.h

@@ -2,6 +2,7 @@
 
 #include "BsCorePrerequisites.h"
 #include "BsIReflectable.h"
+#include "BsCoreObject.h"
 #include "BsColor.h"
 #include "BsRect2I.h"
 #include "BsRect2.h"
@@ -13,31 +14,11 @@ namespace BansheeEngine
 	 * @brief	Viewport provides you with a way to render to only a part of a 
 	 * 			RenderTarget. It also allows you to set up color/depth/stencil
 	 * 			clear values for that specific region.
-	 *
-	 * @note	Thread safe unless noted otherwise.
 	 */
-	class BS_CORE_EXPORT Viewport : public IReflectable
+	class BS_CORE_EXPORT ViewportBase
     {
     public:       
-		Viewport();
-        
-        /**
-         * @brief	Constructs a new viewport.
-         *
-         * @note	Viewport coordinates are normalized in [0, 1] range.
-         */
-        Viewport(const RenderTargetPtr& target, float x = 0.0f, float y = 0.0f, float width = 1.0f, float height = 1.0f);
-        virtual ~Viewport();
-
-        /**
-         * @brief	Returns the render target the viewport is associated with.
-         */
-        RenderTargetPtr getTarget() const { return mTarget; }
-
-		/**
-		 * @brief	Sets the render target the viewport will be associated with.
-		 */
-		void setTarget(const RenderTargetPtr& target) { mTarget = target; markCoreDirty(); }
+		virtual ~ViewportBase() { }
 
         /**
          * @brief	Gets the normalized x coordinate of the viewport, in [0, 1] range.
@@ -61,29 +42,21 @@ namespace BansheeEngine
 
         /**
          * @brief	Gets the actual x coordinate of the viewport in pixels, in [0, RenderTargetWidth] range.
-		 *
-		 * @note	Sim thread only.
          */
 		INT32 getX() const;
 
         /**
          * @brief	Gets the actual y coordinate of the viewport in pixels, in [0, RenderTargetHeight] range.
-		 *
-		 * @note	Sim thread only.
          */
 		INT32 getY() const;
 
 		/**
          * @brief	Gets the actual width coordinate of the viewport in pixels, in [0, RenderTargetWidth] range.
-		 *
-		 * @note	Sim thread only.
          */
 		INT32 getWidth() const;
 
 		/**
          * @brief	Gets the actual height coordinate of the viewport in pixels, in [0, RenderTargetHeight] range.
-		 *
-		 * @note	Sim thread only.
          */
 		INT32 getHeight() const;
                
@@ -96,8 +69,6 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Returns actual area of the viewport, in pixels.
-		 *
-		 * @note	Sim thread only.
 		 */
 		Rect2I getArea() const;
 
@@ -129,7 +100,6 @@ namespace BansheeEngine
 		 */
 		float getClearDepthValue() const { return mDepthClearValue; }
 
-
 		/**
 		 * @brief	Returns the value to clear the viewport stencil buffer to.
 		 */
@@ -150,28 +120,28 @@ namespace BansheeEngine
 		 */
 		bool getRequiresStencilClear() const { return mRequiresStencilClear; }
 
-		/**
-		 * @brief	Makes an exact copy of this viewport.
-		 */
-		Viewport clone();
+    protected:
+        /**
+         * @brief	Constructs a new viewport.
+         *
+         * @note	Viewport coordinates are normalized in [0, 1] range.
+         */
+		ViewportBase(float x = 0.0f, float y = 0.0f, float width = 1.0f, float height = 1.0f);
 
 		/**
-		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know when internal data has changed and core thread potentially needs to be notified.
+		 * @copydoc	CoreObject::markCoreDirty
 		 */
-		bool _isCoreDirty() const { return mCoreDirtyFlags != 0; }
+		virtual void _markCoreDirty() { }
 
 		/**
-		 * @brief	Marks the core dirty flag as clean.
+		 * @brief	Gets the render target width.
 		 */
-		void _markCoreClean() { mCoreDirtyFlags = 0; }
-    protected:
+		virtual UINT32 getTargetWidth() const = 0;
+
 		/**
-		 * @brief	Marks the core data as dirty, signaling that the core thread needs an updated version.
+		 * @brief	Gets the render target width.
 		 */
-		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
-
-        RenderTargetPtr mTarget;
+		virtual UINT32 getTargetHeight() const = 0;
 
 		Rect2 mNormArea;
 
@@ -183,13 +153,126 @@ namespace BansheeEngine
 		float mDepthClearValue;
 		UINT16 mStencilClearValue;
 
-		UINT32 mCoreDirtyFlags; /**< True when internal data has changed and core thread wasn't yet informed. */
-
 		static const Color DEFAULT_CLEAR_COLOR;
+    };
+
+	/**
+	 * @copydoc	ViewportBase
+	 */
+	class BS_CORE_EXPORT ViewportCore : public CoreObjectCore, public ViewportBase
+    {
+    public:       
+        /**
+         * @brief	Returns the render target the viewport is associated with.
+         */
+		SPtr<RenderTargetCore> getTarget() const { return mTarget; }
+
+		/**
+		 * @brief	Sets the render target the viewport will be associated with.
+		 */
+		void setTarget(const SPtr<RenderTargetCore>& target) { mTarget = target; }
+
+		/**
+		 * @copydoc	ViewportBase::ViewportBase
+		 */
+		static SPtr<ViewportCore> create(const SPtr<RenderTargetCore>& target, float x = 0.0f, float y = 0.0f, float width = 1.0f, float height = 1.0f);
+
+    protected:
+		friend class Viewport;
+
+		/**
+		 * @copydoc	ViewportBase::ViewportBase
+		 */
+		ViewportCore(const SPtr<RenderTargetCore>& target, float x = 0.0f, float y = 0.0f, float width = 1.0f, float height = 1.0f);
+
+		/**
+		 * @copydoc	CoreObject::getTargetWidth
+		 */
+		UINT32 getTargetWidth() const;
+
+		/**
+		 * @copydoc	CoreObject::getTargetHeight
+		 */
+		UINT32 getTargetHeight() const;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data);
+
+		SPtr<RenderTargetCore> mTarget;
+    };
+
+	/**
+	 * @copydoc	ViewportBase
+	 */
+	class BS_CORE_EXPORT Viewport : public IReflectable, public CoreObject, public ViewportBase
+    {
+    public:       
+        /**
+         * @brief	Returns the render target the viewport is associated with.
+         */
+        RenderTargetPtr getTarget() const { return mTarget; }
+
+		/**
+		 * @brief	Sets the render target the viewport will be associated with.
+		 */
+		void setTarget(const RenderTargetPtr& target) { mTarget = target; _markCoreDirty(); }
+
+		/**
+		 * @brief	Retrieves a core implementation of a viewport usable only from the
+		 *			core thread.
+		 */
+		SPtr<ViewportCore> getCore() const;
+
+		/**
+		 * @copydoc	ViewportBase::ViewportBase
+		 */
+		static ViewportPtr create(const RenderTargetPtr& target, float x = 0.0f, float y = 0.0f, 
+			float width = 1.0f, float height = 1.0f);
+
+    protected:
+		/**
+		 * @copydoc	ViewportBase::ViewportBase
+		 */
+        Viewport(const RenderTargetPtr& target, float x = 0.0f, float y = 0.0f, float width = 1.0f, float height = 1.0f);
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		void _markCoreDirty();
+
+		/**
+		 * @copydoc	CoreObject::getTargetWidth
+		 */
+		UINT32 getTargetWidth() const;
+
+		/**
+		 * @copydoc	CoreObject::getTargetHeight
+		 */
+		UINT32 getTargetHeight() const;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator);
+
+		/**
+		 * @copydoc	CoreObject::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const;
+
+        RenderTargetPtr mTarget;
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/
 		/************************************************************************/
+		Viewport();
+
+		/**
+		 * @brief	Creates an empty viewport for serialization purposes.
+		 */
+		static ViewportPtr createEmpty();
 	public:
 		friend class ViewportRTTI;
 		static RTTITypeBase* getRTTIStatic();

+ 7 - 1
BansheeCore/Include/BsViewportRTTI.h

@@ -43,6 +43,12 @@ namespace BansheeEngine
 			addPlainField("mStencilClearValue", 6, &ViewportRTTI::getStencilClearValue, &ViewportRTTI::setStencilClearValue);
 		}
 
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Viewport* viewport = static_cast<Viewport*>(obj);
+			viewport->initialize();
+		}
+
 		virtual const String& getRTTIName()
 		{
 			static String name = "Viewport";
@@ -56,7 +62,7 @@ namespace BansheeEngine
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
-			return bs_shared_ptr<Viewport>();
+			return Viewport::createEmpty();
 		}
 	};
 }

+ 0 - 16
BansheeCore/Source/BsCameraProxy.cpp

@@ -1,16 +0,0 @@
-#include "BsCameraProxy.h"
-
-namespace BansheeEngine
-{
-	void CameraProxy::calcWorldFrustum()
-	{
-		const Vector<Plane>& frustumPlanes = frustum.getPlanes();
-		Vector<Plane> worldPlanes;
-		for (auto& plane : frustumPlanes)
-		{
-			worldPlanes.push_back(worldMatrix.multiplyAffine(plane));
-		}
-
-		worldFrustum = ConvexVolume(worldPlanes);
-	}
-}

+ 1 - 2
BansheeCore/Source/BsCoreObject.cpp

@@ -62,8 +62,7 @@ namespace BansheeEngine
 			BS_EXCEPT(InternalErrorException, "Trying to destroy an object that is already destroyed (or it never was initialized).");
 #endif
 
-		if (mCoreSpecific != nullptr)
-			mCoreSpecific->destroy();
+		mCoreSpecific = nullptr;
 
 		setIsInitialized(false);
 	}

+ 1 - 1
BansheeCore/Source/BsCoreObjectCore.cpp

@@ -13,7 +13,7 @@ namespace BansheeEngine
 		// If you are not sure this will get called by the core thread, make sure 
 		// to destroy() the object manually before it goes out of scope.
 		if (!mIsDestroyed)
-			destroy();
+			destroy(); //assert(false && "Destructing an object that has not been destroyed previously. This is not allowed.");
 	}
 
 	void CoreObjectCore::destroy() 

+ 14 - 30
BansheeCore/Source/BsCoreObjectManager.cpp

@@ -2,13 +2,13 @@
 #include "BsCoreObject.h"
 #include "BsCoreObjectCore.h"
 #include "BsException.h"
+#include "BsMath.h"
 #include "BsFrameAlloc.h"
 
 namespace BansheeEngine
 {
 	CoreObjectManager::CoreObjectManager()
-		:mNextAvailableID(1), mSimSyncIdx(0), mSimSyncCount(0),
-		mCoreSyncIdx(0), mCoreSyncCount(0)
+		:mNextAvailableID(1)
 	{
 
 	} 
@@ -51,11 +51,8 @@ namespace BansheeEngine
 		mObjects.erase(internalId);
 
 		{
-			for (UINT32 i = 0; i < mSimSyncCount; i++)
+			for (auto& syncData : mSimSyncData)
 			{
-				UINT32 idx = (mSimSyncIdx + i - mSimSyncCount - 1) % mSimSyncCount;
-
-				SimStoredSyncData& syncData = mSimSyncData[idx];
 				auto iterFind = syncData.entries.find(internalId);
 				if (iterFind != syncData.entries.end())
 				{
@@ -70,11 +67,8 @@ namespace BansheeEngine
 		}
 
 		{
-			for (UINT32 i = 0; i < mCoreSyncCount; i++)
+			for (auto& syncData : mCoreSyncData)
 			{
-				UINT32 idx = (mCoreSyncIdx + i - mCoreSyncCount - 1) % mCoreSyncCount;
-
-				CoreStoredSyncData& syncData = mCoreSyncData[idx];
 				auto iterFind = syncData.entries.find(internalId);
 				if (iterFind != syncData.entries.end())
 				{
@@ -95,12 +89,8 @@ namespace BansheeEngine
 
 		if (type == CoreObjectSync::Sim)
 		{
-			mCoreSyncCount++;
-			if (mCoreSyncCount > (UINT32)mCoreSyncData.size())
-				mCoreSyncData.push_back(CoreStoredSyncData());
-
-			mCoreSyncIdx = (mCoreSyncIdx + 1) % mCoreSyncCount;
-			CoreStoredSyncData& syncData = mCoreSyncData[mCoreSyncIdx];
+			mCoreSyncData.push_back(CoreStoredSyncData());
+			CoreStoredSyncData& syncData = mCoreSyncData.back();
 
 			syncData.alloc = allocator;
 			for (auto& objectData : mObjects)
@@ -118,12 +108,8 @@ namespace BansheeEngine
 		}
 		else
 		{
-			mSimSyncCount++;
-			if (mSimSyncCount > (UINT32)mSimSyncData.size())
-				mSimSyncData.push_back(SimStoredSyncData());
-
-			mSimSyncIdx = (mSimSyncIdx + 1) % mSimSyncCount;
-			SimStoredSyncData& syncData = mSimSyncData[mSimSyncIdx];
+			mSimSyncData.push_back(SimStoredSyncData());
+			SimStoredSyncData& syncData = mSimSyncData.back();
 
 			syncData.alloc = allocator;
 			for (auto& objectData : mObjects)
@@ -147,13 +133,11 @@ namespace BansheeEngine
 
 		if (type == CoreObjectSync::Sim)
 		{
-			if (mCoreSyncCount == 0)
+			if (mCoreSyncData.size() == 0)
 				return;
 
-			mCoreSyncCount--;
-			UINT32 idx = mCoreSyncIdx - mCoreSyncCount;
+			CoreStoredSyncData& syncData = mCoreSyncData.front();
 
-			CoreStoredSyncData& syncData = mCoreSyncData[idx];
 			for (auto& objectData : syncData.entries)
 			{
 				const CoreStoredSyncObjData& objSyncData = objectData.second;
@@ -166,16 +150,15 @@ namespace BansheeEngine
 			}
 
 			syncData.entries.clear();
+			mCoreSyncData.pop_front();
 		}
 		else
 		{
-			if (mSimSyncCount == 0)
+			if (mSimSyncData.size() == 0)
 				return;
 
-			mSimSyncCount--;
-			UINT32 idx = mSimSyncIdx - mSimSyncCount;
+			SimStoredSyncData& syncData = mSimSyncData.front();
 
-			SimStoredSyncData& syncData = mSimSyncData[idx];
 			for (auto& objectData : syncData.entries)
 			{
 				const SimStoredSyncObjData& objSyncData = objectData.second;
@@ -188,6 +171,7 @@ namespace BansheeEngine
 			}
 
 			syncData.entries.clear();
+			mSimSyncData.pop_front();
 		}
 	}
 }

+ 1 - 3
BansheeCore/Source/BsRenderWindow.cpp

@@ -30,13 +30,11 @@ namespace BansheeEngine
 
 	}
 
-	void RenderWindowCore::destroy()
+	RenderWindowCore::~RenderWindowCore()
 	{
 		Platform::resetNonClientAreas(*this);
 
 		RenderWindowCoreManager::instance().windowDestroyed(this);
-
-		RenderTargetCore::destroy();
 	}
 
 	void RenderWindowCore::setHidden(bool hidden)

+ 154 - 33
BansheeCore/Source/BsViewport.cpp

@@ -4,43 +4,33 @@
 #include "BsRenderTarget.h"
 #include "BsMath.h"
 #include "BsRenderSystem.h"
+#include "BsFrameAlloc.h"
 
 namespace BansheeEngine 
 {
 	const Color Viewport::DEFAULT_CLEAR_COLOR = Color(143.0f / 255.0f, 111.0f / 255.0f, 0);
 
-	Viewport::Viewport()
-		:mTarget(nullptr), mClearColor(DEFAULT_CLEAR_COLOR), mRequiresColorClear(true), mRequiresDepthClear(true), 
-		mRequiresStencilClear(false), mStencilClearValue(0), mDepthClearValue(1.0f), mCoreDirtyFlags(0xFFFFFFFF)
-	{
-
-	}
-
-    Viewport::Viewport(const RenderTargetPtr& target, float x, float y, float width, float height)
-         :mTarget(target), mNormArea(x, y, width, height), mClearColor(DEFAULT_CLEAR_COLOR), mRequiresColorClear(true), 
-		 mRequiresDepthClear(true), mRequiresStencilClear(false), mStencilClearValue(0), mDepthClearValue(1.0f), mCoreDirtyFlags(0xFFFFFFFF)
+	ViewportBase::ViewportBase(float x, float y, float width, float height)
+         :mNormArea(x, y, width, height), mClearColor(DEFAULT_CLEAR_COLOR), mRequiresColorClear(true), 
+		 mRequiresDepthClear(true), mRequiresStencilClear(false), mStencilClearValue(0), mDepthClearValue(1.0f)
     {
 
     }
 
-    Viewport::~Viewport()
-    { }
-
-
-    void Viewport::setArea(float x, float y, float width, float height)
+	void ViewportBase::setArea(float x, float y, float width, float height)
     {
         mNormArea.x = x;
         mNormArea.y = y;
         mNormArea.width = width;
         mNormArea.height = height;
 
-		markCoreDirty();
+		_markCoreDirty();
     }
 
-	Rect2I Viewport::getArea() const
+	Rect2I ViewportBase::getArea() const
 	{
-		float width = (float)mTarget->getProperties().getWidth();
-		float height = (float)mTarget->getProperties().getHeight();
+		float width = (float)getTargetWidth();
+		float height = (float)getTargetHeight();
 		
 		Rect2I area;
 		area.x = (int)(mNormArea.x * width);
@@ -51,47 +41,178 @@ namespace BansheeEngine
 		return area;
 	}
 
-	void Viewport::setRequiresClear(bool colorClear, bool depthClear, bool stencilClear)
+	void ViewportBase::setRequiresClear(bool colorClear, bool depthClear, bool stencilClear)
 	{
 		mRequiresColorClear = colorClear;
 		mRequiresDepthClear = depthClear;
 		mRequiresStencilClear = stencilClear;
 
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void Viewport::setClearValues(const Color& clearColor, float clearDepth, UINT16 clearStencil)
+	void ViewportBase::setClearValues(const Color& clearColor, float clearDepth, UINT16 clearStencil)
 	{
 		mClearColor = clearColor;
 		mDepthClearValue = clearDepth;
 		mStencilClearValue = clearStencil;
 
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	INT32 Viewport::getX() const 
+	INT32 ViewportBase::getX() const
 	{ 
-		return (INT32)(mNormArea.x * mTarget->getProperties().getWidth());
+		return (INT32)(mNormArea.x * getTargetWidth());
 	}
 
-	INT32 Viewport::getY() const 
+	INT32 ViewportBase::getY() const
 	{ 
-		return (INT32)(mNormArea.y * mTarget->getProperties().getHeight());
+		return (INT32)(mNormArea.y * getTargetHeight());
 	}
 
-	INT32 Viewport::getWidth() const 
+	INT32 ViewportBase::getWidth() const
 	{ 
-		return (INT32)(mNormArea.width * mTarget->getProperties().getWidth());
+		return (INT32)(mNormArea.width * getTargetWidth());
 	}
 
-	INT32 Viewport::getHeight() const 
+	INT32 ViewportBase::getHeight() const
 	{ 
-		return (INT32)(mNormArea.height * mTarget->getProperties().getHeight());
+		return (INT32)(mNormArea.height * getTargetHeight());
+	}
+
+	ViewportCore::ViewportCore(const SPtr<RenderTargetCore>& target, float x, float y, float width, float height)
+		:ViewportBase(x, y, width, height), mTarget(target)
+	{
+
+	}
+
+	SPtr<ViewportCore> ViewportCore::create(const SPtr<RenderTargetCore>& target, float x, float y, float width, float height)
+	{
+		ViewportCore* viewport = new (bs_alloc<Viewport>()) ViewportCore(target, x, y, width, height);
+
+		SPtr<ViewportCore> viewportPtr = bs_shared_ptr<ViewportCore, GenAlloc>(viewport);
+		viewportPtr->_setThisPtr(viewportPtr);
+		viewportPtr->initialize();
+
+		return viewportPtr;
+	}
+
+	UINT32 ViewportCore::getTargetWidth() const
+	{
+		return mTarget->getProperties().getWidth();
+	}
+
+	UINT32 ViewportCore::getTargetHeight() const
+	{
+		return mTarget->getProperties().getHeight();
+	}
+
+	void ViewportCore::syncToCore(const CoreSyncData& data)
+	{
+		char* dataPtr = (char*)data.getBuffer();
+		dataPtr = rttiReadElem(mNormArea, dataPtr);
+		dataPtr = rttiReadElem(mRequiresColorClear, dataPtr);
+		dataPtr = rttiReadElem(mRequiresDepthClear, dataPtr);
+		dataPtr = rttiReadElem(mRequiresStencilClear, dataPtr);
+		dataPtr = rttiReadElem(mClearColor, dataPtr);
+		dataPtr = rttiReadElem(mDepthClearValue, dataPtr);
+		dataPtr = rttiReadElem(mStencilClearValue, dataPtr);
+
+		SPtr<RenderTargetCore>* rtPtr = (SPtr<RenderTargetCore>*)dataPtr;
+		mTarget = *rtPtr;
+
+		rtPtr->~SPtr<RenderTargetCore>();
+	}
+
+	Viewport::Viewport()
+		:ViewportBase()
+	{ }
+
+	Viewport::Viewport(const RenderTargetPtr& target, float x, float y, float width, float height)
+		:ViewportBase(x, y, width, height), mTarget(target)
+	{
+
+	}
+
+	SPtr<ViewportCore> Viewport::getCore() const
+	{
+		return std::static_pointer_cast<ViewportCore>(mCoreSpecific);
+	}
+
+	void Viewport::_markCoreDirty()
+	{
+		markCoreDirty();
+	}
+
+	UINT32 Viewport::getTargetWidth() const
+	{
+		return mTarget->getProperties().getWidth();
+	}
+
+	UINT32 Viewport::getTargetHeight() const
+	{
+		return mTarget->getProperties().getHeight();
+	}
+
+	SPtr<CoreObjectCore> Viewport::createCore() const
+	{
+		ViewportCore* viewport = new (bs_alloc<Viewport>()) 
+			ViewportCore(mTarget->getCore(), mNormArea.x, mNormArea.y, mNormArea.width, mNormArea.height);
+
+		SPtr<ViewportCore> viewportPtr = bs_shared_ptr<ViewportCore, GenAlloc>(viewport);
+		viewportPtr->_setThisPtr(viewportPtr);
+
+		return viewportPtr;
 	}
 
-	Viewport Viewport::clone()
+	CoreSyncData Viewport::syncToCore(FrameAlloc* allocator)
 	{
-		return *this;
+		UINT32 size = 0;
+		size += rttiGetElemSize(mNormArea);
+		size += rttiGetElemSize(mRequiresColorClear);
+		size += rttiGetElemSize(mRequiresDepthClear);
+		size += rttiGetElemSize(mRequiresStencilClear);
+		size += rttiGetElemSize(mClearColor);
+		size += rttiGetElemSize(mDepthClearValue);
+		size += rttiGetElemSize(mStencilClearValue);
+		size += sizeof(SPtr<RenderTargetCore>);
+
+		UINT8* buffer = allocator->alloc(size);
+
+		char* dataPtr = (char*)buffer;
+		dataPtr = rttiWriteElem(mNormArea, dataPtr);
+		dataPtr = rttiWriteElem(mRequiresColorClear, dataPtr);
+		dataPtr = rttiWriteElem(mRequiresDepthClear, dataPtr);
+		dataPtr = rttiWriteElem(mRequiresStencilClear, dataPtr);
+		dataPtr = rttiWriteElem(mClearColor, dataPtr);
+		dataPtr = rttiWriteElem(mDepthClearValue, dataPtr);
+		dataPtr = rttiWriteElem(mStencilClearValue, dataPtr);
+
+		SPtr<RenderTargetCore>* rtPtr = new (dataPtr) SPtr<RenderTargetCore>();
+		if (mTarget != nullptr)
+			*rtPtr = mTarget->getCore();
+		else
+			*rtPtr = nullptr;
+
+		return CoreSyncData(buffer, size);
+	}
+
+	ViewportPtr Viewport::create(const RenderTargetPtr& target, float x, float y, float width, float height)
+	{
+		Viewport* viewport = new (bs_alloc<Viewport>()) Viewport(target, x, y, width, height);
+		ViewportPtr viewportPtr = bs_core_ptr<Viewport, GenAlloc>(viewport);
+		viewportPtr->_setThisPtr(viewportPtr);
+		viewportPtr->initialize();
+
+		return viewportPtr;
+	}
+
+	ViewportPtr Viewport::createEmpty()
+	{
+		Viewport* viewport = new (bs_alloc<Viewport>()) Viewport();
+		ViewportPtr viewportPtr = bs_core_ptr<Viewport, GenAlloc>(viewport);
+		viewportPtr->_setThisPtr(viewportPtr);
+
+		return viewportPtr;
 	}
 
 	RTTITypeBase* Viewport::getRTTIStatic()

+ 0 - 5
BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h

@@ -110,11 +110,6 @@ namespace BansheeEngine
 		 */
 		virtual void initialize();
 
-		/**
-		 * @copydoc	CoreObjectCore::destroy
-		 */
-		virtual void destroy();
-
 		/**
 		 * @brief	Creates internal resources dependent on window size.
 		 */

+ 24 - 29
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp

@@ -26,7 +26,30 @@ namespace BansheeEngine
 	{ }
 
 	D3D11RenderWindowCore::~D3D11RenderWindowCore()
-	{ }
+	{ 
+		D3D11RenderWindowProperties& props = mProperties;
+
+		props.mActive = false;
+		markCoreDirty();
+
+		SAFE_RELEASE(mSwapChain);
+		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_SwapChain);
+
+		if (mHWnd && !mIsExternal)
+		{
+			DestroyWindow(mHWnd);
+		}
+
+		if (mDepthStencilView != nullptr)
+		{
+			TextureCore::releaseView(mDepthStencilView);
+			mDepthStencilView = nullptr;
+		}
+
+		mHWnd = 0;
+
+		destroySizeDependedD3DResources();
+	}
 
 	void D3D11RenderWindowCore::initialize()
 	{
@@ -247,34 +270,6 @@ namespace BansheeEngine
 		setHidden(props.isHidden());
 	}
 
-	void D3D11RenderWindowCore::destroy()
-	{
-		D3D11RenderWindowProperties& props = mProperties;
-
-		props.mActive = false;
-		markCoreDirty();
-
-		SAFE_RELEASE(mSwapChain);
-		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_SwapChain);
-
-		if (mHWnd && !mIsExternal)
-		{
-			DestroyWindow(mHWnd);
-		}
-
-		if (mDepthStencilView != nullptr)
-		{
-			TextureCore::releaseView(mDepthStencilView);
-			mDepthStencilView = nullptr;
-		}
-
-		mHWnd = 0;
-
-		destroySizeDependedD3DResources();
-
-		RenderWindowCore::destroy();
-	}
-
 	void D3D11RenderWindowCore::swapBuffers()
 	{
 		THROW_IF_NOT_CORE_THREAD;

+ 1 - 1
BansheeEditor/Include/BsGizmoManager.h

@@ -210,7 +210,7 @@ namespace BansheeEngine
 	private:
 		void initialize(const GizmoManager::CoreInitData& initData);
 
-		void render(const CameraProxy& camera);
+		void render(const CameraHandlerCore& camera);
 		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
 		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
 

+ 1 - 1
BansheeEditor/Include/BsHandleDrawManager.h

@@ -85,7 +85,7 @@ namespace BansheeEngine
 		void initialize(const MaterialProxyPtr& wireMatProxy, const MaterialProxyPtr& solidMatProxy);
 
 		void updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes);
-		void render(const CameraProxy& camera);
+		void render(const CameraHandlerCore& camera);
 
 		RenderTargetPtr mSceneRenderTarget;
 		Vector<MeshData> mMeshes;

+ 5 - 5
BansheeEditor/Source/BsGizmoManager.cpp

@@ -711,17 +711,17 @@ namespace BansheeEngine
 		mIconRenderData = iconRenderData;
 	}
 
-	void GizmoManagerCore::render(const CameraProxy& camera)
+	void GizmoManagerCore::render(const CameraHandlerCore& camera)
 	{
 		SPtr<RenderTargetCore> sceneRenderTarget = mSceneRenderTarget->getCore();
 
-		if (camera.renderTarget != sceneRenderTarget)
+		if (camera.getViewport()->getTarget() != sceneRenderTarget)
 			return;
 
 		float width = (float)sceneRenderTarget->getProperties().getWidth();
 		float height = (float)sceneRenderTarget->getProperties().getHeight();
 
-		Rect2 normArea = camera.viewport.getNormArea();
+		Rect2 normArea = camera.getViewport()->getNormArea();
 
 		Rect2I screenArea;
 		screenArea.x = (int)(normArea.x * width);
@@ -730,10 +730,10 @@ namespace BansheeEngine
 		screenArea.height = (int)(normArea.height * height);
 
 		if (mSolidMesh != nullptr)
-			renderGizmos(camera.viewMatrix, camera.projMatrix, mSolidMesh, GizmoManager::GizmoMaterial::Solid);
+			renderGizmos(camera.getViewMatrix(), camera.getProjectionMatrixRS(), mSolidMesh, GizmoManager::GizmoMaterial::Solid);
 
 		if (mWireMesh != nullptr)
-			renderGizmos(camera.viewMatrix, camera.projMatrix, mWireMesh, GizmoManager::GizmoMaterial::Wire);
+			renderGizmos(camera.getViewMatrix(), camera.getProjectionMatrixRS(), mWireMesh, GizmoManager::GizmoMaterial::Wire);
 
 		if (mIconMesh != nullptr)
 			renderIconGizmos(screenArea, mIconMesh, mIconRenderData, false);

+ 4 - 4
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -210,18 +210,18 @@ namespace BansheeEngine
 		mMeshes = meshes;
 	}
 
-	void HandleDrawManagerCore::render(const CameraProxy& camera)
+	void HandleDrawManagerCore::render(const CameraHandlerCore& camera)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		SPtr<RenderTargetCore> sceneRenderTarget = mSceneRenderTarget->getCore();
-		if (camera.renderTarget != sceneRenderTarget)
+		if (camera.getViewport()->getTarget() != sceneRenderTarget)
 			return;
 
 		float width = (float)sceneRenderTarget->getProperties().getWidth();
 		float height = (float)sceneRenderTarget->getProperties().getHeight();
 
-		Rect2 normArea = camera.viewport.getNormArea();
+		Rect2 normArea = camera.getViewport()->getNormArea();
 
 		Rect2I screenArea;
 		screenArea.x = (int)(normArea.x * width);
@@ -229,7 +229,7 @@ namespace BansheeEngine
 		screenArea.width = (int)(normArea.width * width);
 		screenArea.height = (int)(normArea.height * height);
 
-		Matrix4 viewProjMat = camera.projMatrix * camera.viewMatrix;
+		Matrix4 viewProjMat = camera.getProjectionMatrixRS() * camera.getViewMatrix();
 		mSolidMaterial.mViewProj.set(viewProjMat);
 		mWireMaterial.mViewProj.set(viewProjMat);
 

+ 1 - 30
BansheeEngine/Include/BsCamera.h

@@ -286,35 +286,6 @@ namespace BansheeEngine
 		 */
 		CameraHandlerPtr _getHandler() const { updateView(); return mInternal; }
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
-
-		/**
-		 * @copydoc	CameraHandler::_isCoreDirty
-		 */
-		bool _isCoreDirty() const { return mInternal->_isCoreDirty(); }
-
-		/**
-		 * @copydoc	CameraHandler::_markCoreClean
-		 */
-		void _markCoreClean() { mInternal->_markCoreClean(); }
-
-		/**
-		 * @copydoc	CameraHandler::_createProxy
-		 */
-		CameraProxyPtr _createProxy() const { updateView(); return mInternal->_createProxy(); }
-
-		/**
-		 * @copydoc	CameraHandler::_getActiveProxy
-		 */
-		CameraProxyPtr _getActiveProxy() const { return mInternal->_getActiveProxy(); }
-
-		/**
-		 * @copydoc	CameraHandler::_setActiveProxy
-		 */
-		void _setActiveProxy(const CameraProxyPtr& proxy) { mInternal->_setActiveProxy(proxy); }
-
     protected:
 		/**
 		 * @brief	Checks if the world transform of the camera changed, and if needed updates
@@ -335,7 +306,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	Component::update
 		 */
-		virtual void update() {}
+		virtual void update();
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 103 - 57
BansheeEngine/Include/BsCameraHandler.h

@@ -9,7 +9,7 @@
 #include "BsAABox.h"
 #include "BsQuaternion.h"
 #include "BsRay.h"
-#include "BsCameraProxy.h"
+#include "BsCoreObject.h"
 #include "BsConvexVolume.h"
 
 namespace BansheeEngine 
@@ -40,21 +40,11 @@ namespace BansheeEngine
 	 * @brief	Camera determines how is world geometry projected onto a 2D surface. You may
 	 *			position and orient it in space, set options like aspect ratio and field or view
 	 *			and it outputs view and projection matrices required for rendering.
-	 *
-	 * @note	Sim thread only.
 	 */
-    class BS_EXPORT CameraHandler : public IReflectable
+	class BS_EXPORT CameraHandlerBase
     {
     public:
-		CameraHandler(RenderTargetPtr target = nullptr,
-			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
-
-		virtual ~CameraHandler();
-
-		/**
-		 * @brief	Returns the viewport used by the camera.
-		 */	
-		ViewportPtr getViewport() const { return mViewport; }
+		virtual ~CameraHandlerBase() { }
 
 		/**
 		 * @brief	Sets the camera horizontal field of view. This determines how wide the camera
@@ -293,7 +283,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	This option tells the renderer that this camera should ignore any renderable components.
 		 */
-		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; markCoreDirty(); }
+		void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; _markCoreDirty(); }
 
 		/**
 		 * @brief	This option tells the renderer that this camera should ignore any renderable components.
@@ -312,7 +302,7 @@ namespace BansheeEngine
 		 *
 		 * @param	priority	The priority. Higher value means the camera will be rendered sooner.
 		 */
-		void setPriority(INT32 priority) { mPriority = priority; markCoreDirty(); }
+		void setPriority(INT32 priority) { mPriority = priority; _markCoreDirty(); }
 
 		/**
 		 * @brief	Retrieves layer bitfield that is used when determining which object should the camera render.
@@ -322,7 +312,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Sets layer bitfield that is used when determining which object should the camera render.
 		 */
-		void setLayers(UINT64 layers) { mLayers = layers; markCoreDirty(); }
+		void setLayers(UINT64 layers) { mLayers = layers; _markCoreDirty(); }
 
 		/**
 		 * @brief	Converts a point in world space to screen coordinates (in pixels
@@ -419,42 +409,10 @@ namespace BansheeEngine
 
         static const float INFINITE_FAR_PLANE_ADJUST; /**< Small constant used to reduce far plane projection to avoid inaccuracies. */
 
-		/************************************************************************/
-		/* 								CORE PROXY                      		*/
-		/************************************************************************/
-
-		/**
-		 * @brief	Checks is the core dirty flag set. This is used by external systems 
-		 *			to know when internal data has changed and core thread potentially needs to be notified.
-		 */
-		bool _isCoreDirty() const { return mCoreDirtyFlags != 0 || mViewport->_isCoreDirty(); }
-
-		/**
-		 * @brief	Marks the core dirty flag as clean.
-		 */
-		void _markCoreClean() { mCoreDirtyFlags = 0; mViewport->_markCoreClean(); }
-
-		/**
-		 * @brief	Creates a new core proxy from the currently set options. Core proxies ensure
-		 *			that the core thread has all the necessary data, while avoiding the need
-		 *			to manage Camera itself on the core thread.
-		 *
-		 * @note	You generally need to update the core thread with a new proxy whenever core 
-		 *			dirty flag is set.
-		 */
-		CameraProxyPtr _createProxy() const;
-
-		/**
-		 * @brief	Returns the currently active proxy object, if any.
-		 */
-		CameraProxyPtr _getActiveProxy() const { return mActiveProxy; }
-
-		/**
-		 * @brief	Changes the currently active proxy object. 
-		 */
-		void _setActiveProxy(const CameraProxyPtr& proxy) { mActiveProxy = proxy; }
-
 	protected:
+		CameraHandlerBase(RenderTargetPtr target = nullptr,
+			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+
 		/**
 		 * @brief	Calculate projection parameters that are used when constructing the projection matrix.
 		 */
@@ -488,12 +446,16 @@ namespace BansheeEngine
 		virtual void invalidateFrustum() const;
 
 		/**
-		 * @brief	Marks the core data as dirty.
+		 * @brief	Returns a rectangle that defines the viewport position and size, in pixels.
 		 */
-		void markCoreDirty() { mCoreDirtyFlags = 0xFFFFFFFF; }
+		virtual Rect2I getViewportRect() const = 0;
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		virtual void _markCoreDirty() { }
 
     protected:
-		ViewportPtr mViewport; /**< Viewport that describes 2D rendering surface. */
 		UINT64 mLayers; /**< Bitfield that can be used for filtering what objects the camera sees. */
 
 		Vector3 mPosition; /**< World space position. */
@@ -513,9 +475,6 @@ namespace BansheeEngine
 		bool mFrustumExtentsManuallySet; /**< Are frustum extents manually set. */
 		bool mIgnoreSceneRenderables; /**< Should the camera ignore renderable components. */
 
-		UINT32 mCoreDirtyFlags; /**< True when internal data has changed and core thread wasn't yet informed. */
-		CameraProxyPtr mActiveProxy; /**< Active core proxy if any. */
-
 		mutable Matrix4 mProjMatrixRS; /**< Cached render-system specific projection matrix. */
 		mutable Matrix4 mProjMatrix; /**< Cached projection matrix that determines how are 3D points projected to a 2D viewport. */
 		mutable Matrix4 mViewMatrix; /**< Cached view matrix that determines camera position/orientation. */
@@ -529,6 +488,93 @@ namespace BansheeEngine
 		mutable bool mRecalcView; /**< Should view matrix be recalculated. */
 		mutable float mLeft, mRight, mTop, mBottom; /**< Frustum extents. */
 		mutable AABox mBoundingBox; /**< Frustum bounding box. */
+     };
+
+	/**
+	 * @copydoc	CameraHandlerBase
+	 */
+	class BS_EXPORT CameraHandlerCore : public CoreObjectCore, public CameraHandlerBase
+	{
+	public:
+		~CameraHandlerCore();
+
+		/**
+		 * @brief	Returns the viewport used by the camera.
+		 */	
+		SPtr<ViewportCore> getViewport() const { return mViewport; }
+
+	protected:
+		friend class CameraHandler;
+
+		CameraHandlerCore(SPtr<RenderTargetCore> target = nullptr,
+			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+
+		/**
+		 * @copydoc	CoreObjectCore::initialize
+		 */
+		void initialize();
+
+		/**
+		 * @copydoc	CameraHandlerBase
+		 */
+		virtual Rect2I getViewportRect() const;
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		void syncToCore(const CoreSyncData& data);
+
+		SPtr<ViewportCore> mViewport;
+	};
+
+	/**
+	 * @copydoc	CameraHandlerBase
+	 */
+	class BS_EXPORT CameraHandler : public IReflectable, public CoreObject, public CameraHandlerBase
+    {
+    public:
+		/**
+		 * @brief	Returns the viewport used by the camera.
+		 */	
+		ViewportPtr getViewport() const { return mViewport; }
+
+		/**
+		 * @brief	Retrieves an implementation of a shader usable only from the
+		 *			core thread.
+		 */
+		SPtr<CameraHandlerCore> getCore() const;
+
+		/**
+		 * @brief	Creates a new camera that renders to the specified portion of the provided render target.
+		 */
+		static CameraHandlerPtr create(RenderTargetPtr target = nullptr,
+			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+
+	protected:
+		CameraHandler(RenderTargetPtr target = nullptr,
+			float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
+
+		/**
+		 * @copydoc	CameraHandlerBase
+		 */
+		virtual Rect2I getViewportRect() const;
+
+		/**
+		 * @copydoc	CoreObject::createCore
+		 */
+		SPtr<CoreObjectCore> createCore() const;
+
+		/**
+		 * @copydoc	CoreObject::markCoreDirty
+		 */
+		void _markCoreDirty();
+
+		/**
+		 * @copydoc	CoreObject::syncToCore
+		 */
+		CoreSyncData syncToCore(FrameAlloc* allocator);
+
+		ViewportPtr mViewport; /**< Viewport that describes 2D rendering surface. */
 
 		/************************************************************************/
 		/* 								RTTI		                     		*/

+ 1 - 1
BansheeEngine/Include/BsCameraHandlerRTTI.h

@@ -115,7 +115,7 @@ namespace BansheeEngine
 
 		virtual std::shared_ptr<IReflectable> newRTTIObject()
 		{
-			return bs_shared_ptr<CameraHandler>();
+			return CameraHandler::create();
 		}
 	};
 }

+ 1 - 0
BansheeEngine/Include/BsPrerequisites.h

@@ -82,6 +82,7 @@ namespace BansheeEngine
 	class DrawHelper;
 	class CameraHandler;
 	class RenderableHandler;
+	class CameraHandlerCore;
 
 	// 2D
 	class TextSprite;

+ 0 - 5
BansheeEngine/Include/BsSceneManager.h

@@ -70,11 +70,6 @@ namespace BansheeEngine
 		 * @brief	Triggered whenever a renderable is removed from a SceneObject.
 		 */
 		Event<void(const RenderableHandlerPtr&)> onRenderableRemoved;
-
-		/**
-		 * @brief	Triggered whenever a camera is removed from a SceneObject.
-		 */
-		Event<void(const CameraHandlerPtr&)> onCameraRemoved;
 	};
 
 	/**

+ 7 - 1
BansheeEngine/Source/BsCamera.cpp

@@ -18,13 +18,14 @@ namespace BansheeEngine
 	Camera::Camera(const HSceneObject& parent, RenderTargetPtr target, float left, float top, float width, float height)
 		: Component(parent), mLastUpdateHash(std::numeric_limits<UINT32>::max())
     {
-		mInternal = bs_shared_ptr<CameraHandler>(target, left, top, width, height);
+		mInternal = CameraHandler::create(target, left, top, width, height);
 
 		setName("Camera");
     }
 
     Camera::~Camera()
     {
+		mInternal->destroy();
     }
 
 	ConvexVolume Camera::getWorldFrustum() const
@@ -55,6 +56,11 @@ namespace BansheeEngine
 		}
 	}
 
+	void Camera::update() 
+	{
+		updateView();
+	}
+
 	RTTITypeBase* Camera::getRTTIStatic()
 	{
 		return CameraRTTI::instance();

+ 208 - 95
BansheeEngine/Source/BsCameraHandler.cpp

@@ -9,16 +9,19 @@
 #include "BsRenderSystem.h"
 #include "BsSceneObject.h"
 #include "BsDebug.h"
+#include "BsRendererManager.h"
+#include "BsRenderer.h"
+#include "BsFrameAlloc.h"
 
 namespace BansheeEngine
 {
-	const float CameraHandler::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
+	const float CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
 
-	CameraHandler::CameraHandler(RenderTargetPtr target, float left, float top, float width, float height)
+	CameraHandlerBase::CameraHandlerBase(RenderTargetPtr target, float left, float top, float width, float height)
 		:mProjType(PT_PERSPECTIVE), mHorzFOV(Radian(Math::PI / 4.0f)), mFarDist(1000.0f),
 		mNearDist(0.05f), mAspect(1.33333333333333f), mOrthoHeight(1000), mRecalcFrustum(true), mRecalcFrustumPlanes(true),
 		mCustomViewMatrix(false), mCustomProjMatrix(false), mFrustumExtentsManuallySet(false), mIgnoreSceneRenderables(false),
-		mPriority(0), mLayers(0xFFFFFFFFFFFFFFFF), mCoreDirtyFlags(0xFFFFFFFF), mRecalcView(true)
+		mPriority(0), mLayers(0xFFFFFFFFFFFFFFFF), mRecalcView(true)
 	{
 		mViewMatrix = Matrix4::ZERO;
 		mProjMatrixRS = Matrix4::ZERO;
@@ -27,40 +30,33 @@ namespace BansheeEngine
 		mProjMatrixInv = Matrix4::ZERO;
 
 		invalidateFrustum();
-
-		target->synchronize();
-		mViewport = bs_shared_ptr<Viewport, PoolAlloc>(target, left, top, width, height);
 	}
 
-	CameraHandler::~CameraHandler()
-	{
-	}
-
-	void CameraHandler::setHorzFOV(const Radian& fov)
+	void CameraHandlerBase::setHorzFOV(const Radian& fov)
 	{
 		mHorzFOV = fov;
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	const Radian& CameraHandler::getHorzFOV() const
+	const Radian& CameraHandlerBase::getHorzFOV() const
 	{
 		return mHorzFOV;
 	}
 
-	void CameraHandler::setFarClipDistance(float farPlane)
+	void CameraHandlerBase::setFarClipDistance(float farPlane)
 	{
 		mFarDist = farPlane;
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	float CameraHandler::getFarClipDistance() const
+	float CameraHandlerBase::getFarClipDistance() const
 	{
 		return mFarDist;
 	}
 
-	void CameraHandler::setNearClipDistance(float nearPlane)
+	void CameraHandlerBase::setNearClipDistance(float nearPlane)
 	{
 		if (nearPlane <= 0)
 		{
@@ -69,57 +65,57 @@ namespace BansheeEngine
 
 		mNearDist = nearPlane;
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	float CameraHandler::getNearClipDistance() const
+	float CameraHandlerBase::getNearClipDistance() const
 	{
 		return mNearDist;
 	}
 
-	const Matrix4& CameraHandler::getProjectionMatrix() const
+	const Matrix4& CameraHandlerBase::getProjectionMatrix() const
 	{
 		updateFrustum();
 
 		return mProjMatrix;
 	}
 
-	const Matrix4& CameraHandler::getProjectionMatrixInv() const
+	const Matrix4& CameraHandlerBase::getProjectionMatrixInv() const
 	{
 		updateFrustum();
 
 		return mProjMatrixInv;
 	}
 
-	const Matrix4& CameraHandler::getProjectionMatrixRS() const
+	const Matrix4& CameraHandlerBase::getProjectionMatrixRS() const
 	{
 		updateFrustum();
 
 		return mProjMatrixRS;
 	}
 
-	const Matrix4& CameraHandler::getProjectionMatrixRSInv() const
+	const Matrix4& CameraHandlerBase::getProjectionMatrixRSInv() const
 	{
 		updateFrustum();
 
 		return mProjMatrixRSInv;
 	}
 
-	const Matrix4& CameraHandler::getViewMatrix() const
+	const Matrix4& CameraHandlerBase::getViewMatrix() const
 	{
 		updateView();
 
 		return mViewMatrix;
 	}
 
-	const Matrix4& CameraHandler::getViewMatrixInv() const
+	const Matrix4& CameraHandlerBase::getViewMatrixInv() const
 	{
 		updateView();
 
 		return mViewMatrixInv;
 	}
 
-	const ConvexVolume& CameraHandler::getFrustum() const
+	const ConvexVolume& CameraHandlerBase::getFrustum() const
 	{
 		// Make any pending updates to the calculated frustum planes
 		updateFrustumPlanes();
@@ -127,7 +123,7 @@ namespace BansheeEngine
 		return mFrustum;
 	}
 
-	ConvexVolume CameraHandler::getWorldFrustum() const
+	ConvexVolume CameraHandlerBase::getWorldFrustum() const
 	{
 		const Vector<Plane>& frustumPlanes = getFrustum().getPlanes();
 		Matrix4 worldMatrix;
@@ -144,7 +140,7 @@ namespace BansheeEngine
 		return ConvexVolume(worldPlanes);
 	}
 
-	void CameraHandler::calcProjectionParameters(float& left, float& right, float& bottom, float& top) const
+	void CameraHandlerBase::calcProjectionParameters(float& left, float& right, float& bottom, float& top) const
 	{
 		if (mCustomProjMatrix)
 		{
@@ -207,7 +203,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void CameraHandler::updateFrustum() const
+	void CameraHandlerBase::updateFrustum() const
 	{
 		if (isFrustumOutOfDate())
 		{
@@ -232,8 +228,8 @@ namespace BansheeEngine
 					if (mFarDist == 0)
 					{
 						// Infinite far plane
-						q = CameraHandler::INFINITE_FAR_PLANE_ADJUST - 1;
-						qn = mNearDist * (CameraHandler::INFINITE_FAR_PLANE_ADJUST - 2);
+						q = CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 1;
+						qn = mNearDist * (CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 2);
 					}
 					else
 					{
@@ -261,8 +257,8 @@ namespace BansheeEngine
 					if (mFarDist == 0)
 					{
 						// Can not do infinite far plane here, avoid divided zero only
-						q = -CameraHandler::INFINITE_FAR_PLANE_ADJUST / mNearDist;
-						qn = -CameraHandler::INFINITE_FAR_PLANE_ADJUST - 1;
+						q = -CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST / mNearDist;
+						qn = -CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 1;
 					}
 					else
 					{
@@ -319,12 +315,12 @@ namespace BansheeEngine
 		}
 	}
 
-	bool CameraHandler::isFrustumOutOfDate() const
+	bool CameraHandlerBase::isFrustumOutOfDate() const
 	{
 		return mRecalcFrustum;
 	}
 
-	void CameraHandler::updateView() const
+	void CameraHandlerBase::updateView() const
 	{
 		if (!mCustomViewMatrix && mRecalcView)
 		{
@@ -334,7 +330,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void CameraHandler::updateFrustumPlanes() const
+	void CameraHandlerBase::updateFrustumPlanes() const
 	{
 		updateFrustum();
 
@@ -384,38 +380,38 @@ namespace BansheeEngine
 		}
 	}
 
-	float CameraHandler::getAspectRatio(void) const
+	float CameraHandlerBase::getAspectRatio(void) const
 	{
 		return mAspect;
 	}
 
-	void CameraHandler::setAspectRatio(float r)
+	void CameraHandlerBase::setAspectRatio(float r)
 	{
 		mAspect = r;
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	const AABox& CameraHandler::getBoundingBox() const
+	const AABox& CameraHandlerBase::getBoundingBox() const
 	{
 		updateFrustum();
 
 		return mBoundingBox;
 	}
 
-	void CameraHandler::setProjectionType(ProjectionType pt)
+	void CameraHandlerBase::setProjectionType(ProjectionType pt)
 	{
 		mProjType = pt;
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	ProjectionType CameraHandler::getProjectionType() const
+	ProjectionType CameraHandlerBase::getProjectionType() const
 	{
 		return mProjType;
 	}
 
-	void CameraHandler::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
+	void CameraHandlerBase::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
 	{
 		mCustomViewMatrix = enable;
 		if (enable)
@@ -425,10 +421,10 @@ namespace BansheeEngine
 			mViewMatrixInv = mViewMatrix.inverseAffine();
 		}
 
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
+	void CameraHandlerBase::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
 	{
 		mCustomProjMatrix = enable;
 
@@ -436,45 +432,45 @@ namespace BansheeEngine
 			mProjMatrix = projMatrix;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::setOrthoWindow(float w, float h)
+	void CameraHandlerBase::setOrthoWindow(float w, float h)
 	{
 		mOrthoHeight = h;
 		mAspect = w / h;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::setOrthoWindowHeight(float h)
+	void CameraHandlerBase::setOrthoWindowHeight(float h)
 	{
 		mOrthoHeight = h;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::setOrthoWindowWidth(float w)
+	void CameraHandlerBase::setOrthoWindowWidth(float w)
 	{
 		mOrthoHeight = w / mAspect;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	float CameraHandler::getOrthoWindowHeight() const
+	float CameraHandlerBase::getOrthoWindowHeight() const
 	{
 		return mOrthoHeight;
 	}
 
-	float CameraHandler::getOrthoWindowWidth() const
+	float CameraHandlerBase::getOrthoWindowWidth() const
 	{
 		return mOrthoHeight * mAspect;
 	}
 
-	void CameraHandler::setFrustumExtents(float left, float right, float top, float bottom)
+	void CameraHandlerBase::setFrustumExtents(float left, float right, float top, float bottom)
 	{
 		mFrustumExtentsManuallySet = true;
 		mLeft = left;
@@ -483,18 +479,18 @@ namespace BansheeEngine
 		mBottom = bottom;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::resetFrustumExtents()
+	void CameraHandlerBase::resetFrustumExtents()
 	{
 		mFrustumExtentsManuallySet = false;
 
 		invalidateFrustum();
-		markCoreDirty();
+		_markCoreDirty();
 	}
 
-	void CameraHandler::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
+	void CameraHandlerBase::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
 	{
 		updateFrustum();
 
@@ -504,103 +500,107 @@ namespace BansheeEngine
 		outbottom = mBottom;
 	}
 
-	void CameraHandler::setPosition(const Vector3& position)
+	void CameraHandlerBase::setPosition(const Vector3& position)
 	{
 		mPosition = position;
 
 		mRecalcView = true;
 	}
 
-	void CameraHandler::setRotation(const Quaternion& rotation)
+	void CameraHandlerBase::setRotation(const Quaternion& rotation)
 	{
 		mRotation = rotation;
 
 		mRecalcView = true;
 	}
 
-	void CameraHandler::invalidateFrustum() const
+	void CameraHandlerBase::invalidateFrustum() const
 	{
 		mRecalcFrustum = true;
 		mRecalcFrustumPlanes = true;
 	}
 
-	Vector2I CameraHandler::worldToScreenPoint(const Vector3& worldPoint) const
+	Vector2I CameraHandlerBase::worldToScreenPoint(const Vector3& worldPoint) const
 	{
 		Vector2 clipPoint = worldToClipPoint(worldPoint);
 		return clipToScreenPoint(clipPoint);
 	}
 
-	Vector2 CameraHandler::worldToClipPoint(const Vector3& worldPoint) const
+	Vector2 CameraHandlerBase::worldToClipPoint(const Vector3& worldPoint) const
 	{
 		Vector3 viewPoint = worldToViewPoint(worldPoint);
 		return viewToClipPoint(viewPoint);
 	}
 
-	Vector3 CameraHandler::worldToViewPoint(const Vector3& worldPoint) const
+	Vector3 CameraHandlerBase::worldToViewPoint(const Vector3& worldPoint) const
 	{
 		return getViewMatrix().multiplyAffine(worldPoint);
 	}
 
-	Vector3 CameraHandler::screenToWorldPoint(const Vector2I& screenPoint) const
+	Vector3 CameraHandlerBase::screenToWorldPoint(const Vector2I& screenPoint) const
 	{
 		Vector2 clipPoint = screenToClipPoint(screenPoint);
 		return clipToWorldPoint(clipPoint);
 	}
 
-	Vector3 CameraHandler::screenToViewPoint(const Vector2I& screenPoint) const
+	Vector3 CameraHandlerBase::screenToViewPoint(const Vector2I& screenPoint) const
 	{
 		Vector2 clipPoint = screenToClipPoint(screenPoint);
 		return clipToViewPoint(clipPoint);
 	}
 
-	Vector2 CameraHandler::screenToClipPoint(const Vector2I& screenPoint) const
+	Vector2 CameraHandlerBase::screenToClipPoint(const Vector2I& screenPoint) const
 	{
+		Rect2I viewport = getViewportRect();
+
 		Vector2 clipPoint;
-		clipPoint.x = (float)(((screenPoint.x - mViewport->getX()) / (float)mViewport->getWidth()) * 2.0f - 1.0f);
-		clipPoint.y = (float)((1.0f - ((screenPoint.y - mViewport->getY()) / (float)mViewport->getHeight())) * 2.0f - 1.0f);
+		clipPoint.x = (float)(((screenPoint.x - viewport.x) / (float)viewport.width) * 2.0f - 1.0f);
+		clipPoint.y = (float)((1.0f - ((screenPoint.y - viewport.y) / (float)viewport.height)) * 2.0f - 1.0f);
 
 		return clipPoint;
 	}
 
-	Vector3 CameraHandler::viewToWorldPoint(const Vector3& viewPoint) const
+	Vector3 CameraHandlerBase::viewToWorldPoint(const Vector3& viewPoint) const
 	{
 		return getViewMatrix().inverseAffine().multiplyAffine(viewPoint);
 	}
 
-	Vector2I CameraHandler::viewToScreenPoint(const Vector3& viewPoint) const
+	Vector2I CameraHandlerBase::viewToScreenPoint(const Vector3& viewPoint) const
 	{
 		Vector2 clipPoint = viewToClipPoint(viewPoint);
 		return clipToScreenPoint(clipPoint);
 	}
 
-	Vector2 CameraHandler::viewToClipPoint(const Vector3& viewPoint) const
+	Vector2 CameraHandlerBase::viewToClipPoint(const Vector3& viewPoint) const
 	{
 		Vector3 projPoint = projectPoint(viewPoint);
 
 		return Vector2(projPoint.x, projPoint.y);
 	}
 
-	Vector3 CameraHandler::clipToWorldPoint(const Vector2& clipPoint) const
+	Vector3 CameraHandlerBase::clipToWorldPoint(const Vector2& clipPoint) const
 	{
 		Vector3 viewPoint = clipToViewPoint(clipPoint);
 		return viewToWorldPoint(viewPoint);
 	}
 
-	Vector3 CameraHandler::clipToViewPoint(const Vector2& clipPoint) const
+	Vector3 CameraHandlerBase::clipToViewPoint(const Vector2& clipPoint) const
 	{
 		return unprojectPoint(Vector3(clipPoint.x, clipPoint.y, 0.5f));
 	}
 
-	Vector2I CameraHandler::clipToScreenPoint(const Vector2& clipPoint) const
+	Vector2I CameraHandlerBase::clipToScreenPoint(const Vector2& clipPoint) const
 	{
+		Rect2I viewport = getViewportRect();
+
 		Vector2I screenPoint;
-		screenPoint.x = Math::roundToInt(mViewport->getX() + ((clipPoint.x + 1.0f) * 0.5f) * mViewport->getWidth());
-		screenPoint.y = Math::roundToInt(mViewport->getY() + (1.0f - (clipPoint.y + 1.0f) * 0.5f) * mViewport->getHeight());
+		screenPoint.x = Math::roundToInt(viewport.x + ((clipPoint.x + 1.0f) * 0.5f) * viewport.width);
+		screenPoint.y = Math::roundToInt(viewport.y + (1.0f - (clipPoint.y + 1.0f) * 0.5f) * viewport.height);
 
 		return screenPoint;
 	}
 
-	Ray CameraHandler::screenPointToRay(const Vector2I& screenPoint) const
+	Ray CameraHandlerBase::screenPointToRay(const Vector2I& screenPoint) const
 	{
 		Vector2 clipPoint = screenToClipPoint(screenPoint);
 
@@ -613,7 +613,7 @@ namespace BansheeEngine
 		return ray;
 	}
 
-	Vector3 CameraHandler::projectPoint(const Vector3& point) const
+	Vector3 CameraHandlerBase::projectPoint(const Vector3& point) const
 	{
 		Vector4 projPoint4(point.x, point.y, point.z, 1.0f);
 		projPoint4 = getProjectionMatrixRS().multiply(projPoint4);
@@ -635,7 +635,7 @@ namespace BansheeEngine
 		return Vector3(projPoint4.x, projPoint4.y, projPoint4.z);
 	}
 
-	Vector3 CameraHandler::unprojectPoint(const Vector3& point) const
+	Vector3 CameraHandlerBase::unprojectPoint(const Vector3& point) const
 	{
 		Vector4 dir4(point.x, point.y, 0.95f, 1.0f); // 0.95f arbitrary
 		dir4 = getProjectionMatrixRS().inverse().multiply(dir4);
@@ -674,21 +674,134 @@ namespace BansheeEngine
 		return Vector3(dir.x, dir.y, dir.z);
 	}
 
-	CameraProxyPtr CameraHandler::_createProxy() const
+	CameraHandlerCore::~CameraHandlerCore()
 	{
-		CameraProxyPtr proxy = bs_shared_ptr<CameraProxy>();
-		proxy->layer = mLayers;
-		proxy->priority = mPriority;
-		proxy->projMatrix = getProjectionMatrixRS();
-		proxy->viewMatrix = getViewMatrix();
-		proxy->worldMatrix.setTRS(mPosition, mRotation, Vector3::ONE);
-		proxy->renderTarget = mViewport->getTarget()->getCore();
-		proxy->viewport = mViewport->clone();
-		proxy->frustum = getFrustum();
-		proxy->ignoreSceneRenderables = mIgnoreSceneRenderables;
-		proxy->worldPosition = mPosition;
+		RendererManager::instance().getActive()->_notifyCameraRemoved(this);
+	}
 
-		return proxy;
+	CameraHandlerCore::CameraHandlerCore(SPtr<RenderTargetCore> target, float left, float top, float width, float height)
+	{
+		mViewport = ViewportCore::create(target, left, top, width, height);
+	}
+
+	void CameraHandlerCore::initialize()
+	{
+		RendererManager::instance().getActive()->_notifyCameraAdded(this);
+
+		CoreObjectCore::initialize();
+	}
+
+	Rect2I CameraHandlerCore::getViewportRect() const
+	{
+		return mViewport->getArea();
+	}
+
+	void CameraHandlerCore::syncToCore(const CoreSyncData& data)
+	{
+		char* dataPtr = (char*)data.getBuffer();
+
+		dataPtr = rttiReadElem(mLayers, dataPtr);
+		dataPtr = rttiReadElem(mPosition, dataPtr);
+		dataPtr = rttiReadElem(mRotation, dataPtr);
+		dataPtr = rttiReadElem(mProjType, dataPtr);
+		dataPtr = rttiReadElem(mHorzFOV, dataPtr);
+		dataPtr = rttiReadElem(mFarDist, dataPtr);
+		dataPtr = rttiReadElem(mNearDist, dataPtr);
+		dataPtr = rttiReadElem(mAspect, dataPtr);
+		dataPtr = rttiReadElem(mOrthoHeight, dataPtr);
+		dataPtr = rttiReadElem(mPriority, dataPtr);
+		dataPtr = rttiReadElem(mCustomViewMatrix, dataPtr);
+		dataPtr = rttiReadElem(mCustomProjMatrix, dataPtr);
+		dataPtr = rttiReadElem(mFrustumExtentsManuallySet, dataPtr);
+		dataPtr = rttiReadElem(mIgnoreSceneRenderables, dataPtr);
+
+		mRecalcFrustum = true;
+		mRecalcFrustumPlanes = true;
+		mRecalcView = true;
+	}
+
+	CameraHandler::CameraHandler(RenderTargetPtr target, float left, float top, float width, float height)
+	{
+		target->synchronize();
+		mViewport = Viewport::create(target, left, top, width, height);
+	}
+
+	SPtr<CameraHandlerCore> CameraHandler::getCore() const
+	{
+		return std::static_pointer_cast<CameraHandlerCore>(mCoreSpecific);
+	}
+
+	CameraHandlerPtr CameraHandler::create(RenderTargetPtr target, float left, float top, float width, float height)
+	{
+		CameraHandler* handler = new (bs_alloc<CameraHandler>()) CameraHandler(target, left, top, width, height);
+		CameraHandlerPtr handlerPtr = bs_core_ptr<CameraHandler, GenAlloc>(handler);
+		handlerPtr->_setThisPtr(handlerPtr);
+		handlerPtr->initialize();
+
+		return handlerPtr;
+	}
+
+	SPtr<CoreObjectCore> CameraHandler::createCore() const
+	{
+		Rect2 normArea = mViewport->getNormArea();
+
+		CameraHandlerCore* handler = new (bs_alloc<CameraHandlerCore>()) 
+			CameraHandlerCore(mViewport->getTarget()->getCore(), normArea.x, normArea.y, normArea.width, normArea.height);
+		SPtr<CameraHandlerCore> handlerPtr = bs_shared_ptr<CameraHandlerCore, GenAlloc>(handler);
+		handlerPtr->_setThisPtr(handlerPtr);
+
+		return handlerPtr;
+	}
+
+	Rect2I CameraHandler::getViewportRect() const
+	{
+		return mViewport->getArea();
+	}
+
+	CoreSyncData CameraHandler::syncToCore(FrameAlloc* allocator)
+	{
+		UINT32 size = 0;
+		size += rttiGetElemSize(mLayers);
+		size += rttiGetElemSize(mPosition);
+		size += rttiGetElemSize(mRotation);
+		size += rttiGetElemSize(mProjType);
+		size += rttiGetElemSize(mHorzFOV);
+		size += rttiGetElemSize(mFarDist);
+		size += rttiGetElemSize(mNearDist);
+		size += rttiGetElemSize(mAspect);
+		size += rttiGetElemSize(mOrthoHeight);
+		size += rttiGetElemSize(mPriority);
+
+		size += rttiGetElemSize(mCustomViewMatrix);
+		size += rttiGetElemSize(mCustomProjMatrix);
+
+		size += rttiGetElemSize(mFrustumExtentsManuallySet);
+		size += rttiGetElemSize(mIgnoreSceneRenderables);
+
+		UINT8* buffer = allocator->alloc(size);
+
+		char* dataPtr = (char*)buffer;
+		dataPtr = rttiWriteElem(mLayers, dataPtr);
+		dataPtr = rttiWriteElem(mPosition, dataPtr);
+		dataPtr = rttiWriteElem(mRotation, dataPtr);
+		dataPtr = rttiWriteElem(mProjType, dataPtr);
+		dataPtr = rttiWriteElem(mHorzFOV, dataPtr);
+		dataPtr = rttiWriteElem(mFarDist, dataPtr);
+		dataPtr = rttiWriteElem(mNearDist, dataPtr);
+		dataPtr = rttiWriteElem(mAspect, dataPtr);
+		dataPtr = rttiWriteElem(mOrthoHeight, dataPtr);
+		dataPtr = rttiWriteElem(mPriority, dataPtr);
+		dataPtr = rttiWriteElem(mCustomViewMatrix, dataPtr);
+		dataPtr = rttiWriteElem(mCustomProjMatrix, dataPtr);
+		dataPtr = rttiWriteElem(mFrustumExtentsManuallySet, dataPtr);
+		dataPtr = rttiWriteElem(mIgnoreSceneRenderables, dataPtr);
+
+		return CoreSyncData(buffer, size);
+	}
+
+	void CameraHandler::_markCoreDirty()
+	{
+		markCoreDirty();
 	}
 
 	RTTITypeBase* CameraHandler::getRTTIStatic()

+ 28 - 45
BansheeRenderer/Include/BsBansheeRenderer.h

@@ -31,7 +31,15 @@ namespace BansheeEngine
 		struct RenderTargetData
 		{
 			SPtr<RenderTargetCore> target;
-			Vector<CameraProxyPtr> cameras;
+			Vector<const CameraHandlerCore*> cameras;
+		};
+
+		/**
+		 * @brief	Various data used by a single camera.
+		 */
+		struct CameraData
+		{
+			RenderQueuePtr renderQueue;
 		};
 
 	public:
@@ -59,6 +67,16 @@ namespace BansheeEngine
 		virtual void _onDeactivated();
 
 	private:
+		/**
+		 * @copydoc	Renderer::_notifyCameraAdded
+		 */
+		virtual void _notifyCameraAdded(const CameraHandlerCore* camera);
+
+		/**
+		 * @copydoc	Renderer::_notifyCameraRemoved
+		 */
+		virtual void _notifyCameraRemoved(const CameraHandlerCore* camera);
+
 		/**
 		 * @brief	Adds a new renderable proxy which will be considered for rendering next frame.
 		 *
@@ -85,33 +103,6 @@ namespace BansheeEngine
 		 */
 		void updateRenderableProxy(RenderableProxyPtr proxy, Matrix4 localToWorld);
 
-		/**
-		 * @brief	Adds a new camera proxy will be used for rendering renderable proxy objects.
-		 *
-		 * @note	Core thread only.
-		 */
-		void addCameraProxy(CameraProxyPtr proxy);
-
-		/**
-		 * @brief	Removes an existing camera proxy, meaning the camera will no longer be rendered from.
-		 * 
-		 * @note	Core thread only.
-		 */
-		void removeCameraProxy(CameraProxyPtr proxy);
-
-		/**
-		 * @brief	Updates an existing camera proxy with new data. This includes data that changes
-		 *			often. For other data it is best to remove old proxy and add new one.
-		 *
-		 * @param	proxy			Proxy to update.
-		 * @param	worldPosition	World position of the camera.
-		 * @param	worldMatrix		World transform matrix of the camera.
-		 * @param	viewMatrix		View transform matrix of the camera.
-		 *
-		 * @note	Core thread only.
-		 */
-		void updateCameraProxy(CameraProxyPtr proxy, Vector3 worldPosition, Matrix4 worldMatrix, Matrix4 viewMatrix);
-
 		/**
 		 * @brief	Adds a new set of objects to the cameras render queue.
 		 *
@@ -120,7 +111,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Core thread only.
 		 */
-		void addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue);
+		void addToRenderQueue(const SPtr<CameraHandlerCore>& proxy, RenderQueuePtr renderQueue);
 
 		/**
 		 * @brief	Performs rendering over all camera proxies.
@@ -134,12 +125,12 @@ namespace BansheeEngine
 		/**
 		 * @brief	Renders all objects visible by the provided camera.
 		 *
-		 * @param	cameraProxy		Camera used for determining destination render target and visibility.
+		 * @param	camera			Camera used for determining destination render target and visibility.
 		 * @param	renderQueue		Optionally non-empty queue of manually added objects to render.
 		 *
 		 * @note	Core thread only.
 		 */
-		virtual void render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue);
+		virtual void render(const CameraHandlerCore& camera, const RenderQueuePtr& renderQueue);
 
 		/**
 		 * @brief	Called by the scene manager whenever a Renderable component has been
@@ -148,26 +139,19 @@ namespace BansheeEngine
 		void renderableRemoved(const RenderableHandlerPtr& renderable);
 
 		/**
-		 * @brief	Called by the scene manager whenever a Camera component has been
-		 *			removed from the scene.
-		 */
-		void cameraRemoved(const CameraHandlerPtr& camera);
-
-		/**
-		 * @brief	Creates a controller used for rendering.
+		 * @brief	Creates data used by the renderer on the core thread.
 		 */
-		void createController();
+		void initializeCore();
 
 		/**
-		 * @brief	Destroys a controller used for rendering.
+		 * @brief	Destroys data used by the renderer on the core thread.
 		 */
-		static void destroyController(LitTexRenderableController* controller);
+		void destroyCore();
 
 		Vector<RenderableProxyPtr> mDeletedRenderableProxies;
-		Vector<CameraProxyPtr> mDeletedCameraProxies;
 
-		UnorderedMap<UINT64, CameraProxyPtr> mCameraProxies;
-		Vector<RenderTargetData> mRenderTargets;
+		Vector<RenderTargetData> mRenderTargets; // Core thread
+		UnorderedMap<const CameraHandlerCore*, CameraData> mCameraData; // Core thread
 
 		Vector<RenderableElement*> mRenderableElements;
 		Vector<Matrix4> mWorldTransforms;
@@ -176,6 +160,5 @@ namespace BansheeEngine
 		LitTexRenderableController* mLitTexHandler;
 
 		HEvent mRenderableRemovedConn;
-		HEvent mCameraRemovedConn;
 	};
 }

+ 77 - 138
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -35,13 +35,11 @@ namespace BansheeEngine
 	BansheeRenderer::BansheeRenderer()
 	{
 		mRenderableRemovedConn = gSceneManager().onRenderableRemoved.connect(std::bind(&BansheeRenderer::renderableRemoved, this, _1));
-		mCameraRemovedConn = gSceneManager().onCameraRemoved.connect(std::bind(&BansheeRenderer::cameraRemoved, this, _1));
 	}
 
 	BansheeRenderer::~BansheeRenderer()
 	{
 		mRenderableRemovedConn.disconnect();
-		mCameraRemovedConn.disconnect();
 	}
 
 	const String& BansheeRenderer::getName() const
@@ -54,25 +52,29 @@ namespace BansheeEngine
 	{
 		Renderer::_onActivated();
 
-		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::createController, this));
+		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::initializeCore, this));
 	}
 
 	void BansheeRenderer::_onDeactivated()
 	{
 		Renderer::_onDeactivated();
 
-		gCoreAccessor().queueCommand(std::bind(&destroyController, mLitTexHandler));
+		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::destroyCore, this));
+		gCoreAccessor().submitToCoreThread(true);
 	}
 
-	void BansheeRenderer::createController()
+	void BansheeRenderer::initializeCore()
 	{
 		mLitTexHandler = bs_new<LitTexRenderableController>();
 	}
 
-	void BansheeRenderer::destroyController(LitTexRenderableController* controller)
+	void BansheeRenderer::destroyCore()
 	{
-		if (controller != nullptr)
-			bs_delete(controller);
+		if (mLitTexHandler != nullptr)
+			bs_delete(mLitTexHandler);
+
+		mRenderTargets.clear();
+		mCameraData.clear();
 	}
 
 	void BansheeRenderer::addRenderableProxy(RenderableProxyPtr proxy)
@@ -125,68 +127,15 @@ namespace BansheeEngine
 		}
 	}
 
-	void BansheeRenderer::addCameraProxy(CameraProxyPtr proxy)
-	{
-		SPtr<RenderTargetCore> renderTarget = proxy->renderTarget;
-		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
-
-		if (findIter != mRenderTargets.end())
-		{
-			proxy->renderQueue = bs_shared_ptr<RenderQueue>();
-
-			findIter->cameras.push_back(proxy);
-		}
-		else
-		{
-			mRenderTargets.push_back(RenderTargetData());
-			RenderTargetData& renderTargetData = mRenderTargets.back();
-
-			proxy->renderQueue = bs_shared_ptr<RenderQueue>();
-			renderTargetData.target = renderTarget;
-			renderTargetData.cameras.push_back(proxy);
-		}
-
-		// Sort everything based on priority
-		auto cameraComparer = [&](const CameraProxyPtr& a, const CameraProxyPtr& b) { return a->priority > b->priority; };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) 
-		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
-		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
-
-		for (auto& camerasPerTarget : mRenderTargets)
-		{
-			Vector<CameraProxyPtr>& cameras = camerasPerTarget.cameras;
-
-			std::sort(begin(cameras), end(cameras), cameraComparer);
-		}
-
-		proxy->calcWorldFrustum();
-	}
-
-	void BansheeRenderer::removeCameraProxy(CameraProxyPtr proxy)
+	void BansheeRenderer::_notifyCameraAdded(const CameraHandlerCore* camera)
 	{
-		SPtr<RenderTargetCore> renderTarget = proxy->renderTarget;
-		auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
-
-		if (findIter != mRenderTargets.end())
-		{
-			auto findIter2 = std::find(findIter->cameras.begin(), findIter->cameras.end(), proxy);
-
-			if (findIter2 != findIter->cameras.end())
-			{
-				findIter->cameras.erase(findIter2);
-			}
-
-			if (findIter->cameras.size() == 0)
-				mRenderTargets.erase(findIter);
-		}
+		CameraData& camData = mCameraData[camera];
+		camData.renderQueue = bs_shared_ptr<RenderQueue>();
 	}
 
-	void BansheeRenderer::updateCameraProxy(CameraProxyPtr proxy, Vector3 worldPosition, Matrix4 worldMatrix, Matrix4 viewMatrix)
+	void BansheeRenderer::_notifyCameraRemoved(const CameraHandlerCore* camera)
 	{
-		proxy->viewMatrix = viewMatrix;
-		proxy->worldPosition = worldPosition;
-		proxy->worldMatrix = worldMatrix;
-		proxy->calcWorldFrustum();
+		mCameraData.erase(camera);
 	}
 
 	void BansheeRenderer::renderableRemoved(const RenderableHandlerPtr& renderable)
@@ -197,23 +146,15 @@ namespace BansheeEngine
 		}
 	}
 
-	void BansheeRenderer::cameraRemoved(const CameraHandlerPtr& camera)
-	{
-		if (camera->_getActiveProxy() != nullptr)
-		{
-			mDeletedCameraProxies.push_back(camera->_getActiveProxy());
-		}
-	}
-
 	void BansheeRenderer::renderAll() 
 	{
 		gSceneManager().updateRenderableTransforms();
 
 		// Remove proxies from deleted Renderables
-		for (auto& proxy : mDeletedRenderableProxies)
+		for (auto& camera : mDeletedRenderableProxies)
 		{
-			if (proxy != nullptr)
-				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, proxy));
+			if (camera != nullptr)
+				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeRenderableProxy, this, camera));
 		}
 
 		// Add or update Renderable proxies
@@ -274,47 +215,6 @@ namespace BansheeEngine
 			renderable->_markCoreClean();
 		}
 
-		// Remove proxies from deleted Cameras
-		for (auto& proxy : mDeletedCameraProxies)
-		{
-			if (proxy != nullptr)
-				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeCameraProxy, this, proxy));
-		}
-
-		// Add or update Camera proxies
-		const Vector<SceneCameraData>& allCameras = gSceneManager().getAllCameras();
-		for (auto& cameraData : allCameras)
-		{
-			CameraHandlerPtr camera = cameraData.camera;
-			HSceneObject cameraSO = cameraData.sceneObject;
-
-			if (camera->_isCoreDirty())
-			{
-				CameraProxyPtr proxy = camera->_getActiveProxy();
-
-				if (proxy != nullptr)
-					gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::removeCameraProxy, this, proxy));
-
-				proxy = camera->_createProxy();
-				camera->_setActiveProxy(proxy);
-
-				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addCameraProxy, this, proxy));
-
-				camera->_markCoreClean();
-				dirtySceneObjects.push_back(cameraSO);
-			}
-			else if (cameraSO->_isCoreDirty())
-			{
-				CameraProxyPtr proxy = camera->_getActiveProxy();
-				assert(proxy != nullptr);
-
-				gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::updateCameraProxy, this, 
-					proxy, cameraSO->getWorldPosition(), cameraSO->getWorldTfrm(), camera->getViewMatrix()));
-
-				dirtySceneObjects.push_back(cameraSO);
-			}
-		}
-
 		// Mark scene objects clean
 		for (auto& dirtySO : dirtySceneObjects)
 		{
@@ -322,6 +222,7 @@ namespace BansheeEngine
 		}
 
 		// Populate direct draw lists
+		const Vector<SceneCameraData>& allCameras = gSceneManager().getAllCameras();
 		for (auto& cameraData : allCameras)
 		{
 			CameraHandlerPtr camera = cameraData.camera;
@@ -367,15 +268,15 @@ namespace BansheeEngine
 				renderQueue->add(materialProxy, meshCore, subMesh, distanceToCamera);
 			}
 
-			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->_getActiveProxy(), renderQueue));
+			gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::addToRenderQueue, this, camera->getCore(), renderQueue));
 		}
 
 		gCoreAccessor().queueCommand(std::bind(&BansheeRenderer::renderAllCore, this, gTime().getTime()));
 	}
 
-	void BansheeRenderer::addToRenderQueue(CameraProxyPtr proxy, RenderQueuePtr renderQueue)
+	void BansheeRenderer::addToRenderQueue(const SPtr<CameraHandlerCore>& camera, RenderQueuePtr renderQueue)
 	{
-		RenderQueuePtr cameraRenderQueue = proxy->renderQueue;
+		RenderQueuePtr cameraRenderQueue = mCameraData[camera.get()].renderQueue;
 		cameraRenderQueue->add(*renderQueue);
 	}
 
@@ -386,56 +287,94 @@ namespace BansheeEngine
 		// Update global hardware buffers
 		mLitTexHandler->updateGlobalBuffers(time);
 
+		// Sort cameras by render target
+		for (auto& cameraData : mCameraData)
+		{
+			const CameraHandlerCore* camera = cameraData.first;
+			SPtr<RenderTargetCore> renderTarget = camera->getViewport()->getTarget();
+
+			auto findIter = std::find_if(mRenderTargets.begin(), mRenderTargets.end(), [&](const RenderTargetData& x) { return x.target == renderTarget; });
+			if (findIter != mRenderTargets.end())
+			{
+				findIter->cameras.push_back(camera);
+			}
+			else
+			{
+				mRenderTargets.push_back(RenderTargetData());
+				RenderTargetData& renderTargetData = mRenderTargets.back();
+
+				renderTargetData.target = renderTarget;
+				renderTargetData.cameras.push_back(camera);
+			}
+		}
+
+		// Sort everything based on priority
+		auto cameraComparer = [&](const CameraHandlerCore* a, const CameraHandlerCore* b) { return a->getPriority() > b->getPriority(); };
+		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b)
+		{ return a.target->getProperties().getPriority() > b.target->getProperties().getPriority(); };
+		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
+
+		for (auto& camerasPerTarget : mRenderTargets)
+		{
+			Vector<const CameraHandlerCore*>& cameras = camerasPerTarget.cameras;
+
+			std::sort(begin(cameras), end(cameras), cameraComparer);
+		}
+
 		// Render everything, target by target
 		for (auto& renderTargetData : mRenderTargets)
 		{
 			SPtr<RenderTargetCore> target = renderTargetData.target;
-			Vector<CameraProxyPtr>& cameras = renderTargetData.cameras;
+			Vector<const CameraHandlerCore*>& cameras = renderTargetData.cameras;
 
 			RenderSystem::instance().beginFrame();
 
 			for(auto& camera : cameras)
 			{
-				Viewport viewport = camera->viewport;
+				SPtr<ViewportCore> viewport = camera->getViewport();
 				RenderSystem::instance().setRenderTarget(target);
-				RenderSystem::instance().setViewport(viewport.getNormArea());
+				RenderSystem::instance().setViewport(viewport->getNormArea());
 
 				UINT32 clearBuffers = 0;
-				if(viewport.getRequiresColorClear())
+				if(viewport->getRequiresColorClear())
 					clearBuffers |= FBT_COLOR;
 
-				if(viewport.getRequiresDepthClear())
+				if(viewport->getRequiresDepthClear())
 					clearBuffers |= FBT_DEPTH;
 
-				if(viewport.getRequiresStencilClear())
+				if(viewport->getRequiresStencilClear())
 					clearBuffers |= FBT_STENCIL;
 
 				if(clearBuffers != 0)
-					RenderSystem::instance().clearViewport(clearBuffers, viewport.getClearColor(), viewport.getClearDepthValue(), viewport.getClearStencilValue());
+					RenderSystem::instance().clearViewport(clearBuffers, viewport->getClearColor(), viewport->getClearDepthValue(), viewport->getClearStencilValue());
 
-				render(*camera, camera->renderQueue);
+				render(*camera, mCameraData[camera].renderQueue);
 			}
 
 			RenderSystem::instance().endFrame();
 			RenderSystem::instance().swapBuffers(target);
 		}
+
+		mRenderTargets.clear();
 	}
 
-	void BansheeRenderer::render(const CameraProxy& cameraProxy, const RenderQueuePtr& renderQueue) 
+	void BansheeRenderer::render(const CameraHandlerCore& camera, const RenderQueuePtr& renderQueue)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		RenderSystem& rs = RenderSystem::instance();
 
-		Matrix4 projMatrixCstm = cameraProxy.projMatrix;
-		Matrix4 viewMatrixCstm = cameraProxy.viewMatrix;
+		Matrix4 projMatrixCstm = camera.getProjectionMatrixRS();
+		Matrix4 viewMatrixCstm = camera.getViewMatrix();
 
 		Matrix4 viewProjMatrix = projMatrixCstm * viewMatrixCstm;
 
-		onCorePreRenderViewport(cameraProxy);
+		onCorePreRenderViewport(camera);
 
-		if (!cameraProxy.ignoreSceneRenderables)
+		if (!camera.getIgnoreSceneRenderables())
 		{
+			ConvexVolume worldFrustum = camera.getWorldFrustum();
+
 			// Update per-object param buffers and queue render elements
 			for (auto& renderElem : mRenderableElements)
 			{
@@ -457,14 +396,14 @@ namespace BansheeEngine
 				// TODO - This is bound to be a bottleneck at some point. When it is ensure that intersect
 				// methods use vector operations, as it is trivial to update them.
 				const Sphere& boundingSphere = mWorldBounds[renderElem->id].getSphere();
-				if (cameraProxy.worldFrustum.intersects(boundingSphere))
+				if (worldFrustum.intersects(boundingSphere))
 				{
 					// More precise with the box
 					const AABox& boundingBox = mWorldBounds[renderElem->id].getBox();
 
-					if (cameraProxy.worldFrustum.intersects(boundingBox))
+					if (worldFrustum.intersects(boundingBox))
 					{
-						float distanceToCamera = (cameraProxy.worldPosition - boundingBox.getCenter()).length();
+						float distanceToCamera = (camera.getPosition() - boundingBox.getCenter()).length();
 
 						renderQueue->add(renderElem, distanceToCamera);
 					}
@@ -485,6 +424,6 @@ namespace BansheeEngine
 
 		renderQueue->clear();
 
-		onCorePostRenderViewport(cameraProxy);
+		onCorePostRenderViewport(camera);
 	}
 }

+ 0 - 2
BansheeSceneManager/Source/BsBansheeSceneManager.cpp

@@ -63,8 +63,6 @@ namespace BansheeEngine
 			}
 
 			mCachedCameras.erase(findIter);
-
-			onCameraRemoved(cameraHandler);
 		}
 		else if(component->getTypeId() == TID_Renderable)
 		{

+ 1 - 1
SBansheeEngine/Include/BsScriptCamera.h

@@ -94,6 +94,6 @@ namespace BansheeEngine
 		static MonoObject* internal_GetRenderTexture(ScriptCamera* instance);
 		static void internal_SetRenderTexture(ScriptCamera* instance, MonoObject* textureObj);
 
-		CameraHandler* mCameraHandler;
+		SPtr<CameraHandler> mCameraHandler;
 	};
 }

+ 2 - 2
SBansheeEngine/Source/BsScriptCamera.cpp

@@ -14,12 +14,12 @@ namespace BansheeEngine
 	{ 
 		ViewportPtr primaryViewport = gApplication().getPrimaryViewport();
 
-		mCameraHandler = bs_new<CameraHandler>(primaryViewport->getTarget());
+		mCameraHandler = CameraHandler::create(primaryViewport->getTarget());
 	}
 
 	ScriptCamera::~ScriptCamera()
 	{
-		bs_delete(mCameraHandler);
+
 	}
 
 	void ScriptCamera::initRuntimeData()

+ 0 - 2
TODO.txt

@@ -3,10 +3,8 @@
 TODO - CoreObject refactor:
 Resource
  - Material -> Remove MaterialProxy
- - Shader -> Remove ShaderProxy
 
 Also:
- - Make CameraHandler a Coreobject and remove CameraProxy
  - Make RenderableHandler a CoreObject and remove CameraProxy
  - Rename CoreObject initialize_internal and destroy_internal to initializeCore/destroyCore and make them private