修改设置碰撞的时候能获取UV,模型用复杂碰撞。修改不用计算Shader而是直接用材质,直接在UV空间模拟计算形变并累积
This commit is contained in:
@@ -102,3 +102,6 @@ AppliedDefaultGraphicsPerformance=Maximum
|
||||
+ActiveClassRedirects=(OldClassName="TP_FirstPersonGameMode",NewClassName="BladeSmithGameMode")
|
||||
+ActiveClassRedirects=(OldClassName="TP_FirstPersonCharacter",NewClassName="BladeSmithCharacter")
|
||||
|
||||
[/Script/Engine.PhysicsSettings]
|
||||
bSupportUVFromHitResults=True
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
+109
-88
@@ -16,6 +16,8 @@
|
||||
#include "RHICommandList.h"
|
||||
#include "Engine/Texture.h"
|
||||
#include "GenericPlatform/GenericPlatformProcess.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetRenderingLibrary.h"
|
||||
|
||||
|
||||
// Sets default values
|
||||
@@ -105,15 +107,15 @@ UTextureRenderTarget2D* AIronBlock::CreateDeformRT(const FString& RTName, int32
|
||||
if (RenderTarget)
|
||||
{
|
||||
// **关键修复 1:** 设置为32位浮点数格式,以匹配 FLinearColor 和 CS 的 PF_A32B32G32R32F
|
||||
//RenderTarget->RenderTargetFormat = RTF_RGBA32f;
|
||||
RenderTarget->RenderTargetFormat = RTF_RGBA32f;
|
||||
|
||||
// **关键修复 2:** 明确告诉引擎我们需要为这个纹理创建UAV
|
||||
RenderTarget->bCanCreateUAV = true;
|
||||
//RenderTarget->bCanCreateUAV = true;
|
||||
|
||||
RenderTarget->InitCustomFormat(Size, Size, PF_A32B32G32R32F, false);
|
||||
RenderTarget->bNeedsTwoCopies = true; // 告知引擎这个纹理会被用于Ping-Pong,优化内存
|
||||
//RenderTarget->SizeX = Size;
|
||||
//RenderTarget->SizeY = Size;
|
||||
RenderTarget->SizeX = Size;
|
||||
RenderTarget->SizeY = Size;
|
||||
RenderTarget->bAutoGenerateMips = false;
|
||||
RenderTarget->AddressX = TA_Clamp;
|
||||
RenderTarget->AddressY = TA_Clamp;
|
||||
@@ -129,33 +131,33 @@ void AIronBlock::InitializePositionTexture()
|
||||
{
|
||||
CalculateLocalBounds();
|
||||
|
||||
// 获取顶点位置 (用于计算初始UV->WorldPos)
|
||||
TArray<FVector3f> VertexPositions;
|
||||
GetStaticMeshVertexPositions(VertexPositions);
|
||||
// // 获取顶点位置 (用于计算初始UV->WorldPos)
|
||||
// TArray<FVector3f> VertexPositions;
|
||||
// GetStaticMeshVertexPositions(VertexPositions);
|
||||
|
||||
// 创建位置纹理
|
||||
const int32 TextureSize = 256; // 纹理尺寸
|
||||
TArray<FLinearColor> InitialData;
|
||||
InitialData.SetNum(TextureSize * TextureSize);
|
||||
|
||||
// 初始化纹理数据 (将UV映射到本地包围盒的XY平面)
|
||||
for (int32 Y = 0; Y < TextureSize; ++Y)
|
||||
{
|
||||
for (int32 X = 0; X < TextureSize; ++X)
|
||||
{
|
||||
int32 Index = Y * TextureSize + X;
|
||||
FVector2D UV(FVector2D(X, Y) / (TextureSize - 1.0f)); // 使用 255.0 或 (Size-1)
|
||||
|
||||
// 将UV坐标转换为本地空间位置 (XY平面)
|
||||
FVector LocalPos(
|
||||
FMath::Lerp(LocalBounds.Min.X, LocalBounds.Max.X, UV.X),
|
||||
FMath::Lerp(LocalBounds.Min.Y, LocalBounds.Max.Y, UV.Y),
|
||||
LocalBounds.Min.Z // 假设初始是一个平面
|
||||
);
|
||||
|
||||
InitialData[Index] = FLinearColor(LocalPos.X * 1000, LocalPos.Y * 1000, LocalPos.Z * 1000, 1.0f);
|
||||
}
|
||||
}
|
||||
const int32 TextureSize = 1024; // 纹理尺寸
|
||||
// TArray<FLinearColor> InitialData;
|
||||
// InitialData.SetNum(TextureSize * TextureSize);
|
||||
//
|
||||
// // 初始化纹理数据 (将UV映射到本地包围盒的XY平面)
|
||||
// for (int32 Y = 0; Y < TextureSize; ++Y)
|
||||
// {
|
||||
// for (int32 X = 0; X < TextureSize; ++X)
|
||||
// {
|
||||
// int32 Index = Y * TextureSize + X;
|
||||
// FVector2D UV(FVector2D(X, Y) / (TextureSize - 1.0f)); // 使用 255.0 或 (Size-1)
|
||||
//
|
||||
// // 将UV坐标转换为本地空间位置 (XY平面)
|
||||
// FVector LocalPos(
|
||||
// FMath::Lerp(LocalBounds.Min.X, LocalBounds.Max.X, UV.X),
|
||||
// FMath::Lerp(LocalBounds.Min.Y, LocalBounds.Max.Y, UV.Y),
|
||||
// LocalBounds.Min.Z // 假设初始是一个平面
|
||||
// );
|
||||
//
|
||||
// InitialData[Index] = FLinearColor(LocalPos.X * 1000, LocalPos.Y * 1000, LocalPos.Z * 1000, 1.0f);
|
||||
// }
|
||||
// }
|
||||
|
||||
// --- 关键修复: 创建两个 RenderTarget ---
|
||||
PositionRenderTarget0 = CreateDeformRT(TEXT("PositionRT0"), TextureSize);
|
||||
@@ -165,39 +167,39 @@ void AIronBlock::InitializePositionTexture()
|
||||
// 我们需要将CPU端的 InitialData 写入到GPU纹理中
|
||||
// 最简单的方法是创建一个临时的UTexture2D,用BulkData上传,然后拷贝到RT
|
||||
|
||||
UTexture2D* TempTexture = UTexture2D::CreateTransient(TextureSize, TextureSize, PF_A32B32G32R32F); // 必须匹配格式
|
||||
if (TempTexture && PositionRenderTarget0 && PositionRenderTarget1)
|
||||
{
|
||||
// 锁定 Mip 并拷贝数据
|
||||
FTexture2DMipMap& Mip = TempTexture->GetPlatformData()->Mips[0];
|
||||
void* MipData = Mip.BulkData.Lock(LOCK_READ_WRITE);
|
||||
FMemory::Memcpy(MipData, InitialData.GetData(), InitialData.Num() * sizeof(FLinearColor));
|
||||
Mip.BulkData.Unlock();
|
||||
TempTexture->UpdateResource(); // 提交到GPU
|
||||
|
||||
// 获取RHI资源
|
||||
FTextureRHIRef DestRT0_RHI = GetRenderTargetRHI(PositionRenderTarget0);
|
||||
FTextureRHIRef DestRT1_RHI = GetRenderTargetRHI(PositionRenderTarget1);
|
||||
FTextureRHIRef SrcTex_RHI = TempTexture->GetResource() ? TempTexture->GetResource()->TextureRHI : nullptr;
|
||||
|
||||
if (DestRT0_RHI && DestRT1_RHI && SrcTex_RHI)
|
||||
{
|
||||
// 在渲染线程上执行拷贝
|
||||
ENQUEUE_RENDER_COMMAND(InitializeDeformRTs)(
|
||||
[DestRT0_RHI, DestRT1_RHI, SrcTex_RHI](FRHICommandListImmediate& RHICmdList)
|
||||
{
|
||||
// 将初始数据拷贝到两个RT
|
||||
RHICmdList.CopyTexture(SrcTex_RHI, DestRT0_RHI, {});
|
||||
RHICmdList.CopyTexture(SrcTex_RHI, DestRT1_RHI, {});
|
||||
});
|
||||
|
||||
// 确保拷贝完成
|
||||
FlushRenderingCommands();
|
||||
}
|
||||
}
|
||||
// UTexture2D* TempTexture = UTexture2D::CreateTransient(TextureSize, TextureSize, PF_A32B32G32R32F); // 必须匹配格式
|
||||
// if (TempTexture && PositionRenderTarget0 && PositionRenderTarget1)
|
||||
// {
|
||||
// // 锁定 Mip 并拷贝数据
|
||||
// FTexture2DMipMap& Mip = TempTexture->GetPlatformData()->Mips[0];
|
||||
// void* MipData = Mip.BulkData.Lock(LOCK_READ_WRITE);
|
||||
// FMemory::Memcpy(MipData, InitialData.GetData(), InitialData.Num() * sizeof(FLinearColor));
|
||||
// Mip.BulkData.Unlock();
|
||||
// TempTexture->UpdateResource(); // 提交到GPU
|
||||
//
|
||||
// // 获取RHI资源
|
||||
// FTextureRHIRef DestRT0_RHI = GetRenderTargetRHI(PositionRenderTarget0);
|
||||
// FTextureRHIRef DestRT1_RHI = GetRenderTargetRHI(PositionRenderTarget1);
|
||||
// FTextureRHIRef SrcTex_RHI = TempTexture->GetResource() ? TempTexture->GetResource()->TextureRHI : nullptr;
|
||||
//
|
||||
// if (DestRT0_RHI && DestRT1_RHI && SrcTex_RHI)
|
||||
// {
|
||||
// // 在渲染线程上执行拷贝
|
||||
// ENQUEUE_RENDER_COMMAND(InitializeDeformRTs)(
|
||||
// [DestRT0_RHI, DestRT1_RHI, SrcTex_RHI](FRHICommandListImmediate& RHICmdList)
|
||||
// {
|
||||
// // 将初始数据拷贝到两个RT
|
||||
// RHICmdList.CopyTexture(SrcTex_RHI, DestRT0_RHI, {});
|
||||
// RHICmdList.CopyTexture(SrcTex_RHI, DestRT1_RHI, {});
|
||||
// });
|
||||
//
|
||||
// // 确保拷贝完成
|
||||
// FlushRenderingCommands();
|
||||
// }
|
||||
// }
|
||||
|
||||
// 设置变形材质
|
||||
SetupDeformationMaterial(TempTexture);
|
||||
SetupDeformationMaterial(nullptr);
|
||||
UE_LOG(LogTemp, Log, TEXT("Position textures initialized"));
|
||||
}
|
||||
|
||||
@@ -240,21 +242,22 @@ void AIronBlock::SetupDeformationMaterial(UTexture2D* OrigTex)
|
||||
{
|
||||
BaseMaterial = LoadObject<UMaterial>(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial"));
|
||||
}
|
||||
|
||||
if (BaseMaterial)
|
||||
UMaterial* CalMaterial = LoadObject<UMaterial>(nullptr, TEXT("/Game/Materials/M_HitCal")); // 示例路径
|
||||
if (!CalMaterial)
|
||||
{
|
||||
CalMaterial = LoadObject<UMaterial>(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial"));
|
||||
}
|
||||
if (BaseMaterial && CalMaterial)
|
||||
{
|
||||
DynMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, this);
|
||||
DynCalMaterial = UMaterialInstanceDynamic::Create(CalMaterial, this);
|
||||
StaticMeshComp->SetMaterial(0, DynMaterial);
|
||||
|
||||
//StaticMeshComp->SetMaterial(1, DynCalMaterial);
|
||||
// 设置初始参数
|
||||
if (DynMaterial)
|
||||
{
|
||||
// 初始时读取 RT0
|
||||
DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"), OrigTex);
|
||||
//DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"), PositionRenderTarget0);
|
||||
DynMaterial->SetVectorParameterValue(TEXT("LocalBoundsMin"), FLinearColor(LocalBounds.Min));
|
||||
DynMaterial->SetVectorParameterValue(TEXT("LocalBoundsMax"), FLinearColor(LocalBounds.Max));
|
||||
DynMaterial->SetScalarParameterValue(TEXT("DeformationStrength"), 1.0f);
|
||||
DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"), PositionRenderTarget0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -267,30 +270,50 @@ void AIronBlock::SetupDeformationMaterial(UTexture2D* OrigTex)
|
||||
void AIronBlock::OnHammerHit(const FHitResult& HitResult)
|
||||
{
|
||||
// 获取锤子冲击力
|
||||
float ImpactForce = 0.0f;
|
||||
// 检查 HitResult.GetComponent() 是否有效
|
||||
if (HitResult.GetComponent() && !HitResult.GetComponent()->GetPhysicsLinearVelocity().IsNearlyZero())
|
||||
FVector2D HitUV;
|
||||
UGameplayStatics::FindCollisionUV(HitResult,0,HitUV);
|
||||
FVector ImpactNormal = -HitResult.ImpactNormal;
|
||||
CurrentDeformationRadius = 10.0f/1024.0f;
|
||||
UTextureRenderTarget2D* LastTex = nullptr;
|
||||
UTextureRenderTarget2D* CurTex = nullptr;
|
||||
if(CurrentTextureIndex == 0)
|
||||
{
|
||||
ImpactForce = HitResult.GetComponent()->GetPhysicsLinearVelocity().Size();
|
||||
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"),CurrentDeformationRadius);
|
||||
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;
|
||||
}
|
||||
// // 转换到本地空间
|
||||
// FVector ImpactPoint = HitResult.ImpactPoint;
|
||||
// FVector ImpactNormal = HitResult.ImpactNormal;
|
||||
// FVector LocalImpactPoint = GetTransform().InverseTransformPosition(ImpactPoint);
|
||||
// FVector LocalImpactNormal = GetTransform().InverseTransformVector(ImpactNormal);
|
||||
// UE_LOG(LogTemp,Display,TEXT("[AIronBlock::OnHammerHit] ImpactForce:%f,ImpactPoint:%s,ImpactNormal:%s,LocalImpactPoint:%s,LocalImpactNormal:%s")
|
||||
// ,ImpactForce,*ImpactPoint.ToString(),*ImpactNormal.ToString(),*LocalImpactPoint.ToString(),*LocalImpactNormal.ToString());
|
||||
// UpdateComputeShaderParams(LocalImpactPoint, LocalImpactNormal, ImpactForce);
|
||||
|
||||
// 默认冲击力
|
||||
if (ImpactForce < 10.0f) ImpactForce = 500.0f;
|
||||
|
||||
// 转换到本地空间
|
||||
FVector ImpactPoint = HitResult.ImpactPoint;
|
||||
FVector ImpactNormal = HitResult.ImpactNormal;
|
||||
FVector LocalImpactPoint = GetTransform().InverseTransformPosition(ImpactPoint);
|
||||
FVector LocalImpactNormal = GetTransform().InverseTransformVector(ImpactNormal);
|
||||
UE_LOG(LogTemp,Display,TEXT("[AIronBlock::OnHammerHit] ImpactForce:%f,ImpactPoint:%s,ImpactNormal:%s,LocalImpactPoint:%s,LocalImpactNormal:%s")
|
||||
,ImpactForce,*ImpactPoint.ToString(),*ImpactNormal.ToString(),*LocalImpactPoint.ToString(),*LocalImpactNormal.ToString());
|
||||
UpdateComputeShaderParams(LocalImpactPoint, LocalImpactNormal, ImpactForce);
|
||||
|
||||
ExecuteDeformationCS();
|
||||
//ExecuteDeformationCS();
|
||||
}
|
||||
|
||||
|
||||
void AIronBlock::UpdateComputeShaderParams(FVector LocalImpactPoint, FVector LocalImpactNormal, float ImpactForce)
|
||||
void AIronBlock::UpdateComputeShaderParams(FVector LocalImpactPoint, FVector LocalImpactNormal, float _ImpactForce)
|
||||
{
|
||||
// 更新碰撞参数
|
||||
CurrentImpactPoint = LocalImpactPoint;
|
||||
@@ -313,8 +336,6 @@ void AIronBlock::UpdateComputeShaderParams(FVector LocalImpactPoint, FVector Loc
|
||||
|
||||
// 切换纹理缓冲索引
|
||||
CurrentTextureIndex = 1 - CurrentTextureIndex;
|
||||
UE_LOG(LogTemp,Display,TEXT("[AIronBlock::OnHammerHitUpdateComputeShaderParams]CurrentImpactForce:%f, CurrentImpactPoint:%s,CurrentImpactNormal:%s,CurrentDeformationRadius:%f,CurrentPlasticity:%f")
|
||||
,CurrentImpactForce,*CurrentImpactPoint.ToString(),*CurrentImpactNormal.ToString(),CurrentDeformationRadius,CurrentPlasticity);
|
||||
}
|
||||
|
||||
void AIronBlock::ExecuteDeformationCS()
|
||||
|
||||
@@ -32,6 +32,13 @@ class BLADESMITH_API AIronBlock : public AActor
|
||||
UPROPERTY()
|
||||
UMaterialInstanceDynamic* DynMaterial;
|
||||
|
||||
/** 应用于网格的动态材质实例 */
|
||||
UPROPERTY()
|
||||
UMaterialInstanceDynamic* DynCalMaterial;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
float ImpactForce;
|
||||
|
||||
public:
|
||||
// Sets default values for this actor's properties
|
||||
AIronBlock();
|
||||
|
||||
Reference in New Issue
Block a user