diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index 20b38fd..516f8ad 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -102,3 +102,6 @@ AppliedDefaultGraphicsPerformance=Maximum +ActiveClassRedirects=(OldClassName="TP_FirstPersonGameMode",NewClassName="BladeSmithGameMode") +ActiveClassRedirects=(OldClassName="TP_FirstPersonCharacter",NewClassName="BladeSmithCharacter") +[/Script/Engine.PhysicsSettings] +bSupportUVFromHitResults=True + diff --git a/Content/FirstPerson/Blueprints/BP_IronBlock.uasset b/Content/FirstPerson/Blueprints/BP_IronBlock.uasset index 5e077aa..e34a01f 100644 Binary files a/Content/FirstPerson/Blueprints/BP_IronBlock.uasset and b/Content/FirstPerson/Blueprints/BP_IronBlock.uasset differ diff --git a/Content/Materials/M_HitCal.uasset b/Content/Materials/M_HitCal.uasset new file mode 100644 index 0000000..519fde6 Binary files /dev/null and b/Content/Materials/M_HitCal.uasset differ diff --git a/Content/Materials/M_Iron.uasset b/Content/Materials/M_Iron.uasset index 31b9dde..9c2112e 100644 Binary files a/Content/Materials/M_Iron.uasset and b/Content/Materials/M_Iron.uasset differ diff --git a/Content/Res/Box2w4.uasset b/Content/Res/Box2w4.uasset index 56db3c7..3faf198 100644 Binary files a/Content/Res/Box2w4.uasset and b/Content/Res/Box2w4.uasset differ diff --git a/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/5/SI/6K90CL2ZSQWKILI9NQQLEA.uasset b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/5/SI/6K90CL2ZSQWKILI9NQQLEA.uasset index a42e84f..c991b1e 100644 Binary files a/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/5/SI/6K90CL2ZSQWKILI9NQQLEA.uasset and b/Content/__ExternalActors__/FirstPerson/Maps/FirstPersonMap/5/SI/6K90CL2ZSQWKILI9NQQLEA.uasset differ diff --git a/Source/BladeSmith/IronBlock.cpp b/Source/BladeSmith/IronBlock.cpp index 20c681f..842e1aa 100644 --- a/Source/BladeSmith/IronBlock.cpp +++ b/Source/BladeSmith/IronBlock.cpp @@ -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 VertexPositions; - GetStaticMeshVertexPositions(VertexPositions); + // // 获取顶点位置 (用于计算初始UV->WorldPos) + // TArray VertexPositions; + // GetStaticMeshVertexPositions(VertexPositions); // 创建位置纹理 - const int32 TextureSize = 256; // 纹理尺寸 - TArray 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 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(nullptr, TEXT("/Engine/BasicShapes/BasicShapeMaterial")); } - - if (BaseMaterial) + UMaterial* CalMaterial = LoadObject(nullptr, TEXT("/Game/Materials/M_HitCal")); // 示例路径 + if (!CalMaterial) + { + CalMaterial = LoadObject(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() diff --git a/Source/BladeSmith/IronBlock.h b/Source/BladeSmith/IronBlock.h index d7915e2..9f29a82 100644 --- a/Source/BladeSmith/IronBlock.h +++ b/Source/BladeSmith/IronBlock.h @@ -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();