diff --git a/code/nel/include/nel/3d/bloom_effect.h b/code/nel/include/nel/3d/bloom_effect.h
index f5da7a4dd..b637fe937 100644
--- a/code/nel/include/nel/3d/bloom_effect.h
+++ b/code/nel/include/nel/3d/bloom_effect.h
@@ -83,7 +83,7 @@ public:
 	// If window size exceeds 256*256 the textures used to apply blur are reinitialized with
 	// 256*256 size. If a dimension is less than 256, the texture is initialized with the nearer
 	// power of 2, lower than this window dimension.
-	void initBloom(UTexture &renderTarget);
+	void initBloom(UTexture *renderTarget);
 	void initBloom();
 
 	// Called at the end of renderAll method in the main loop, recover stretched texture, apply
diff --git a/code/nel/include/nel/3d/stereo_display.h b/code/nel/include/nel/3d/stereo_display.h
index 2f6592b60..aa98dae50 100644
--- a/code/nel/include/nel/3d/stereo_display.h
+++ b/code/nel/include/nel/3d/stereo_display.h
@@ -124,7 +124,7 @@ public:
 	/// Returns non-NULL if a new render target was set
 	virtual UTexture *beginRenderTarget(bool set) = 0;
 	/// Returns true if a render target was fully drawn
-	virtual bool endRenderTarget(bool unset) = 0;
+	virtual bool endRenderTarget() = 0;
 	
 	static const char *getLibraryName(CStereoDeviceInfo::TStereoDeviceLibrary library);
 	static void listDevices(std::vector<CStereoDeviceInfo> &devicesOut);
diff --git a/code/nel/include/nel/3d/stereo_ovr.h b/code/nel/include/nel/3d/stereo_ovr.h
index f25ef10e0..1a4ebf916 100644
--- a/code/nel/include/nel/3d/stereo_ovr.h
+++ b/code/nel/include/nel/3d/stereo_ovr.h
@@ -111,7 +111,7 @@ public:
 	/// Returns non-NULL if a new render target was set, always NULL if not using render targets
 	virtual UTexture *beginRenderTarget(bool set);
 	/// Returns true if a render target was fully drawn, always false if not using render targets
-	virtual bool endRenderTarget(bool unset);
+	virtual bool endRenderTarget();
 
 
 	/// Get the HMD orientation
diff --git a/code/nel/src/3d/bloom_effect.cpp b/code/nel/src/3d/bloom_effect.cpp
index 0bc9c1e41..60b7d36b7 100644
--- a/code/nel/src/3d/bloom_effect.cpp
+++ b/code/nel/src/3d/bloom_effect.cpp
@@ -273,16 +273,15 @@ void CBloomEffect::initTexture(CSmartPtr<ITexture> & tex, bool isMode2D, uint32
 
 void CBloomEffect::initBloom()
 {
-	CTextureUser cu;
-	initBloom(cu);
+	initBloom(NULL);
 }
 
-void CBloomEffect::initBloom(UTexture &renderTarget) // clientcfg
+void CBloomEffect::initBloom(UTexture *renderTarget) // clientcfg
 {
 	if(!((CDriverUser *)_Driver)->getDriver()->supportBloomEffect())
 		return;
 
-	m_UserRenderTarget = dynamic_cast<CTextureUser &>(renderTarget).getITexture();
+	m_UserRenderTarget = renderTarget ? dynamic_cast<CTextureUser *>(renderTarget)->getITexture() : NULL;
 
 	// don't activate bloom when PolygonMode is different from Filled
 	if (_Driver->getPolygonMode() != UDriver::Filled) return;
diff --git a/code/nel/src/3d/stereo_ovr.cpp b/code/nel/src/3d/stereo_ovr.cpp
index 8eb8e1f9b..68fd1400e 100644
--- a/code/nel/src/3d/stereo_ovr.cpp
+++ b/code/nel/src/3d/stereo_ovr.cpp
@@ -163,7 +163,7 @@ public:
 	OVR::HMDInfo HMDInfo;
 };
 
-CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_BarrelTexU(NULL)
+CStereoOVR::CStereoOVR(const CStereoOVRDeviceHandle *handle) : m_Stage(0), m_SubStage(0), m_OrientationCached(false), m_Driver(NULL), m_BarrelTexU(NULL)
 {
 	++s_DeviceCounter;
 	m_DevicePtr = new CStereoOVRDevicePtr();
@@ -453,7 +453,7 @@ UTexture *CStereoOVR::beginRenderTarget(bool set)
 {
 	// render target always set before driver clear
 	// nlassert(m_SubStage <= 1);
-	if (m_Stage == 1)
+	if (m_Driver && m_Stage == 1)
 	{
 		if (set)
 		{
@@ -465,17 +465,19 @@ UTexture *CStereoOVR::beginRenderTarget(bool set)
 }
 
 /// Returns true if a render target was fully drawn
-bool CStereoOVR::endRenderTarget(bool unset)
+bool CStereoOVR::endRenderTarget()
 {
 	// after rendering of course
 	// nlassert(m_SubStage > 1);
-	if (m_Stage == 4)
+	if (m_Driver && m_Stage == 4)
 	{
-		if (unset)
-		{
-			CTextureUser cu;
-			(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
-		}
+		CTextureUser cu;
+		(static_cast<CDriverUser *>(m_Driver))->setRenderTarget(cu);
+
+		m_Driver->setMatrixMode2D11();
+		m_Driver->setViewport(CViewport());
+		m_Driver->drawQuad(m_BarrelQuad, m_BarrelMat);
+
 		return true;
 	}
 	return false;
diff --git a/code/snowballs2/client/src/camera.cpp b/code/snowballs2/client/src/camera.cpp
index f4f5ea2b4..92216fe98 100644
--- a/code/snowballs2/client/src/camera.cpp
+++ b/code/snowballs2/client/src/camera.cpp
@@ -113,10 +113,14 @@ void	initCamera()
 		{
 			nlinfo("Create VR stereo display device");
 			StereoDisplay = IStereoDisplay::createDevice(*deviceInfo);
-			if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD)
+			if (StereoDisplay)
 			{
-				nlinfo("Stereo display device is a HMD");
-				StereoHMD = static_cast<IStereoHMD *>(StereoDisplay);
+				if (deviceInfo->Class == CStereoDeviceInfo::StereoHMD)
+				{
+					nlinfo("Stereo display device is a HMD");
+					StereoHMD = static_cast<IStereoHMD *>(StereoDisplay);
+				}
+				StereoDisplay->setDriver(Driver); // move after driver creation, move stereodisplay before driver creation
 			}
 		}
 		IStereoDisplay::releaseUnusedLibraries();
@@ -212,7 +216,7 @@ void releaseSky()
 // -- -- random note: update and render makes more sense than animate and update
 void animateSky(double dt)
 {
-	Clouds->anim(dt);
+	if (!StereoDisplay) Clouds->anim(dt);
 }
 
 // this is actually render
diff --git a/code/snowballs2/client/src/snowballs_client.cpp b/code/snowballs2/client/src/snowballs_client.cpp
index e6754388a..e71136377 100644
--- a/code/snowballs2/client/src/snowballs_client.cpp
+++ b/code/snowballs2/client/src/snowballs_client.cpp
@@ -736,26 +736,28 @@ void loopIngame()
 		{
 			uint i = 0;
 			uint bloomStage = 0;
-			while ((!StereoHMD && i == 0) || (StereoHMD && StereoHMD->nextPass()))
+			while ((!StereoDisplay && i == 0) || (StereoDisplay && StereoDisplay->nextPass()))
 			{
 				++i;
-				if (StereoHMD)
+				if (StereoDisplay)
 				{
-					const CViewport &vp = StereoHMD->getCurrentViewport();
+					const CViewport &vp = StereoDisplay->getCurrentViewport();
 					Driver->setViewport(vp);
 					Scene->setViewport(vp);
 					SkyScene->setViewport(vp);
-					StereoHMD->getCurrentFrustum(0, &Camera);
-					StereoHMD->getCurrentFrustum(0, &SkyCamera);
-					StereoHMD->getCurrentMatrix(0, &Camera);
+					StereoDisplay->getCurrentFrustum(0, &Camera);
+					StereoDisplay->getCurrentFrustum(0, &SkyCamera);
+					StereoDisplay->getCurrentMatrix(0, &Camera);
 				}
 				
-				if (!StereoHMD || StereoHMD->wantClear())
+				if (!StereoDisplay || StereoDisplay->wantClear())
 				{
+					NL3D::UTexture *rt = StereoDisplay ? StereoDisplay->beginRenderTarget(!s_EnableBloom) : NULL;
+
 					if (s_EnableBloom)
 					{
 						nlassert(bloomStage == 0);
-						CBloomEffect::instance().initBloom(); // start bloom effect (just before the first scene element render)
+						CBloomEffect::instance().initBloom(/*rt*/); // start bloom effect (just before the first scene element render)
 						bloomStage = 1;
 					}
 
@@ -763,7 +765,7 @@ void loopIngame()
 					Driver->clearBuffers(CRGBA(0, 0, 127)); // clear all buffers, if you see this blue there's a problem with scene rendering
 				}
 
-				if (!StereoHMD || StereoHMD->wantScene())
+				if (!StereoDisplay || StereoDisplay->wantScene())
 				{				
 					// 02. Render Sky (sky scene)
 					updateSky(); // Render the sky scene before the main scene
@@ -772,17 +774,17 @@ void loopIngame()
 					Scene->render(); // Render
 
 					// 05. Render Effects (flare)
-					if (!StereoHMD) updateLensFlare(); // Render the lens flare (left eye stretched with stereo...)
+					if (!StereoDisplay) updateLensFlare(); // Render the lens flare (left eye stretched with stereo...)
 				}
 
-				if (!StereoHMD || StereoHMD->wantInterface3D())
+				if (!StereoDisplay || StereoDisplay->wantInterface3D())
 				{
 					if (s_EnableBloom && bloomStage == 1)
 					{
 						// End the actual bloom effect visible in the scene.
-						if (StereoHMD) Driver->setViewport(NL3D::CViewport());
+						if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
 						CBloomEffect::instance().endBloom();
-						if (StereoHMD) Driver->setViewport(StereoHMD->getCurrentViewport());
+						if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport());
 						bloomStage = 2;
 					}
 
@@ -790,14 +792,14 @@ void loopIngame()
 					// ... 
 				}
 
-				if (!StereoHMD || StereoHMD->wantInterface2D())
+				if (!StereoDisplay || StereoDisplay->wantInterface2D())
 				{
 					if (s_EnableBloom && bloomStage == 2)
 					{
 						// End bloom effect system after drawing the 3d interface (z buffer related).
-						if (StereoHMD) Driver->setViewport(NL3D::CViewport());
+						if (StereoDisplay) Driver->setViewport(NL3D::CViewport());
 						CBloomEffect::instance().endInterfacesDisplayBloom();
-						if (StereoHMD) Driver->setViewport(StereoHMD->getCurrentViewport());
+						if (StereoDisplay) Driver->setViewport(StereoDisplay->getCurrentViewport());
 						bloomStage = 0;
 					}
 
@@ -810,11 +812,16 @@ void loopIngame()
 					renderEntitiesNames(); // Render the name on top of the other players
 					updateInterface(); // Update interface
 					renderInformation();
-					if (!StereoHMD) update3dLogo(); // broken with stereo
+					if (!StereoDisplay) update3dLogo(); // broken with stereo
 
 					// 08. Render Debug (stuff for dev)
 					// ...
 				}
+
+				if (StereoDisplay)
+				{
+					StereoDisplay->endRenderTarget();
+				}
 			}
 
 			// 09. Render Buffer