虚幻4渲染编程(环境模拟篇)【第七卷:海洋模拟-上-海洋模拟理论推导】

本文介绍了虚幻4中海洋模拟的技术,包括基础环境搭建,使用Gerstner Wave创建初步波浪,以及深入的FFT海面理论推导和实现步骤,探讨了如何通过FFT变换生成逼真的海面效果。
摘要由CSDN通过智能技术生成

我的专栏目录:

小IVan:专题概述及目录

简介:

海洋这个要素在游戏里占比越来越多,开放世界的游戏要求角色能上天入地下水。目前游戏里做海洋的方法就那几种。(1)预烘焙法(2)Gerstner wave(3)FFT海洋。预烘焙法可以是实现烘焙好DisplacementMap或者是FFT的运算结果。Gerstner wave可以在GPU或者CPU上算。FFT的话就是拿海洋频率模型算出Displacement。


【1】基础环境搭建

在开始研究之前我们需要先搭建起我们的环境。我选择在ComputeShader种完成各种计算,然后在顶点着色器种直接Sample前面的ComputeShader的波形计算结果。不要把波形的计算塞到VertexShader里。把波形计算独立出来还有个好处就是我能把波形的结果储存起来拿给其它效果使用,比如制作浮力部分的时候我们就需要知道海面波形的信息,如果塞VertexShader里就拿不到这些信息了。

搭建ComputeShader的方法前面我的文章有提到,这里我就直接贴代码了。使用的引擎版本是4.21.0,如果引擎更新了新版本可能代码有一点区别。FFT部分我会给出4.22的代码。

如果不是在Unreal中实现或者不想做这么复杂,可以直接跳过这部分。

v2-4ab738bee9f2f0f9000ffab4845f0bb3_b.jpg
v2-dc8f6793cb3b3573ec7cc7995691837d_b.jpg

SDHOcean.build.cs

        // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class SDHOcean : ModuleRules
{
	public SDHOcean(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
		
		PublicIncludePaths.AddRange(
			new string[] {
				// ... add public include paths required here ...
			}
			);
				
		
		PrivateIncludePaths.AddRange(
			new string[] {
				// ... add other private include paths required here ...
			}
			);
			
		
		PublicDependencyModuleNames.AddRange(
			new string[]
			{
                "Core",
                "CoreUObject",
                "Engine",
                "RHI",
                "Engine",
                "RenderCore",
                "ShaderCore",
				// ... add other public dependencies that you statically link with here ...
			}
			);
			
		
		PrivateDependencyModuleNames.AddRange(
			new string[]
			{
                "CoreUObject",
                "Engine",
                "Slate",
                "SlateCore",
                "UnrealEd",
                "Projects",
				// ... add private dependencies that you statically link with here ...	
			}
			);
		
		
		DynamicallyLoadedModuleNames.AddRange(
			new string[]
			{
				// ... add any modules that your module loads dynamically here ...
			}
			);
	}
}
      

SDHOcean.h

        // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/Paths.h"
#include "Modules/ModuleManager.h"

class FSDHOceanModule : public IModuleInterface
{
public:

	/** IModuleInterface implementation */
	virtual void StartupModule() override;
	virtual void ShutdownModule() override;
};
      

SDHOcean.cpp

        // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "SDHOcean.h"

#define LOCTEXT_NAMESPACE "FSDHOceanModule"

void FSDHOceanModule::StartupModule()
{
	// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
	FString PluginShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("SDHOcean"))->GetBaseDir(), TEXT("Shaders"));
	AddShaderSourceDirectoryMapping(TEXT("/Plugin/SDHOcean"), PluginShaderDir);
}

void FSDHOceanModule::ShutdownModule()
{
	// This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
	// we call this function before unloading the module.
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FSDHOceanModule, SDHOcean)
      

Ocean.h

        #pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Runtime/Engine/Classes/Components/ActorComponent.h"
#include "Engine/Classes/Engine/TextureRenderTarget2D.h"
#include "Ocean.generated.h"

typedef TRefCountPtr<class FRHITexture2D> FTexture2DRHIRef;
typedef TRefCountPtr<class FRHIUnorderedAccessView> FUnorderedAccessViewRHIRef;
typedef TRefCountPtr<class FRHIStructuredBuffer> FStructuredBufferRHIRef;
class FRHITexture;
class FRHIUnorderedAccessView;
class FRHICommandListImmediate;

USTRUCT(BlueprintType)
struct FOceanBasicStructData_GameThread
{
	GENERATED_USTRUCT_BODY()

	FOceanBasicStructData_GameThread(){}

	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	FVector4 OceanTime_GameThread;
};

UCLASS(hidecategories = (Object, LOD, Physics, Collision), editinlinenew, meta = (BlueprintSpawnableComponent), ClassGroup = Rendering, DisplayName = "OceanRenderComp")
class SDHOCEAN_API UOceanRenderComponent : public UActorComponent
{
	GENERATED_BODY()

public:

	UOceanRenderComponent(const FObjectInitializer& ObjectInitializer);
	//~ Begin UActorComponent Interface.
	virtual void OnRegister() override;
	virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;

	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "OceanComponent")
	UTextureRenderTarget2D* OutputRenderTarget2D;

	//UniformData for Ocean render
	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "OceanComponent")
	FOceanBasicStructData_GameThread OceanUniformDataBuffer;

	int32 TargetSize;
	ETextureRenderTargetFormat RenderTargetFormat;

private:

	//Render ocean render thread
	void OceanCalculating_GameThread();
	void OceanCalculating_RenderThread
	(
		FRHICommandListImmediate& RHICmdList,
		ERHIFeatureLevel::Type FeatureLevel,
		FRHITexture* OutputRenderTarget,
		int32 SurfaceSize,
		const FOceanBasicStructData_GameThread& OceanUniformData
	);
	
	FTexture2DRHIRef OutputTexture;
	FUnorderedAccessViewRHIRef OutputTextureUAV;
};

      

Ocean.cpp

        #include "SDHOcean/Public/Ocean.h"

#include "ShaderCore/Public/GlobalShader.h"

#include "Classes/Engine/World.h"
#include "Public/GlobalShader.h"
#include "Public/PipelineStateCache.h"
#include "Public/RHIStaticStates.h"
#include "Public/SceneUtils.h"
#include "Public/SceneInterface.h"
#include "Public/ShaderParameterUtils.h"
#include "Public/Logging/MessageLog.h"
#include "Public/Internationaliz
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值