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