Преглед изворни кода

Sort reflection probes before sending them off to the shader

BearishSun пре 8 година
родитељ
комит
e5f8dd740b

+ 1 - 1
Source/BansheeEngine/Source/BsReflectionProbes.cpp

@@ -64,7 +64,7 @@ namespace bs { namespace ct
 
 		// First part of the equation for determining mip level for sample from.
 		// See http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html
-		float mipFactor = 0.5f * std::log2(width * height / NUM_SAMPLES); // TODO
+		float mipFactor = 0.5f * std::log2(width * height / NUM_SAMPLES);
 		gReflectionCubeImportanceSampleParamDef.gPrecomputedMipFactor.set(mParamBuffer, mipFactor);
 
 		RenderAPI& rapi = RenderAPI::instance();

+ 1 - 1
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -236,7 +236,7 @@ namespace bs { namespace ct
 		PixelData pixelData = texture->lock(GBL_WRITE_ONLY_DISCARD);
 
 		UINT16* rawPixels = (UINT16*)pixelData.getData();
-		UINT32 rowPitch = pixelData.getRowPitch() * PixelUtil::getNumElemBytes(desc.format);
+		UINT32 rowPitch = pixelData.getRowPitch();
 
 		for (UINT32 y = 0; y < desc.height; y++)
 		{

+ 26 - 2
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -41,6 +41,9 @@ using namespace std::placeholders;
 
 namespace bs { namespace ct
 {
+    // Limited by max number of array elements in texture for DX11 hardware
+    constexpr UINT32 MaxReflectionCubemaps = 2048 / 6;
+
 	RenderBeast::RenderBeast()
 		: mDefaultMaterial(nullptr)
 		, mTiledDeferredLightingMats()
@@ -490,6 +493,12 @@ namespace bs { namespace ct
 				probeInfo.arrayIdx = numArrayEntries;
 				mCubemapArrayUsedSlots.push_back(true);
 			}
+
+            if(probeInfo.arrayIdx > MaxReflectionCubemaps)
+            {
+                LOGERR("Reached the maximum number of allowed reflection probe cubemaps at once. "
+                       "Ignoring reflection probe data.");
+            }
 		}
 	}
 
@@ -860,6 +869,15 @@ namespace bs { namespace ct
 			mReflProbes[i].getParameters(mReflProbeDataTemp.back());
 		}
 
+        // Sort probes so bigger ones get accessed first, this way we overlay smaller ones on top of biggers ones when
+	    // rendering
+        auto sorter = [](const ReflProbeData& lhs, const ReflProbeData& rhs)
+        {
+            return rhs.radius < lhs.radius;
+        };
+
+        std::sort(mReflProbeDataTemp.begin(), mReflProbeDataTemp.end(), sorter);
+
 		mGPUReflProbeData->setProbes(mReflProbeDataTemp, numProbes);
 
 		mReflProbeDataTemp.clear();
@@ -1194,8 +1212,10 @@ namespace bs { namespace ct
 
 		bs_frame_mark();
 		{		
+            UINT32 currentCubeArraySize = mCubemapArrayTex->getProperties().getNumArraySlices();
+
 			bool forceArrayUpdate = false;
-			if(mCubemapArrayTex == nullptr || mCubemapArrayTex->getProperties().getNumArraySlices() < numProbes)
+			if(mCubemapArrayTex == nullptr || (currentCubeArraySize < numProbes && currentCubeArraySize != MaxReflectionCubemaps))
 			{
 				TEXTURE_DESC cubeMapDesc;
 				cubeMapDesc.type = TEX_TYPE_CUBE_MAP;
@@ -1203,7 +1223,7 @@ namespace bs { namespace ct
 				cubeMapDesc.width = ReflectionProbes::REFLECTION_CUBEMAP_SIZE;
 				cubeMapDesc.height = ReflectionProbes::REFLECTION_CUBEMAP_SIZE;
 				cubeMapDesc.numMips = PixelUtil::getMaxMipmaps(cubeMapDesc.width, cubeMapDesc.height, 1, cubeMapDesc.format);
-				cubeMapDesc.numArraySlices = numProbes + 4; // Keep a few empty entries
+				cubeMapDesc.numArraySlices = std::min(MaxReflectionCubemaps, numProbes + 4); // Keep a few empty entries
 
 				mCubemapArrayTex = Texture::create(cubeMapDesc);
 
@@ -1227,6 +1247,10 @@ namespace bs { namespace ct
 			for (UINT32 i = 0; i < numProbes; i++)
 			{
 				RendererReflectionProbe& probeInfo = mReflProbes[i];
+
+                if (probeInfo.arrayIdx > MaxReflectionCubemaps)
+                    continue;
+
 				if (probeInfo.probe->getType() != ReflectionProbeType::Plane)
 				{
 					if (probeInfo.texture == nullptr)