【UE4】指数密度高度雾

https://zhuanlan.zhihu.com/p/76627240
指数密度高度雾总共分为4个板块,完成了其中的两个板块
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

https://blog.csdn.net/netyeaxi/article/details/87437880

控制台设置

SceneRendering.cpp
FSceneRenderer::PostVisibilityFrameSetup
InitFogConstants();

Common.ush

// also see ConvertToDeviceZ()
// @param DeviceZ value that is stored in the depth buffer (Z/W)
// @return SceneDepth (linear in world units, W)
float ConvertFromDeviceZ(float DeviceZ)
{
	// Supports ortho and perspective, see CreateInvDeviceZToWorldZTransform()
	return DeviceZ * View.InvDeviceZToWorldZTransform[0] + View.InvDeviceZToWorldZTransform[1] + 1.0f / (DeviceZ * View.InvDeviceZToWorldZTransform[2] - View.InvDeviceZToWorldZTransform[3]);
}

shader中关于View相关的代码在:SceneView.cpp
L2424

ViewUniformShaderParameters.ScreenToTranslatedWorld = FMatrix(
		FPlane(1, 0, 0, 0),
		FPlane(0, 1, 0, 0),
		FPlane(0, 0, ProjectionMatrixUnadjustedForRHI.M[2][2], 1),
		FPlane(0, 0, ProjectionMatrixUnadjustedForRHI.M[3][2], 0))
		* InViewMatrices.GetInvTranslatedViewProjectionMatrix();

L2251

	// to bring NDC (-1..1, 1..-1) into 0..1 UV for BufferSize textures
	const FVector4 ScreenPositionScaleBias(
		EffectiveViewRect.Width() * InvBufferSizeX / +2.0f,
		EffectiveViewRect.Height() * InvBufferSizeY / (-2.0f * GProjectionSignY),
		(EffectiveViewRect.Height() / 2.0f + EffectiveViewRect.Min.Y) * InvBufferSizeY,
		(EffectiveViewRect.Width() / 2.0f + EffectiveViewRect.Min.X) * InvBufferSizeX);

RenderUtils.cpp
QuadVertex

	virtual void InitRHI() override
	{
		// create a static vertex buffer
		FRHIResourceCreateInfo CreateInfo;
		VertexBufferRHI = RHICreateVertexBuffer(sizeof(FVector2D) * 4, BUF_Static, CreateInfo);
		void* VoidPtr = RHILockVertexBuffer(VertexBufferRHI, 0, sizeof(FVector2D) * 4, RLM_WriteOnly);
		static const FVector2D Vertices[4] =
		{
			FVector2D(-1,-1),
			FVector2D(-1,+1),
			FVector2D(+1,-1),
			FVector2D(+1,+1),
		};
		FMemory::Memcpy(VoidPtr, Vertices, sizeof(FVector2D) * 4);
		RHIUnlockVertexBuffer(VertexBufferRHI);
	}
// FogStruct.ExponentialFogParameters: FogDensity * exp2(-FogHeightFalloff * (CameraWorldPosition.z - FogHeight)) in x, FogHeightFalloff in y, MaxWorldObserverHeight in z, StartDistance in w. 
// FogStruct.ExponentialFogParameters2: FogDensitySecond * exp2(-FogHeightFalloffSecond * (CameraWorldPosition.z - FogHeightSecond)) in x, FogHeightFalloffSecond in y, FogDensitySecond in z, FogHeightSecond in w 
// FogStruct.ExponentialFogParameters3: FogDensity in x, FogHeight in y, whether to use cubemap fog color in z, FogCutoffDistance in w. 

//ExponentialFogParameters
在这里插入图片描述
y和雾高度衰减有关
z=65536+HeiFog的z
w=
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
y=雾高度
w=在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
w=1-雾最大不透明度

在这里插入图片描述
引擎版
在这里插入图片描述

复制版
在这里插入图片描述

shader

参数设置

// FogStruct.ExponentialFogParameters: FogDensity * exp2(-FogHeightFalloff * (CameraWorldPosition.z - FogHeight)) in x, FogHeightFalloff in y, MaxWorldObserverHeight in z, StartDistance in w. 
// FogStruct.ExponentialFogParameters2: FogDensitySecond * exp2(-FogHeightFalloffSecond * (CameraWorldPosition.z - FogHeightSecond)) in x, FogHeightFalloffSecond in y, FogDensitySecond in z, FogHeightSecond in w 
// FogStruct.ExponentialFogParameters3: FogDensity in x, FogHeight in y, whether to use cubemap fog color in z, FogCutoffDistance in w.
static const float3 MyFogColor = float3(0.528, 0.646, 1.0);
static const float FogHeightFalloff = 0.001;
//Why not 0 or 1 or 2 .when set FogHeightFalloff value to 2 in editor it set 0.002 actually??Why
//it becomes constance when value=0
static const float GlobalDensity = 0.0003;
//this value is used to control the global fog density

//using a special starting distance to limit the inscattering to the distance
static const float DirectionalInscatteringStartDistance=10312;
static const float3 DirectionalInscatteringColor = float3(0.0, 2.594,0.615);
static const float3 InscatterinLightDirection = float3(0.506, 0.863, 0.00);
static const float DirectionalInscatteringStrenthFactor = 8.0;

雾密度计算+积分计算

float CalculateLineIntegralShared(float RayDirectionZ)
{
	//积分拟合函数
	//RayDirectionZ 人眼与物体的相对高度
	//雾效影响程度受到 物体高度的影响。越高的物体,到达人眼雾效消失的越严重,越低的物体,到达人眼以后,雾效会加强。
	float Falloff = max(-127.0f, FogHeightFalloff * RayDirectionZ); // if it's lower than -127.0, then exp2() goes crazy in OpenGL's GLSL.
	float LineIntegral = (1.0f - exp2(-Falloff)) / Falloff;
	float LineIntegralTaylor = log(2.0) - (0.5 * Pow2(log(2.0))) * Falloff; // Taylor expansion around 0
	
	//float FogDensity = GlobalDensity * exp2(-FogHeightFalloff * (CameraWorldPosition.z - FogHeight));
	//we set fogheight to 0
	
	//雾密度呈指数变化。
	//摄像机与雾的相对高度越大,这个密度值越小,且最小为0;相对高度越小,雾密度越大,最高为正无穷。
	//当摄像机的高度比雾高度小时,雾的密度始终大于1,且变化剧烈;反之,雾密度始终小于1, 且随着高度的增加,逐渐衰减为0
	
	//GlobalDensity ,高度雾全局密度,通过这个参数来控制整体的密度,人工干预修正曲线
	//FogHeightFalloff的引入,是为了缩小高度变化的程度,当衰减值为0时,变化程度缩小最大化,所有高度只有同一个密度值,当那个衰减值为2时,加强了高度对密度的影响程度。
	float FogDensity = GlobalDensity * exp2(-FogHeightFalloff * (View.WorldCameraOrigin.z-0.0));
	
	//abs(Falloff) > FLT_EPSILON2 avoid dvide zero
	//return RayOriginTerms * (abs(Falloff) > FLT_EPSILON2 ? LineIntegral : LineIntegralTaylor);
	//RayOriginTerms=FogDensity * exp2(-FogHeightFalloff * (CameraWorldPosition.z - FogHeight)) which is FogStruct.ExponentialFogParameters.x
	return FogDensity * (abs(Falloff) > FLT_EPSILON2 ? LineIntegral : LineIntegralTaylor);

}

计算指数高度雾+DirectionalLightInscattering

half4 GetExponentialHeightFog(float3 WorldPositionRelativeToCamera, float ExcludeDistance)
{
	float3 CameraToReceiver = WorldPositionRelativeToCamera;
	//const float3 WorldObserverOrigin = View.WorldCameraOrigin.xyz;
	float CameraToReceiverLengthSqr = dot(CameraToReceiver, CameraToReceiver);
	float CameraToReceiverLengthInv = rsqrt(CameraToReceiverLengthSqr);
	float CameraToReceiverLength = CameraToReceiverLengthSqr * CameraToReceiverLengthInv;
	half3 CameraToReceiverNormalized = CameraToReceiver * CameraToReceiverLengthInv;
	
	float RayLength = CameraToReceiverLength;
	
	float RayDirectionZ = CameraToReceiver.z;
	float ExponentialHeightLineIntegralShared = CalculateLineIntegralShared(RayDirectionZ);
	
	//RayLength 加上距离的影响
	float ExponentialHeightLineIntegral = ExponentialHeightLineIntegralShared * RayLength;
	
	half MinFogOpacity = 0.0;
	
	//设置最小不透明度为0.0 观察低处的影响
	half ExpFogFactor = max(saturate(exp2(-ExponentialHeightLineIntegral)), 0.5);
	
	//Shader type 2:DirectionalLightInscattering--------------------------------------------------------------
	half3 DirectionalLightInscattering = DirectionalInscatteringColor * pow(saturate(dot(CameraToReceiverNormalized, InscatterinLightDirection)), DirectionalInscatteringStrenthFactor);
	
	//距离影响因子
	float DirExponentialHeightLineIntegral = ExponentialHeightLineIntegralShared * max(RayLength - DirectionalInscatteringStartDistance, 0.0f);
	// Calculate the amount of light that made it through the fog using the transmission equation
	half DirectionalInscatteringFogFactor = saturate(exp2(-DirExponentialHeightLineIntegral));
	// Final inscattering from the light
	half3 DirectionalInscattering = DirectionalLightInscattering * (1 - DirectionalInscatteringFogFactor);
	//-----------------------------------------------------------------------------------------------------------
	
	half3 FogColor = (MyFogColor.xyz) * (1 - ExpFogFactor) + DirectionalInscattering;
	//return half4(0.0, 0.0, 0.0, 1.0);
	return half4(FogColor, ExpFogFactor);
}
void MainPS(
	in float2 UV: TEXCOORD0,
	in float3 ScreenVector : TEXCOORD1,
	in float4 Position : SV_POSITION,
    out float4 OutColor : SV_Target0
)
{
	float DeviceZ = Texture2DSampleLevel(SceneTexturesStruct.SceneDepthTexture, SceneTexturesStruct_SceneDepthTextureSampler, UV, 0).r;
	// @param DeviceZ value that is stored in the depth buffer (Z/W)
	// @return SceneDepth (linear in world units, W)
	float SceneDepth = ConvertFromDeviceZ(DeviceZ); // Fetch the depth buffer Z / W value, solve for W

	bool bIsRendered = (DeviceZ != 0.0);
	
	float3 WorldPositionRelativeToCamera = ScreenVector.xyz * SceneDepth;//scale xyz ??
	
	float4 HeightFogInscatteringAndOpacity = CalculateHeightFog(WorldPositionRelativeToCamera);
	
	float LightShaftMask = Texture2DSample(OcclusionTexture, OcclusionSampler, UV).x;
	HeightFogInscatteringAndOpacity.xyz *= LightShaftMask;
	
	if (!bIsRendered)
	{
		HeightFogInscatteringAndOpacity.rgb = 0;
		HeightFogInscatteringAndOpacity.a = 1;
	}
	OutColor = float4(HeightFogInscatteringAndOpacity.xyz, HeightFogInscatteringAndOpacity.w);
	//recompileshaders changed
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值