diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index abead17d6ff60f3edc559a46d643f6e751eef0b3..985f5a0a1f9ffbc500a2f6749d176c5948f57504 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -963,14 +963,16 @@ void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* d
 	entry->setState(LLVOCacheEntry::INACTIVE);
 }
 
-void LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group)
+bool LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group)
 {
 	if(mDead || group->isEmpty())
 	{
-		return;
+		return false;
 	}
-	group->setVisible();
+	
 	mImpl->mVisibleGroups.insert(group);
+
+	return true;
 }
 
 U32 LLViewerRegion::getNumOfVisibleGroups() const
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index e07c2aa8d0d74a79367d51aca00665141de6a897..b2df8d5325957252155bb7e4988484ca446de38e 100755
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -229,7 +229,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	F32	getWidth() const						{ return mWidth; }
 
 	BOOL idleUpdate(F32 max_update_time);
-	void addVisibleGroup(LLviewerOctreeGroup* group);
+	bool addVisibleGroup(LLviewerOctreeGroup* group);
 	void addVisibleCacheEntry(LLVOCacheEntry* entry);
 	void addActiveCacheEntry(LLVOCacheEntry* entry);
 	void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep);	
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 6d2a17882adc429de5fc600cc000f39229785f48..dfc9ee57d8107676b1d45031b1b2721934a4d711 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -490,7 +490,9 @@ LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)
 {
 	mLODPeriod = 16;
 	mRegionp = regionp;
-	mPartitionType = LLViewerRegion::PARTITION_VO_CACHE;	
+	mPartitionType = LLViewerRegion::PARTITION_VO_CACHE;
+	mBackSlectionEnabled = -1;
+	mIdleHash = 0;
 	
 	for(S32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
 	{
@@ -517,7 +519,8 @@ void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry)
 class LLVOCacheOctreeCull : public LLViewerOctreeCull
 {
 public:
-	LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, const LLVector3& shift, bool use_object_cache_occlusion, LLVOCachePartition* part) 
+	LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, 
+		const LLVector3& shift, bool use_object_cache_occlusion, LLVOCachePartition* part) 
 		: LLViewerOctreeCull(camera), 
 		  mRegionp(regionp),
 		  mPartition(part)
@@ -583,7 +586,10 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 			!base_group->getOctreeNode()->getParent())
 		{ 
 			//no occlusion check
-			mRegionp->addVisibleGroup(base_group);
+			if(mRegionp->addVisibleGroup(base_group))
+			{
+				base_group->setVisible();
+			}
 			return;
 		}
 
@@ -603,7 +609,10 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 		}
 		else
 		{
-			mRegionp->addVisibleGroup(base_group);
+			if(mRegionp->addVisibleGroup(base_group))
+			{
+				base_group->setVisible();
+			}
 		}
 	}
 
@@ -614,6 +623,81 @@ class LLVOCacheOctreeCull : public LLViewerOctreeCull
 	bool                mUseObjectCacheOcclusion;
 };
 
+//select objects behind camera
+class LLVOCacheOctreeBackCull : public LLViewerOctreeCull
+{
+public:
+	LLVOCacheOctreeBackCull(LLCamera* camera, const LLVector3& shift, LLViewerRegion* regionp) 
+		: LLViewerOctreeCull(camera), mRegionp(regionp)
+	{
+		mLocalShift = shift;
+		mSphereRadius = 20.f; //20m
+	}
+
+	virtual S32 frustumCheck(const LLviewerOctreeGroup* group)
+	{			
+		const LLVector4a* exts = group->getExtents();
+		return backSphereCheck(exts[0], exts[1]);
+	}
+
+	virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group)
+	{
+		const LLVector4a* exts = group->getObjectExtents();
+		return backSphereCheck(exts[0], exts[1]);
+	}
+
+	virtual void processGroup(LLviewerOctreeGroup* base_group)
+	{
+		mRegionp->addVisibleGroup(base_group);
+		return;
+	}
+
+private:
+	//a sphere around the camera origin, including objects behind camera.
+	S32 backSphereCheck(const LLVector4a& min, const LLVector4a& max)
+	{
+		return AABBSphereIntersect(min, max, mCamera->getOrigin() - mLocalShift, mSphereRadius);
+	}
+
+private:
+	F32              mSphereRadius;
+	LLViewerRegion*  mRegionp;
+	LLVector3        mLocalShift; //shift vector from agent space to local region space.
+};
+
+void LLVOCachePartition::selectBackObjects(LLCamera &camera)
+{
+	if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+	{
+		return;
+	}
+
+	if(mBackSlectionEnabled < 0)
+	{
+		mBackSlectionEnabled = LLVOCacheEntry::getInvisibleObjectsLiveTime() - 1;
+		mBackSlectionEnabled = llmax(mBackSlectionEnabled, (S32)1);
+	}
+
+	if(!mBackSlectionEnabled)
+	{
+		return;
+	}
+
+	//localize the camera
+	LLVector3 region_agent = mRegionp->getOriginAgent();
+	
+	LLVOCacheOctreeBackCull culler(&camera, region_agent, mRegionp);
+	culler.traverse(mOctree);
+
+	mBackSlectionEnabled--;
+	if(!mRegionp->getNumOfVisibleGroups())
+	{
+		mBackSlectionEnabled = 0;
+	}
+
+	return;
+}
+
 S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion)
 {
 	static LLCachedControl<bool> use_object_cache_occlusion(gSavedSettings,"UseObjectCacheOcclusion");
@@ -638,22 +722,25 @@ S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion)
 
 	if(!mCullHistory[LLViewerCamera::sCurCameraID] && LLViewerRegion::isViewerCameraStatic())
 	{
-		static U32 hash = 0;
-
 		U32 seed = llmax(mLODPeriod >> 1, (U32)4);
 		if(LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
 		{
 			if(!(LLViewerOctreeEntryData::getCurrentFrame() % seed))
 			{
-				hash = (hash + 1) % seed;
+				mIdleHash = (mIdleHash + 1) % seed;
 			}
 		}
-		if(LLViewerOctreeEntryData::getCurrentFrame() % seed != hash)
+		if(LLViewerOctreeEntryData::getCurrentFrame() % seed != mIdleHash)
 		{
+			selectBackObjects(camera);//process back objects selection
 			return 0; //nothing changed, reduce frequency of culling
 		}
 	}
-	
+	else
+	{
+		mBackSlectionEnabled = -1; //reset it.
+	}
+
 	if(LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
 	{
 		mCullHistory[LLViewerCamera::sCurCameraID] <<= 1;
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index 7c7b64ad5ba2e402541d37fe181e70c1fa9c06c1..867f9ab93c42e5fa1e729ba7aecf55c193f2f6ed 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -126,10 +126,9 @@ class LLVOCacheEntry
 	U32  getUpdateFlags() const    {return mUpdateFlags;}
 
 	static void updateBackCullingFactors();
-
-private:
 	static U32  getInvisibleObjectsLiveTime();
 
+private:
 	void updateParentBoundingInfo(const LLVOCacheEntry* child);	
 
 public:
@@ -172,6 +171,9 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	void resetOccluders();
 	void processOccluders(LLCamera* camera);
 	
+private:
+	void selectBackObjects(LLCamera &camera); //select objects behind camera.
+
 public:
 	static BOOL sNeedsOcclusionCheck;
 	//static	LLTrace::MemStatHandle	sMemStat;
@@ -180,6 +182,9 @@ class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTr
 	U32   mCullHistory[LLViewerCamera::NUM_CAMERAS];
 	U32   mCulledTime[LLViewerCamera::NUM_CAMERAS];
 	std::set<LLOcclusionCullingGroup*> mOccludedGroups;
+
+	S32   mBackSlectionEnabled; //enable to select back objects if > 0.
+	U32   mIdleHash;
 };
 
 //