UE4战争迷雾的制作

1.首先做个材质放在Content/Fow/目录下





2.build.cs里加上

PrivateDependencyModuleNames.AddRange(new string[] { "RHI", "RenderCore" });

3.添加一个叫Profow的Actor

.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/Actor.h"
#include "ProFow.generated.h"

UCLASS()
class TTTTT_API AProFow : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AProFow();

	virtual void PostInitializeComponents() override;

	// Set the fog size
	void setSize(float s);

	// Reveal a portion of the fow
	void revealSmoothCircle(const FVector2D &pos, float radius);

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	
	void UpdateTextureRegions(UTexture2D* Texture, int32 MipIndex, uint32 NumRegions, FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData);

	// Fow texture size
	static const int m_textureSize = 512;

	UPROPERTY()
		UStaticMeshComponent* m_squarePlane;
		//TSubobjectPtr<UStaticMeshComponent> m_squarePlane;
	UPROPERTY(EditAnywhere, Category = "ProFow")
		UTexture2D* m_dynamicTexture;
	UPROPERTY()
		UMaterialInterface* m_dynamicMaterial;
	UPROPERTY()
		UMaterialInstanceDynamic *m_dynamicMaterialInstance;
	uint8 m_pixelArray[m_textureSize * m_textureSize];
		FUpdateTextureRegion2D m_wholeTextureReagion;
	float m_coverSize;
	UPROPERTY(EditAnywhere, Category = "ProFow")
		APawn* myPawn;
	UPROPERTY(EditAnywhere, Category = "ProFow")
		bool bIsMMOBA = false;
};
.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "TTTTT.h"
#include "ProFow.h"


// Sets default values
AProFow::AProFow() :m_wholeTextureReagion(0, 0, 0, 0, m_textureSize, m_textureSize)
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	m_coverSize = 5000;

	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Create a planar mesh from engine's planar static mesh
	m_squarePlane = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Fow Plane Static Mesh"));
	RootComponent = m_squarePlane;
	m_squarePlane->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
	{
		static ConstructorHelpers::FObjectFinder<UStaticMesh> asset(TEXT("StaticMesh'/Engine/ArtTools/RenderToTexture/Meshes/S_1_Unit_Plane.S_1_Unit_Plane'"));
		m_squarePlane->SetStaticMesh(asset.Object);
	}
	m_squarePlane->TranslucencySortPriority = 100;
	m_squarePlane->SetRelativeScale3D(FVector(m_coverSize, m_coverSize, 1));

	// Load the base material from your created material
	{
		static ConstructorHelpers::FObjectFinder<UMaterial> asset(TEXT("Material'/Game/Fow/FowMat.FowMat'"));
		m_dynamicMaterial = asset.Object;
	}
	
	// Create the runtime FOW texture
	if (!m_dynamicTexture)
	{
		m_dynamicTexture = UTexture2D::CreateTransient(m_textureSize, m_textureSize, PF_G8);
		m_dynamicTexture->CompressionSettings = TextureCompressionSettings::TC_Grayscale;
		m_dynamicTexture->SRGB = 0;
		m_dynamicTexture->UpdateResource();
		m_dynamicTexture->MipGenSettings = TMGS_NoMipmaps;
	}

	// Initialise array to all black
	for (int x = 0; x < m_textureSize; ++x)
		for (int y = 0; y < m_textureSize; ++y)
			m_pixelArray[y * m_textureSize + x] = 255;
	
	// Propagate memory's array to texture
	if (m_dynamicTexture)
		UpdateTextureRegions(m_dynamicTexture, 0, 1, &m_wholeTextureReagion, m_textureSize, 1, m_pixelArray, false);
		
}

void AProFow::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	// Create a dynamic material instance to swap in the FOW texture
	if (m_dynamicMaterial)
	{
		m_dynamicMaterialInstance = UMaterialInstanceDynamic::Create(m_dynamicMaterial, this);
		m_dynamicMaterialInstance->SetTextureParameterValue("FowTexture", m_dynamicTexture);
	}

	// Set the dynamic material to the mesh
	if (m_dynamicMaterialInstance)
		m_squarePlane->SetMaterial(0, m_dynamicMaterialInstance);
}

void AProFow::setSize(float s)
{
	m_coverSize = s;
	m_squarePlane->SetRelativeScale3D(FVector(m_coverSize, m_coverSize, 1));
}

void AProFow::revealSmoothCircle(const FVector2D &pos, float radius)
{
	// Calculate the where circle center is inside texture space
	FVector2D texel = pos - FVector2D(GetActorLocation().X, GetActorLocation().Y);
	texel = texel * m_textureSize / m_coverSize;
	texel += FVector2D(m_textureSize / 2, m_textureSize / 2);

	// Calculate radius in texel unit ( 1 is 1 pixel )
	float texelRadius = radius * m_textureSize / m_coverSize;

	// The square area to update
	int minX = FMath::Clamp<int>(texel.X - texelRadius, 0, m_textureSize - 1);
	int minY = FMath::Clamp<int>(texel.Y - texelRadius, 0, m_textureSize - 1);
	int maxX = FMath::Clamp<int>(texel.X + texelRadius, 0, m_textureSize - 1);
	int maxY = FMath::Clamp<int>(texel.Y + texelRadius, 0, m_textureSize - 1);
	uint8 theVal = 0;
	
	// Update our array of fow value in memory
	bool dirty = false;
	for (int x = minX; x < maxX; ++x)
	{
		for (int y = minY; y < maxY; ++y)
		{
			float distance = FVector2D::Distance(texel, FVector2D(x, y));
			if (distance < texelRadius)
			{
				static float smoothPct = 0.7f;

				uint8 oldVal = m_pixelArray[y * m_textureSize + x];
				float lerp = FMath::GetMappedRangeValueClamped(FVector2D(smoothPct, 1.0f), FVector2D(0, 1), distance / texelRadius);
				uint8 newVal = lerp * 255;
				newVal = FMath::Min(newVal, oldVal);

				m_pixelArray[y * m_textureSize + x] = newVal;
				dirty = dirty || oldVal != newVal;
			}
		}
	}

	// Propagate the values in memory's array to texture
	if (dirty)
		UpdateTextureRegions(m_dynamicTexture, 0, 1, &m_wholeTextureReagion, m_textureSize, 1, m_pixelArray, false);
}

// Called when the game starts or when spawned
void AProFow::BeginPlay()
{
	Super::BeginPlay();
	PostInitializeComponents();
}

// Called every frame
void AProFow::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if (myPawn)
	{
		if (bIsMMOBA)
		{
			for (int x = 0; x < m_textureSize; ++x)
				for (int y = 0; y < m_textureSize; ++y)
					m_pixelArray[y * m_textureSize + x] = 255;
		}
		revealSmoothCircle(FVector2D(myPawn->GetActorLocation().X, myPawn->GetActorLocation().Y), 300);
		//GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("mypawn"));
		//UE_LOG(LogTemp, Warning, TEXT(" find mypawn"));
	}
	else
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("nomypawn"));
		//UE_LOG(LogTemp, Warning, TEXT("no find mypawn"));
	}
}

void AProFow::UpdateTextureRegions(UTexture2D* Texture, int32 MipIndex, uint32 NumRegions, FUpdateTextureRegion2D* Regions, uint32 SrcPitch, uint32 SrcBpp, uint8* SrcData, bool bFreeData)
{
	if (Texture)
	{
		if (Texture->Resource)
		{
			struct FUpdateTextureRegionsData
			{
				FTexture2DResource* Texture2DResource;
				int32 MipIndex;
				uint32 NumRegions;
				FUpdateTextureRegion2D* Regions;
				uint32 SrcPitch;
				uint32 SrcBpp;
				uint8* SrcData;
			};

			FUpdateTextureRegionsData* RegionData = new FUpdateTextureRegionsData;

			RegionData->Texture2DResource = (FTexture2DResource*)Texture->Resource;
			RegionData->MipIndex = MipIndex;
			RegionData->NumRegions = NumRegions;
			RegionData->Regions = Regions;
			RegionData->SrcPitch = SrcPitch;
			RegionData->SrcBpp = SrcBpp;
			RegionData->SrcData = SrcData;

			ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
				UpdateTextureRegionsData,
				FUpdateTextureRegionsData*, RegionData, RegionData,
				bool, bFreeData, bFreeData,
				{
					for (uint32 RegionIndex = 0; RegionIndex < RegionData->NumRegions; ++RegionIndex)
					{
						int32 CurrentFirstMip = RegionData->Texture2DResource->GetCurrentFirstMip();
						if (RegionData->MipIndex >= CurrentFirstMip)
						{
							RHIUpdateTexture2D(
								RegionData->Texture2DResource->GetTexture2DRHI(),
								RegionData->MipIndex - CurrentFirstMip,
								RegionData->Regions[RegionIndex],
								RegionData->SrcPitch,
								RegionData->SrcData
								+ RegionData->Regions[RegionIndex].SrcY * RegionData->SrcPitch
								+ RegionData->Regions[RegionIndex].SrcX * RegionData->SrcBpp
							);
						}
					}
			if (bFreeData)
			{
				FMemory::Free(RegionData->Regions);
				FMemory::Free(RegionData->SrcData);
			}
			delete RegionData;
				});
		}
	}
}
5.把自己的角色添加进来就可以了

参考:http://phungdinhthang.com/2016/12/12/unreal-engine-4-fog-of-war-tutorial/?i=1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值