浏览代码

Cleaning up the SSRTrace and related shaders

BearishSun 8 年之前
父节点
当前提交
24942205e6

+ 14 - 86
Data/Raw/Engine/Includes/RayMarch.bslinc

@@ -63,79 +63,10 @@ mixin RayMarch
 			
 			return false;
 		}
-		
-		// TODO - Debug only
-		bool hiZSearchLinear(Texture2D depth, SamplerState samp, int2 bufferSize, int maxMipLevel, float3 rayPos, float3 rayStep, out float3 hitPos)
-		{		
-			bufferSize >>= 2;
-		
-			float iterationCount = 0.0f;
-			float mipLevel = 0.0f;
-		
-			// Get the ray equation, in the form so that t == Z
-			float3 D = rayStep / rayStep.z; // Scale vector so Z is moved into [0, 1] range
-			float3 O = rayPos + D * -rayPos.z; // Get point where Z equals 0 (on near plane)
-			// Our ray is now O + D * t, where t = 0 = near plane, and t = 1 = far plane
-			
-			// Avoid division by zero
-			D.x = abs(D.x) < 0.00001f ? 0.00001f : D.x;
-			D.y = abs(D.y) < 0.00001f ? 0.00001f : D.y;
 
-			while(rayPos.z <= 1.0f && iterationCount < 800.0f)
-			{
-				// Get depth of the current cell
-				float cellZ = depth.SampleLevel(samp, rayPos.xy, mipLevel).r;
-			
-				// Get pixel coordinates of the current cell
-				float2 curCellIdx = trunc(rayPos.xy * bufferSize);
-			
-				// Find intersection with the cell floor plane
-				float3 newRay = O + D * max(cellZ, rayPos.z); // max() so we can't hit the ceiling (ray going backwards)
-				
-				// Get pixel coordinates of the new ray's cell
-				float2 newCellIdx = trunc(newRay.xy * bufferSize);
-				
-				// If we moved to another cell, no intersection with floor
-				if(any(curCellIdx != newCellIdx))
-				{
-					// Find intersection with neighbor cell
-					float2 cellStart = (curCellIdx / bufferSize);
-					float2 cellEnd = ((curCellIdx + 1) / bufferSize);
-					
-					float2 intersectStart = (cellStart - rayPos.xy) / D.xy;
-					float2 intersectEnd = (cellEnd - rayPos.xy) / D.xy;
-					
-					// Only care about positive t
-					float maxIntersectX = max(intersectStart.x, intersectEnd.x);
-					float maxIntersectY = max(intersectStart.y, intersectEnd.y);
-					
-					// Closest t is the one at the boundary
-					float minIntersect = min(maxIntersectX, maxIntersectY);
-				
-					// Little extra to ensure the boundary is crossed. max() to ensure the value isn't too
-					// small to prevent it ever leaving a cell. Note that this clamping results in a quality loss,
-					// you want to keep the clamp value as low as possible, but not too low to avoid artifacts.
-					minIntersect = max(minIntersect * 1.05f, 1.0f / (bufferSize * 512)); // 1/512th of a pixel
-					
-					// Move the ray past the boundary
-					rayPos = O + D * (rayPos.z + minIntersect);
-				}
-				else // Intersection with floor
-				{
-					hitPos = newRay;
-					return true;
-				}
-
-				++iterationCount;
-			}
-			
-			hitPos = rayPos;			
-			return false;
-		}
-		
-		bool hiZSearch(Texture2D depth, SamplerState samp, int2 bufferSize, int maxMipLevel, float3 rayPos, float3 rayStep, out float3 hitPos, out float iterationCount)
+		bool hiZSearch(Texture2D depth, SamplerState samp, int2 bufferSize, int maxMipLevel, float3 rayPos, float3 rayStep, out float3 hitPos)
 		{		
-			iterationCount = 0.0f;
+			float iterationCount = 0.0f;
 			int mipLevel = HIZ_START_LEVEL;
 			
 			bufferSize >>= mipLevel;
@@ -218,16 +149,15 @@ mixin RayMarch
 		{
 			int2 bufferSize;
 			int numMips;
-			float4 hiZUVMapping; // From NDC to HiZ UV. .xy - multiply, .zw - add
+			float4 NDCToHiZUV; // From NDC to HiZ UV. .xy - multiply, .zw - add
+			float2 HiZUVToScreenUV; // From HiZ UV to screen UV. .xy - multiply
 			float3 rayOrigin; // World space
 			float3 rayDir; // World space
 			float jitterOffset;
 		};
 	
-		float4 rayMarch(Texture2D depth, SamplerState samp, RayMarchParams params, out float dbg)
+		float4 rayMarch(Texture2D depth, SamplerState samp, RayMarchParams params)
 		{
-			dbg = 0.0f;
-		
 			float3 viewOrigin = mul(gMatView, float4(params.rayOrigin, 1));
 			float3 viewDir = mul(gMatView, float4(params.rayDir, 0));
 		
@@ -246,11 +176,11 @@ mixin RayMarch
 		
 			#if HI_Z
 			float3 uvStart;
-			uvStart.xy = ndcStart.xy * params.hiZUVMapping.xy + params.hiZUVMapping.zw;
+			uvStart.xy = ndcStart.xy * params.NDCToHiZUV.xy + params.NDCToHiZUV.zw;
 			uvStart.z = NDCZToDeviceZ(ndcStart.z);
 			
 			float3 uvStep;
-			uvStep.xy = ndcStep.xy * params.hiZUVMapping.xy;
+			uvStep.xy = ndcStep.xy * params.NDCToHiZUV.xy;
 			uvStep.z = NDCZToDeviceZ(ndcStep.z);
 		
 			#else
@@ -265,23 +195,21 @@ mixin RayMarch
 			
 			// Note: Perhaps tweak this value
 			float compareTolerance = uvStep.z * stepIncrement * 2.0f;
-			
-			// Always do three steps of linear search
-			// (HiZ search is more expensive for short runs)
-			//if(linearSearch(depth, samp, uvStart, uvStep, 3, stepIncrement, compareTolerance, t))
-			//	return float4(uvStart + uvStep * t, t);
-			
+						
 			#if HI_Z
 			
+			// Note: Perhaps do a few steps of linear search first to handle nearby surfaces
+			
 			// Hierarchical search
 			float3 rayPos = uvStart + uvStep * t;
 			float3 hitPos;
-			if(hiZSearch(depth, samp, params.bufferSize, params.numMips, rayPos, uvStep, hitPos, dbg))
-				return float4(NDCToUV((hitPos.xy - params.hiZUVMapping.zw) / params.hiZUVMapping.xy), hitPos.z, 0);
+			if(hiZSearch(depth, samp, params.bufferSize, params.numMips, rayPos, uvStep, hitPos))
+				return float4(hitPos.xy * params.HiZUVToScreenUV.xy, hitPos.z, 0);
+				
 			#else
 			
 			// Plain linear search
-			if(linearSearch(depth, samp, uvStart, uvStep, NUM_STEPS - 4, stepIncrement, compareTolerance, t))
+			if(linearSearch(depth, samp, uvStart, uvStep, NUM_STEPS, stepIncrement, compareTolerance, t))
 				return float4(uvStart + uvStep * t, t);
 			#endif
 			

+ 5 - 24
Data/Raw/Engine/Shaders/PPSSRTrace.bsl

@@ -24,7 +24,8 @@ technique PPSSRTrace
 		[internal]
 		cbuffer Input
 		{
-			float4 gHiZUVMapping;
+			float4 gNDCToHiZUV;
+			float2 gHiZUVToScreenUV;
 			int2 gHiZSize;
 			int gHiZNumMips;
 		}
@@ -67,7 +68,6 @@ technique PPSSRTrace
 			
 			// TODO - Use Hammersley + random to generate ray directions based on GGX BRDF
 			//  - Clip BRDF lobe? And renormalize PDF?
-			// TODO - Generate random ray step offset
 			// TODO - Reject rays pointing under the surface
 			
 			// Eliminate rays pointing towards the viewer. They won't hit anything, plus they can screw up precision
@@ -83,15 +83,15 @@ technique PPSSRTrace
 			RayMarchParams rayMarchParams;
 			rayMarchParams.bufferSize = gHiZSize;
 			rayMarchParams.numMips = gHiZNumMips;
-			rayMarchParams.hiZUVMapping = gHiZUVMapping;
+			rayMarchParams.NDCToHiZUV = gNDCToHiZUV;
+			rayMarchParams.HiZUVToScreenUV = gHiZUVToScreenUV;
 			rayMarchParams.rayOrigin = P;
 			rayMarchParams.rayDir = R;
 			rayMarchParams.jitterOffset = jitterOffset;
 			
 			// TODO - Fade based on roughness
 			
-			float dbg = 0.0f;
-			float4 rayHit = rayMarch(gHiZ, gDepthBufferSamp, rayMarchParams, dbg);
+			float4 rayHit = rayMarch(gHiZ, gDepthBufferSamp, rayMarchParams);
 			if(rayHit.w < 1.0f) // Hit
 			{
 				float4 output = gSceneColor.Sample(gSceneColorSamp, rayHit.xy);
@@ -101,27 +101,8 @@ technique PPSSRTrace
 				float2 vignette = saturate(abs(rayHitNDC) * 5.0f - 4.0f);
 	
 				return output * (1.0f - dot(vignette, vignette));
-				
-				// DEBUG ONLY
-				if(dbg < 4.0)
-					return float4(0.0f, 1.0f, 0.0f, 1.0f);
-				else if(dbg < 8.0)
-					return float4(0.0f, 0.66f, 0.0f, 1.0f);
-				else if(dbg < 12.0)
-					return float4(0.0f, 0.33f, 0.0f, 1.0f);
-				else if(dbg < 16.0)
-					return float4(0.33f, 0.33f, 0.0f, 1.0f);
-				else if(dbg < 24.0)
-					return float4(0.5f, 0.0f, 0.0f, 1.0f);
-				else if(dbg < 32.0)
-					return float4(1.0f, 0.0f, 0.0f, 1.0f);
-				else
-					return float4(0.0f, 0.0f, 1.0f, 1.0f);
 			}
 			
-			//if(dbg > 0.5f)
-			//	return float4(1.0f, 0.0f, 0.0f, 1.0f);
-				
 			return 0.0f;
 		}	
 	};

+ 2 - 1
Source/RenderBeast/Include/BsPostProcessing.h

@@ -803,7 +803,8 @@ namespace bs { namespace ct
 	};
 
 	BS_PARAM_BLOCK_BEGIN(SSRTraceParamDef)
-		BS_PARAM_BLOCK_ENTRY(Vector4, gHiZUVMapping)
+		BS_PARAM_BLOCK_ENTRY(Vector4, gNDCToHiZUV)
+		BS_PARAM_BLOCK_ENTRY(Vector2, gHiZUVToScreenUV)
 		BS_PARAM_BLOCK_ENTRY(Vector2I, gHiZSize)
 		BS_PARAM_BLOCK_ENTRY(int, gHiZNumMips)
 	BS_PARAM_BLOCK_END

+ 18 - 12
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -1679,28 +1679,34 @@ namespace bs { namespace ct
 		Rect2I viewRect = viewProps.viewRect;
 
 		// Maps from NDC to UV [0, 1]
-		Vector4 ndcToUVMapping;
-		ndcToUVMapping.x = 0.5f;
-		ndcToUVMapping.y = -0.5f;
-		ndcToUVMapping.z = 0.5f;
-		ndcToUVMapping.w = 0.5f;
+		Vector4 ndcToHiZUV;
+		ndcToHiZUV.x = 0.5f;
+		ndcToHiZUV.y = -0.5f;
+		ndcToHiZUV.z = 0.5f;
+		ndcToHiZUV.w = 0.5f;
 
 		// Either of these flips the Y axis, but if they're both true they cancel out
 		RenderAPI& rapi = RenderAPI::instance();
 		const RenderAPIInfo& rapiInfo = rapi.getAPIInfo();
 		if (rapiInfo.isFlagSet(RenderAPIFeatureFlag::UVYAxisUp) ^ rapiInfo.isFlagSet(RenderAPIFeatureFlag::NDCYAxisDown))
-			ndcToUVMapping.y = -ndcToUVMapping.y;
+			ndcToHiZUV.y = -ndcToHiZUV.y;
 		
-		// Maps from [0, 1] to are of HiZ where depth is stored in
-		ndcToUVMapping.x *= (float)viewRect.width / hiZProps.getWidth();
-		ndcToUVMapping.y *= (float)viewRect.height / hiZProps.getHeight();
-		ndcToUVMapping.z *= (float)viewRect.width / hiZProps.getWidth();
-		ndcToUVMapping.w *= (float)viewRect.height / hiZProps.getHeight();
+		// Maps from [0, 1] to area of HiZ where depth is stored in
+		ndcToHiZUV.x *= (float)viewRect.width / hiZProps.getWidth();
+		ndcToHiZUV.y *= (float)viewRect.height / hiZProps.getHeight();
+		ndcToHiZUV.z *= (float)viewRect.width / hiZProps.getWidth();
+		ndcToHiZUV.w *= (float)viewRect.height / hiZProps.getHeight();
 		
+		// Maps from HiZ UV to [0, 1] UV
+		Vector2 HiZUVToScreenUV;
+		HiZUVToScreenUV.x = hiZProps.getWidth() / (float)viewRect.width;
+		HiZUVToScreenUV.y = hiZProps.getHeight() / (float)viewRect.height;
+
 		Vector2I bufferSize(viewRect.width, viewRect.height);
 		gSSRTraceParamDef.gHiZSize.set(mParamBuffer, bufferSize);
 		gSSRTraceParamDef.gHiZNumMips.set(mParamBuffer, hiZProps.getNumMipmaps());
-		gSSRTraceParamDef.gHiZUVMapping.set(mParamBuffer, ndcToUVMapping);
+		gSSRTraceParamDef.gNDCToHiZUV.set(mParamBuffer, ndcToHiZUV);
+		gSSRTraceParamDef.gHiZUVToScreenUV.set(mParamBuffer, HiZUVToScreenUV);
 
 		SPtr<GpuParamBlockBuffer> perView = view.getPerViewBuffer();
 		mParamsSet->setParamBlockBuffer("PerCamera", perView);