183 lines
6.0 KiB
C++
183 lines
6.0 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "IronBlock.h"
|
|
// 确保包含了 RDG 所需的头文件
|
|
#include "RenderGraphBuilder.h"
|
|
#include "RenderGraphUtils.h" // FComputeShaderUtils::AddPass
|
|
#include "FDeformComputeShader.h" // 确保这个头文件存在且包含了 FDeformationCSDispatchParams
|
|
#include "StaticMeshResources.h"
|
|
#include "TextureResource.h"
|
|
#include "Engine/TextureRenderTarget2D.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Engine/Texture2D.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
#include "PhysicsEngine/BodySetup.h"
|
|
#include "RHICommandList.h"
|
|
#include "Engine/Texture.h"
|
|
#include "GenericPlatform/GenericPlatformProcess.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Kismet/KismetRenderingLibrary.h"
|
|
|
|
|
|
// Sets default values
|
|
AIronBlock::AIronBlock() : StaticMeshComp(nullptr), DeformBaseMat(nullptr), DeformCalMat(nullptr),
|
|
PositionRenderTarget0(nullptr), PositionRenderTarget1(nullptr),
|
|
DynMaterial(nullptr), DynCalMaterial(nullptr)
|
|
{
|
|
// 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;
|
|
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
|
|
StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComponent"));
|
|
StaticMeshComp->AttachToComponent(RootComponent,FAttachmentTransformRules::SnapToTargetIncludingScale);
|
|
//RootComponent = StaticMeshComp;
|
|
}
|
|
void AIronBlock::PostInitProperties()
|
|
{
|
|
// 必须调用父类实现
|
|
Super::PostInitProperties();
|
|
|
|
// 检查:如果 StaticMeshComp 没有被赋予任何网格(即在编辑器中没有设置)
|
|
// 并且我们正在处理 Class Default Object (CDO),通常用来设置类级的默认值
|
|
if (StaticMeshComp && !StaticMeshComp->GetStaticMesh())
|
|
{
|
|
// 只有当网格为空时,才加载并设置默认的 Cube
|
|
UStaticMesh* DefaultMesh = LoadObject<UStaticMesh>(nullptr, TEXT("/Engine/BasicShapes/Cube"));
|
|
if (DefaultMesh)
|
|
{
|
|
StaticMeshComp->SetStaticMesh(DefaultMesh);
|
|
}
|
|
}
|
|
}
|
|
// Called when the game starts or when spawned
|
|
void AIronBlock::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
InitializePositionTexture();
|
|
}
|
|
|
|
/**
|
|
* 核心修复:创建一个配置好用于变形计算的 RenderTarget
|
|
*/
|
|
UTextureRenderTarget2D* AIronBlock::CreateDeformRT(const FString& RTName, int32 Size)
|
|
{
|
|
UTextureRenderTarget2D* RenderTarget = NewObject<UTextureRenderTarget2D>(this, FName(*RTName));
|
|
if (RenderTarget)
|
|
{
|
|
RenderTarget->InitCustomFormat(Size, Size, PF_A32B32G32R32F, false);
|
|
RenderTarget->bNeedsTwoCopies = true; // 告知引擎这个纹理会被用于Ping-Pong,优化内存
|
|
RenderTarget->SizeX = Size;
|
|
RenderTarget->SizeY = Size;
|
|
RenderTarget->bAutoGenerateMips = false;
|
|
RenderTarget->AddressX = TA_Clamp;
|
|
RenderTarget->AddressY = TA_Clamp;
|
|
FLinearColor ClearColor = FLinearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
|
RenderTarget->ClearColor = ClearColor;
|
|
// 立即创建RHI资源
|
|
RenderTarget->UpdateResource();
|
|
|
|
// 调用 Kismet Rendering Library 的清除函数
|
|
UKismetRenderingLibrary::ClearRenderTarget2D(
|
|
this->GetWorld(), // 通常传入你的 World 或 Actor
|
|
RenderTarget,
|
|
ClearColor
|
|
);
|
|
//FlushRenderingCommands();
|
|
//RenderTarget->UpdateResourceImmediate(true);
|
|
}
|
|
return RenderTarget;
|
|
}
|
|
|
|
|
|
void AIronBlock::InitializePositionTexture()
|
|
{
|
|
// --- 关键修复: 创建两个 RenderTarget ---
|
|
PositionRenderTarget0 = CreateDeformRT(TEXT("PositionRT0"), TexSize);
|
|
PositionRenderTarget1 = CreateDeformRT(TEXT("PositionRT1"), TexSize);
|
|
|
|
// 设置变形材质
|
|
SetupDeformationMaterial(nullptr);
|
|
UE_LOG(LogTemp, Log, TEXT("Position textures initialized"));
|
|
}
|
|
|
|
void AIronBlock::SetupDeformationMaterial(UTexture2D* OrigTex)
|
|
{
|
|
// 创建动态材质实例
|
|
if (StaticMeshComp)
|
|
{
|
|
if (!DeformBaseMat)
|
|
{
|
|
DeformBaseMat = LoadObject<UMaterial>(nullptr, TEXT("/Game/Res/Materials/M_Iron"));
|
|
}
|
|
if (!DeformBaseMat)
|
|
{
|
|
DeformBaseMat = LoadObject<UMaterial>(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial"));
|
|
}
|
|
if (!DeformCalMat)
|
|
{
|
|
DeformCalMat = LoadObject<UMaterial>(nullptr, TEXT("/Game/Res/Materials/M_HitCal"));
|
|
}
|
|
if (!DeformCalMat)
|
|
{
|
|
DeformCalMat = LoadObject<UMaterial>(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial"));
|
|
}
|
|
if (DeformBaseMat && DeformCalMat)
|
|
{
|
|
DynMaterial = UMaterialInstanceDynamic::Create(DeformBaseMat, this);
|
|
DynCalMaterial = UMaterialInstanceDynamic::Create(DeformCalMat, this);
|
|
StaticMeshComp->SetMaterial(0, DynMaterial);
|
|
// 设置初始参数
|
|
if (DynMaterial)
|
|
{
|
|
// 初始时读取 RT0
|
|
DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"), PositionRenderTarget0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogTemp, Warning, TEXT("Failed to load base material for iron block"));
|
|
}
|
|
}
|
|
}
|
|
|
|
void AIronBlock::OnHammerHit(const FHitResult& HitResult)
|
|
{
|
|
// 获取锤子冲击力
|
|
FVector2D HitUV;
|
|
UGameplayStatics::FindCollisionUV(HitResult,0,HitUV);
|
|
FVector ImpactNormal = -HitResult.ImpactNormal;
|
|
float DeformationRadius = ImpactAffectRange/TexSize;
|
|
UTextureRenderTarget2D* LastTex = nullptr;
|
|
UTextureRenderTarget2D* CurTex = nullptr;
|
|
if(CurrentTextureIndex == 0)
|
|
{
|
|
LastTex = PositionRenderTarget0;
|
|
CurTex = PositionRenderTarget1;
|
|
}
|
|
else
|
|
{
|
|
LastTex = PositionRenderTarget1;
|
|
CurTex = PositionRenderTarget0;
|
|
}
|
|
if(DynCalMaterial)
|
|
{
|
|
DynCalMaterial->SetVectorParameterValue(TEXT("ImpactUV"), FLinearColor(HitUV.X,HitUV.Y,0,0));
|
|
DynCalMaterial->SetScalarParameterValue(TEXT("ImpactForce"),ImpactForce);
|
|
DynCalMaterial->SetScalarParameterValue(TEXT("ImpactRadius"), DeformationRadius);
|
|
DynCalMaterial->SetVectorParameterValue(TEXT("ImpactNormal"),ImpactNormal);
|
|
DynCalMaterial->SetTextureParameterValue(TEXT("LastPosition"),LastTex);
|
|
UKismetRenderingLibrary::DrawMaterialToRenderTarget(this->GetWorld(),CurTex,DynCalMaterial);
|
|
}
|
|
if(DynMaterial)
|
|
{
|
|
DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"),CurTex);
|
|
CurrentTextureIndex = 1 - CurrentTextureIndex;
|
|
}
|
|
}
|
|
|
|
// Called every frame
|
|
void AIronBlock::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
}
|