Unreal Engine开发:高级渲染技术_13.大气效果与天空渲染

13. 大气效果与天空渲染

13.1 大气散射原理

大气散射(Atmospheric Scattering)是一种模拟地球大气层中光线与空气分子相互作用的高级渲染技术。这种技术可以模拟光线在大气中的散射效果,包括瑞利散射(Rayleigh Scattering)和米氏散射(Mie Scattering),从而实现更加逼真的天空、太阳光晕、大气雾和远处物体的色彩变化。

13.1.1 瑞利散射

瑞利散射是指光线与空气分子等小粒子相互作用时发生的散射现象。这种散射导致天空呈现出蓝色,而太阳周围则呈现出白色。瑞利散射的数学模型如下:

I Rayleigh ( λ ) = I 0 8 π 3 ( n 2 − 1 ) 2 3 N λ 4 I_{\text{Rayleigh}}(\lambda) = I_0 \frac{8 \pi^3 (n^2 - 1)^2}{3 N \lambda^4} IRayleigh(λ)=I03Nλ48π3(n21)2

其中:

  • I 0 I_0 I0 是入射光强度

  • n n n 是空气分子的折射率

  • N N N 是单位体积内的空气分子数

  • λ \lambda λ 是光的波长

在Unreal Engine中,可以通过调用内置的瑞利散射函数来实现这一效果。例如:


// 在一个自定义的材质函数中实现瑞利散射

FVector UnlitAtmosphericScattering(const FVector& ViewDirection, const FVector& LightDirection, float RayleighScaleHeight)

{

    // 计算散射系数

    const FVector RayleighScatteringCoefficient = FVector(5.8e-4f, 1.352e-3f, 3.31e-3f);



    // 计算高度相关的散射系数

    FVector ScatteringCoefficient = RayleighScatteringCoefficient * FMath::Exp(-FVector::DotProduct(ViewDirection, FVector(0, 0, 1)) / RayleighScaleHeight);



    // 计算散射光强度

    FVector ScatteredLight = LightDirection * ScatteringCoefficient;



    return ScatteredLight;

}

13.1.2 米氏散射

米氏散射是指光线与较大的粒子(如灰尘、水滴等)相互作用时发生的散射现象。这种散射导致天空呈现出黄色和橙色,尤其是在日出和日落时。米氏散射的数学模型如下:

I Mie ( λ ) = I 0 2 π ( n − 1 ) 2 λ 4 ( N π D 3 / 6 ) I_{\text{Mie}}(\lambda) = I_0 \frac{2 \pi (n - 1)^2}{\lambda^4 (N \pi D^3 / 6)} IMie(λ)=I0λ4(NπD3/6)2π(n1)2

其中:

  • I 0 I_0 I0 是入射光强度

  • n n n 是粒子的折射率

  • N N N 是单位体积内的粒子数

  • D D D 是粒子的直径

  • λ \lambda λ 是光的波长

在Unreal Engine中,可以通过调用内置的米氏散射函数来实现这一效果。例如:


// 在一个自定义的材质函数中实现米氏散射

FVector UnlitAtmosphericScattering(const FVector& ViewDirection, const FVector& LightDirection, float MieScaleHeight)

{

    // 计算散射系数

    const FVector MieScatteringCoefficient = FVector(2.1e-5f, 8.4e-5f, 3.1e-5f);



    // 计算高度相关的散射系数

    FVector ScatteringCoefficient = MieScatteringCoefficient * FMath::Exp(-FVector::DotProduct(ViewDirection, FVector(0, 0, 1)) / MieScaleHeight);



    // 计算散射光强度

    FVector ScatteredLight = LightDirection * ScatteringCoefficient;



    return ScatteredLight;

}

13.1.3 大气散射的实现

在Unreal Engine中,大气散射可以通过使用AtmosphericFog组件来实现。AtmosphericFog组件可以模拟大气雾、散射光晕和天空效果。以下是一个简单的步骤来设置AtmosphericFog

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“体积” -> “大气雾”。

  2. 选择添加的大气雾Actor,然后在“细节”面板中调整参数,例如“太阳强度”、“太阳颜色”、“散射强度”等。

  3. 为了更好地控制天空效果,可以在关卡中添加一个SkyLight组件。


// 在C++中设置AtmosphericFog

AAtmosphericFog* AtmosphericFog = GetWorld()->SpawnActor<AAtmosphericFog>(FVector::ZeroVector, FRotator::ZeroRotator);

AtmosphericFog->SetSunDiskIntensity(10.0f);

AtmosphericFog->SetSunDiskColor(FLinearColor(1.0f, 1.0f, 1.0f, 1.0f));

AtmosphericFog->SetScatteringIntensity(2.0f);

13.2 天空渲染

天空渲染是模拟天空颜色和天空球的效果。Unreal Engine提供了多种天空渲染方法,包括使用天空球(Sky Sphere)、天空光(Sky Light)和大气散射(Atmospheric Scattering)。

13.2.1 天空球

天空球是一种简单的天空渲染方法,通常用于快速实现静态的天空效果。天空球可以使用一个球体网格和一个天空纹理来模拟天空。

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“其他” -> “天空球”。

  2. 选择添加的天空球Actor,然后在“细节”面板中选择一个天空纹理。


// 在C++中设置天空球

ASkySphere* SkySphere = GetWorld()->SpawnActor<ASkySphere>(FVector::ZeroVector, FRotator::ZeroRotator);

SkySphere->SetSphereMaterial(LoadObject<UMaterialInterface>(nullptr, TEXT("/Game/Textures/Sky/SkyMaterial")));

SkySphere->SetSphereRadius(5000.0f);

13.2.2 天空光

天空光是一种用于模拟环境光的方法,可以捕捉天空的颜色并将其应用于场景中的物体。天空光可以提高场景的整体光照效果,使其更加自然。

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“体积” -> “天空光”。

  2. 选择添加的天空光Actor,然后在“细节”面板中调整参数,例如“强度”、“半球颜色”等。


// 在C++中设置天空光

ASkyLight* SkyLight = GetWorld()->SpawnActor<ASkyLight>(FVector::ZeroVector, FRotator::ZeroRotator);

SkyLight->SetIntensity(1.5f);

SkyLight->SetLowerHemisphereColor(FLinearColor(0.3f, 0.5f, 0.7f, 1.0f));

SkyLight->SetUpperHemisphereColor(FLinearColor(0.8f, 0.9f, 1.0f, 1.0f));

13.2.3 动态天空渲染

动态天空渲染可以模拟一天中不同时间段的天空变化,例如日出、日落和夜晚。这通常需要使用时间参数来调整天空颜色和光晕效果。

  1. 创建一个时间控制器Actor,用于管理时间参数。

  2. 在材质中使用时间参数来调整颜色和光晕效果。


// 时间控制器Actor

AWeatherController::AWeatherController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void AWeatherController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新时间参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    SetTimeOfDay(TimeOfDay);

}



void AWeatherController::SetTimeOfDay(float TimeOfDay)

{

    // 调整天空颜色

    FLinearColor SkyColor;

    if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

    {

        SkyColor = FLinearColor(0.5f, 0.7f, 1.0f, 1.0f);

    }

    else

    {

        SkyColor = FLinearColor(0.1f, 0.1f, 0.3f, 1.0f);

    }



    // 更新天空球材质参数

    ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

    if (SkySphere)

    {

        UMaterialInstanceDynamic* SkyMaterialInstance = SkySphere->GetDynamicMaterial();

        if (SkyMaterialInstance)

        {

            SkyMaterialInstance->SetVectorParameterValue(TEXT("SkyColor"), SkyColor);

        }

    }

}

13.3 高级天空效果

Unreal Engine还提供了许多高级天空效果,例如天空光晕、云层效果和动态天气系统。这些效果可以进一步增强游戏的视觉表现力。

13.3.1 天空光晕

天空光晕是一种模拟太阳周围光晕效果的技术。这种效果可以通过使用后处理体积(Post Process Volume)和自定义材质来实现。

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“体积” -> “后处理体积”。

  2. 选择添加的后处理体积Actor,然后在“细节”面板中启用“天空光晕”效果。


// 在C++中启用天空光晕效果

APostProcessVolume* PostProcessVolume = GetWorld()->SpawnActor<APostProcessVolume>(FVector::ZeroVector, FRotator::ZeroRotator);

PostProcessVolume->bUnbound = true;

PostProcessVolume->BlendRadius = 100.0f;



// 启用天空光晕

FPostProcessSettings& Settings = PostProcessVolume->Settings;

Settings.bOverride_ScreenPercentage = true;

Settings.ScreenPercentage = 100.0f;

Settings.bOverride_SkyAtmosphere = true;

Settings.SkyAtmosphere = 1.0f;

13.3.2 云层效果

云层效果可以通过使用体积纹理(Volume Texture)和自定义材质来实现。体积纹理可以模拟云的密度和形状,而自定义材质可以控制云的渲染效果。

  1. 在内容浏览器中创建一个体积纹理(Volume Texture)。

  2. 创建一个自定义材质,使用体积纹理来控制云的密度和形状。

  3. 将自定义材质应用到天空球或其他天空渲染Actor上。


// 在C++中设置云层材质

UMaterialInstanceDynamic* CloudMaterialInstance = UMaterialInstanceDynamic::Create(LoadObject<UMaterial>(nullptr, TEXT("/Game/Materials/CloudMaterial")), this);

CloudMaterialInstance->SetTextureParameterValue(TEXT("CloudVolumeTexture"), LoadObject<UTextureVolume>(nullptr, TEXT("/Game/Textures/CloudVolume")));



ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

if (SkySphere)

{

    SkySphere->SetSphereMaterial(CloudMaterialInstance);

}

13.3.3 动态天气系统

动态天气系统可以模拟不同的天气效果,例如晴天、阴天、雨天和雪天。这种系统通常需要使用多个材质和参数来实现不同天气的效果。

  1. 创建一个天气控制器Actor,用于管理天气参数。

  2. 在材质中使用天气参数来控制天空颜色、云层密度和光照效果。


// 天气控制器Actor

AWeatherController::AWeatherController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void AWeatherController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新天气参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    float CloudDensity = FMath::Sin(TimeOfDay * PI / 12.0f) * 0.5f + 0.5f;

    SetWeatherParameters(TimeOfDay, CloudDensity);

}



void AWeatherController::SetWeatherParameters(float TimeOfDay, float CloudDensity)

{

    // 调整天空颜色

    FLinearColor SkyColor;

    if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

    {

        SkyColor = FLinearColor(0.5f, 0.7f, 1.0f, 1.0f);

    }

    else

    {

        SkyColor = FLinearColor(0.1f, 0.1f, 0.3f, 1.0f);

    }



    // 更新天空球材质参数

    ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

    if (SkySphere)

    {

        UMaterialInstanceDynamic* SkyMaterialInstance = SkySphere->GetDynamicMaterial();

        if (SkyMaterialInstance)

        {

            SkyMaterialInstance->SetVectorParameterValue(TEXT("SkyColor"), SkyColor);

            SkyMaterialInstance->SetScalarParameterValue(TEXT("CloudDensity"), CloudDensity);

        }

    }



    // 更新天空光参数

    ASkyLight* SkyLight = Cast<ASkyLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass()));

    if (SkyLight)

    {

        SkyLight->SetIntensity(1.5f * (1.0f - CloudDensity));

    }

}

13.4 环境光遮蔽

环境光遮蔽(Ambient Occlusion, AO)是一种模拟物体之间遮挡环境光的技术。这种技术可以提高场景的深度感和真实感。Unreal Engine提供了多种AO方法,包括屏幕空间环境光遮蔽(Screen Space Ambient Occlusion, SSAO)和全局环境光遮蔽(Global Ambient Occlusion, GAO)。

13.4.1 屏幕空间环境光遮蔽

SSAO是一种实时计算环境光遮蔽效果的技术,通常用于提高场景的细节表现。SSAO通过分析屏幕空间的深度信息来计算遮蔽效果。

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“体积” -> “后处理体积”。

  2. 选择添加的后处理体积Actor,然后在“细节”面板中启用“屏幕空间环境光遮蔽”效果。


// 在C++中启用SSAO

APostProcessVolume* PostProcessVolume = GetWorld()->SpawnActor<APostProcessVolume>(FVector::ZeroVector, FRotator::ZeroRotator);

PostProcessVolume->bUnbound = true;

PostProcessVolume->BlendRadius = 100.0f;



// 启用屏幕空间环境光遮蔽

FPostProcessSettings& Settings = PostProcessVolume->Settings;

Settings.bOverride_ScreenSpaceAO = true;

Settings.ScreenSpaceAOIntensity = 1.0f;

Settings.ScreenSpaceAOPower = 1.0f;

Settings.ScreenSpaceAORadius = 1.0f;

13.4.2 全局环境光遮蔽

GAO是一种更高级的环境光遮蔽技术,可以模拟更远的遮挡效果。GAO通常需要更多的计算资源,但可以提供更逼真的效果。

  1. 打开你的关卡,然后在“添加Actor”菜单中选择“体积” -> “后处理体积”。

  2. 选择添加的后处理体积Actor,然后在“细节”面板中启用“全局环境光遮蔽”效果。


// 在C++中启用GAO

APostProcessVolume* PostProcessVolume = GetWorld()->SpawnActor<APostProcessVolume>(FVector::ZeroVector, FRotator::ZeroRotator);

PostProcessVolume->bUnbound = true;

PostProcessVolume->BlendRadius = 100.0f;



// 启用全局环境光遮蔽

FPostProcessSettings& Settings = PostProcessVolume->Settings;

Settings.bOverride_AmbientOcclusion = true;

Settings.AmbientOcclusionIntensity = 1.0f;

Settings.AmbientOcclusionPower = 1.0f;

Settings.AmbientOcclusionRadius = 1.0f;

Settings.AmbientOcclusionExponent = 1.0f;

Settings.AmbientOcclusionFadeDistance = 1000.0f;

Settings.AmbientOcclusionFadeRadius = 500.0f;

13.5 实时天空更新

实时天空更新是指根据游戏时间或其他动态因素来实时调整天空效果。这可以通过使用时间控制器和自定义材质来实现。

13.5.1 时间控制器

时间控制器可以用于管理游戏中的时间参数,并根据时间参数调整天空效果。通过使用时间控制器,可以实现动态的天空变化,例如日出、日落和夜晚的天空颜色变化。

  1. 创建一个时间控制器Actor,用于管理时间参数。

  2. 在材质中使用时间参数来控制天空颜色和光晕效果。


// 时间控制器Actor

AWeatherController::AWeatherController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void AWeatherController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新时间参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    SetTimeOfDay(TimeOfDay);

}



void AWeatherController::SetTimeOfDay(float TimeOfDay)

{

    // 调整天空颜色

    FLinearColor SkyColor;

    if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

    {

        SkyColor = FLinearColor(0.5f, 0.7f, 1.0f, 1.0f);

    }

    else

    {

        SkyColor = FLinearColor(0.1f, 0.1f, 0.3f, 1.0f);

    }



    // 更新天空球材质参数

    ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

    if (SkySphere)

    {

        UMaterialInstanceDynamic* SkyMaterialInstance = SkySphere->GetDynamicMaterial();

        if (SkyMaterialInstance)

        {

            SkyMaterialInstance->SetVectorParameterValue(TEXT("SkyColor"), SkyColor);



            // 调整云层密度

            float CloudDensity = FMath::Sin(TimeOfDay * PI / 12.0f) * 0.5f + 0.5f;

            SkyMaterialInstance->SetScalarParameterValue(TEXT("CloudDensity"), CloudDensity);



            // 调整天空光强度

            ASkyLight* SkyLight = Cast<ASkyLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass()));

            if (SkyLight)

            {

                SkyLight->SetIntensity(1.5f * (1.0f - CloudDensity));

            }

        }

    }



    // 更新大气雾参数

    AAtmosphericFog* AtmosphericFog = Cast<AAtmosphericFog>(UGameplayStatics::GetActorOfClass(GetWorld(), AAtmosphericFog::StaticClass()));

    if (AtmosphericFog)

    {

        AtmosphericFog->SetSunDiskIntensity(10.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

        AtmosphericFog->SetScatteringIntensity(2.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

    }



    // 更新后处理体积参数

    APostProcessVolume* PostProcessVolume = Cast<APostProcessVolume>(UGameplayStatics::GetActorOfClass(GetWorld(), APostProcessVolume::StaticClass()));

    if (PostProcessVolume)

    {

        FPostProcessSettings& Settings = PostProcessVolume->Settings;

        Settings.bOverride_SkyAtmosphere = true;

        Settings.SkyAtmosphere = FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f);

    }

}

13.5.2 动态光照

动态光照可以根据时间变化实时调整场景中的光照效果,使场景更加逼真。这可以通过调整天空光、方向光和点光的参数来实现。


// 动态光照控制器Actor

ALightController::ALightController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void ALightController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新时间参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    SetLightParameters(TimeOfDay);

}



void ALightController::SetLightParameters(float TimeOfDay)

{

    // 调整方向光颜色和强度

    ADirectionalLight* DirectionalLight = Cast<ADirectionalLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ADirectionalLight::StaticClass()));

    if (DirectionalLight)

    {

        FLinearColor LightColor;

        float LightIntensity;



        if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

        {

            LightColor = FLinearColor(1.0f, 1.0f, 0.9f, 1.0f);

            LightIntensity = 1.0f;

        }

        else

        {

            LightColor = FLinearColor(0.1f, 0.1f, 0.2f, 1.0f);

            LightIntensity = 0.3f;

        }



        DirectionalLight->SetLightColor(LightColor);

        DirectionalLight->SetIntensity(LightIntensity);



        // 调整方向光的方向

        FRotator Light Direction = FRotator(-FMath::Sin(TimeOfDay * PI / 12.0f) * 45.0f, 0.0f, 0.0f);

        DirectionalLight->SetActorRotation(LightDirection);

    }



    // 调整点光颜色和强度

    APointLight* PointLight = Cast<APointLight>(UGameplayStatics::GetActorOfClass(GetWorld(), APointLight::StaticClass()));

    if (PointLight)

    {

        FLinearColor LightColor;

        float LightIntensity;



        if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

        {

            LightColor = FLinearColor(1.0f, 0.9f, 0.8f, 1.0f);

            LightIntensity = 2000.0f;

        }

        else

        {

            LightColor = FLinearColor(0.1f, 0.1f, 0.2f, 1.0f);

            LightIntensity = 500.0f;

        }



        PointLight->SetLightColor(LightColor);

        PointLight->SetIntensity(LightIntensity);

    }

}

13.5.3 动态天气效果

动态天气效果可以模拟不同的天气条件,如晴天、阴天、雨天和雪天。这些效果可以通过调整天空颜色、云层密度、光照强度和后处理效果来实现。


// 天气控制器Actor

AWeatherController::AWeatherController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void AWeatherController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新天气参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    float CloudDensity = FMath::Sin(TimeOfDay * PI / 12.0f) * 0.5f + 0.5f;

    float FogDensity = FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f);

    SetWeatherParameters(TimeOfDay, CloudDensity, FogDensity);

}



void AWeatherController::SetWeatherParameters(float TimeOfDay, float CloudDensity, float FogDensity)

{

    // 调整天空颜色

    FLinearColor SkyColor;

    if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

    {

        SkyColor = FLinearColor(0.5f, 0.7f, 1.0f, 1.0f);

    }

    else

    {

        SkyColor = FLinearColor(0.1f, 0.1f, 0.3f, 1.0f);

    }



    // 更新天空球材质参数

    ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

    if (SkySphere)

    {

        UMaterialInstanceDynamic* SkyMaterialInstance = SkySphere->GetDynamicMaterial();

        if (SkyMaterialInstance)

        {

            SkyMaterialInstance->SetVectorParameterValue(TEXT("SkyColor"), SkyColor);

            SkyMaterialInstance->SetScalarParameterValue(TEXT("CloudDensity"), CloudDensity);

        }

    }



    // 更新天空光参数

    ASkyLight* SkyLight = Cast<ASkyLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass()));

    if (SkyLight)

    {

        SkyLight->SetIntensity(1.5f * (1.0f - CloudDensity));

    }



    // 更新大气雾参数

    AAtmosphericFog* AtmosphericFog = Cast<AAtmosphericFog>(UGameplayStatics::GetActorOfClass(GetWorld(), AAtmosphericFog::StaticClass()));

    if (AtmosphericFog)

    {

        AtmosphericFog->SetSunDiskIntensity(10.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

        AtmosphericFog->SetScatteringIntensity(2.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

        AtmosphericFog->SetFogDensity(FogDensity);

    }



    // 更新后处理体积参数

    APostProcessVolume* PostProcessVolume = Cast<APostProcessVolume>(UGameplayStatics::GetActorOfClass(GetWorld(), APostProcessVolume::StaticClass()));

    if (PostProcessVolume)

    {

        FPostProcessSettings& Settings = PostProcessVolume->Settings;

        Settings.bOverride_SkyAtmosphere = true;

        Settings.SkyAtmosphere = FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f);

        Settings.bOverride_ScreenSpaceAO = true;

        Settings.ScreenSpaceAOIntensity = 1.0f * (1.0f - CloudDensity);

    }

}

13.5.4 动态天气和光照效果的结合

为了实现更加逼真的天气和光照效果,可以将时间控制器和天气控制器结合起来,共同调整天空颜色、云层密度、光照强度和后处理效果。


// 组合控制器Actor

ACombinedController::ACombinedController()

{

    PrimaryActorTick.bCanEverTick = true;

}



void ACombinedController::Tick(float DeltaTime)

{

    Super::Tick(DeltaTime);



    // 更新时间参数

    float TimeOfDay = FMath::Fmod(GetGameTimeSinceCreation() + 12.0f, 24.0f);

    SetCombinedParameters(TimeOfDay);

}



void ACombinedController::SetCombinedParameters(float TimeOfDay)

{

    float CloudDensity = FMath::Sin(TimeOfDay * PI / 12.0f) * 0.5f + 0.5f;

    float FogDensity = FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f);



    // 调整天空颜色

    FLinearColor SkyColor;

    if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

    {

        SkyColor = FLinearColor(0.5f, 0.7f, 1.0f, 1.0f);

    }

    else

    {

        SkyColor = FLinearColor(0.1f, 0.1f, 0.3f, 1.0f);

    }



    // 更新天空球材质参数

    ASkySphere* SkySphere = Cast<ASkySphere>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkySphere::StaticClass()));

    if (SkySphere)

    {

        UMaterialInstanceDynamic* SkyMaterialInstance = SkySphere->GetDynamicMaterial();

        if (SkyMaterialInstance)

        {

            SkyMaterialInstance->SetVectorParameterValue(TEXT("SkyColor"), SkyColor);

            SkyMaterialInstance->SetScalarParameterValue(TEXT("CloudDensity"), CloudDensity);

        }

    }



    // 更新天空光参数

    ASkyLight* SkyLight = Cast<ASkyLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ASkyLight::StaticClass()));

    if (SkyLight)

    {

        SkyLight->SetIntensity(1.5f * (1.0f - CloudDensity));

    }



    // 更新大气雾参数

    AAtmosphericFog* AtmosphericFog = Cast<AAtmosphericFog>(UGameplayStatics::GetActorOfClass(GetWorld(), AAtmosphericFog::StaticClass()));

    if (AtmosphericFog)

    {

        AtmosphericFog->SetSunDiskIntensity(10.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

        AtmosphericFog->SetScatteringIntensity(2.0f * FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f));

        AtmosphericFog->SetFogDensity(FogDensity);

    }



    // 更新后处理体积参数

    APostProcessVolume* PostProcessVolume = Cast<APostProcessVolume>(UGameplayStatics::GetActorOfClass(GetWorld(), APostProcessVolume::StaticClass()));

    if (PostProcessVolume)

    {

        FPostProcessSettings& Settings = PostProcessVolume->Settings;

        Settings.bOverride_SkyAtmosphere = true;

        Settings.SkyAtmosphere = FMath::Clamp((TimeOfDay - 6.0f) / 12.0f, 0.0f, 1.0f);

        Settings.bOverride_ScreenSpaceAO = true;

        Settings.ScreenSpaceAOIntensity = 1.0f * (1.0f - CloudDensity);

    }



    // 调整方向光颜色和强度

    ADirectionalLight* DirectionalLight = Cast<ADirectionalLight>(UGameplayStatics::GetActorOfClass(GetWorld(), ADirectionalLight::StaticClass()));

    if (DirectionalLight)

    {

        FLinearColor LightColor;

        float LightIntensity;



        if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

        {

            LightColor = FLinearColor(1.0f, 1.0f, 0.9f, 1.0f);

            LightIntensity = 1.0f;

        }

        else

        {

            LightColor = FLinearColor(0.1f, 0.1f, 0.2f, 1.0f);

            LightIntensity = 0.3f;

        }



        DirectionalLight->SetLightColor(LightColor);

        DirectionalLight->SetIntensity(LightIntensity);



        // 调整方向光的方向

        FRotator LightDirection = FRotator(-FMath::Sin(TimeOfDay * PI / 12.0f) * 45.0f, 0.0f, 0.0f);

        DirectionalLight->SetActorRotation(LightDirection);

    }



    // 调整点光颜色和强度

    APointLight* PointLight = Cast<APointLight>(UGameplayStatics::GetActorOfClass(GetWorld(), APointLight::StaticClass()));

    if (PointLight)

    {

        FLinearColor LightColor;

        float LightIntensity;



        if (TimeOfDay >= 6.0f && TimeOfDay < 18.0f)

        {

            LightColor = FLinearColor(1.0f, 0.9f, 0.8f, 1.0f);

            LightIntensity = 2000.0f;

        }

        else

        {

            LightColor = FLinearColor(0.1f, 0.1f, 0.2f, 1.0f);

            LightIntensity = 500.0f;

        }



        PointLight->SetLightColor(LightColor);

        PointLight->SetIntensity(LightIntensity);

    }

}

通过这些步骤,可以实现一个动态且逼真的天空和光照效果系统,提升游戏的视觉表现力和沉浸感。动态天气和光照效果不仅可以根据时间变化,还可以根据玩家的行为或其他游戏事件进行实时调整,使游戏世界更加生动和真实。
在这里插入图片描述

你可能感兴趣的:(游戏开发2,虚幻,游戏引擎,人工智能,java,前端)