diff --git a/Content/Materials/M_Iron.uasset b/Content/Materials/M_Iron.uasset index 07ff7ed..31b9dde 100644 Binary files a/Content/Materials/M_Iron.uasset and b/Content/Materials/M_Iron.uasset differ diff --git a/Plugins/MiceShaders/Shaders/Private/DeformationCS.usf b/Plugins/MiceShaders/Shaders/Private/DeformationCS.usf index 87e1e58..864226b 100644 --- a/Plugins/MiceShaders/Shaders/Private/DeformationCS.usf +++ b/Plugins/MiceShaders/Shaders/Private/DeformationCS.usf @@ -53,6 +53,7 @@ void MainCompute( // 注意: 建议使用 MainCompute,如果 C++ 注册的是 { // 虽然我们调度时已经只调度了需要的区域,但为了安全起见,保留检查。 // 理论上,如果 C++ 端调度正确,这个检查应该很少触发。 + OutputTexture[PixelCoord] = float4(100,100,100,100); return; } diff --git a/Shaders/DeformationCS.usf b/Shaders/DeformationCS.usf deleted file mode 100644 index 3f6dcab..0000000 --- a/Shaders/DeformationCS.usf +++ /dev/null @@ -1,90 +0,0 @@ -// DeformationCS.usf - -#include "/Engine/Public/Platform.ush" - -// ----------------------------------------------------------------------------- -// 1. 输入输出定义 -// ----------------------------------------------------------------------------- -// 必须与 C++ 的 SHADER_PARAMETER_RDG_TEXTURE_SRV 匹配 -Texture2D InputTexture; -// 必须与 C++ 的 SHADER_PARAMETER_RDG_TEXTURE_UAV 匹配 -RWTexture2D OutputTexture; - -// ----------------------------------------------------------------------------- -// 2. 参数缓冲区 (必须与 C++ FParameters 结构体严格匹配) -// ----------------------------------------------------------------------------- -cbuffer Parameters -{ - float3 ImpactPoint; - float ImpactForce; - float3 ImpactNormal; - float DeformationRadius; - float Plasticity; - int3 TextureSize; - - // 修正后的参数:对应 C++ 的 FIntVector4 UpdateRegionParam - // 分量顺序: (Min.X, Min.Y, Max.X, Max.Y) - int4 UpdateRegionParam; -}; - -// ----------------------------------------------------------------------------- -// 3. 线程组大小和入口点 -// ----------------------------------------------------------------------------- -#define THREADGROUP_SIZE_X 8 -#define THREADGROUP_SIZE_Y 8 -[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)] -void MainCompute( // 注意: 建议使用 MainCompute,如果 C++ 注册的是 MainCompute - uint3 GroupID : SV_GroupID, - uint3 GroupThreadID : SV_GroupThreadID, - uint3 DispatchThreadID : SV_DispatchThreadID // 全局线程 ID -) -{ - // ------------------------------------------------------------------------- - // 4. 坐标计算与边界检查 - // ------------------------------------------------------------------------- - - // DispatchThreadID 从 0 开始,代表在调度区域内的偏移量。 - // 我们将其加上 UpdateRegionParam.xy (Min.X, Min.Y) 得到全局像素坐标。 - int2 PixelCoord = DispatchThreadID.xy + int2(UpdateRegionParam.x, UpdateRegionParam.y); - - // 边界检查:检查是否超出 UpdateRegionParam.zw (Max.X, Max.Y) - if (PixelCoord.x < UpdateRegionParam.x || PixelCoord.x >= UpdateRegionParam.z || - PixelCoord.y < UpdateRegionParam.y || PixelCoord.y >= UpdateRegionParam.w) - { - // 虽然我们调度时已经只调度了需要的区域,但为了安全起见,保留检查。 - // 理论上,如果 C++ 端调度正确,这个检查应该很少触发。 - return; - } - - // ------------------------------------------------------------------------- - // 5. 变形计算逻辑 (与之前相同) - // ------------------------------------------------------------------------- - - // 从输入纹理读取位置 - // Load 需要 int3,第三个分量 (MipLevel) 设为 0 - float4 OriginalPos = InputTexture.Load(int3(PixelCoord, 0)); - - // 计算到碰撞点的距离 - float dist = distance(OriginalPos.xyz, ImpactPoint); - - // 在变形半径内处理 - if (dist < DeformationRadius) - { - // 计算变形衰减 (高斯衰减) - float falloff = exp(-(dist * dist) / (2.0 * DeformationRadius * DeformationRadius)); - - // 计算变形量 (考虑法线方向) - float3 deformation = ImpactNormal * ImpactForce * falloff * 0.01; - - // 应用塑性变形 - float3 newPos = OriginalPos.xyz + deformation * Plasticity; - - // 写入新位置 - OutputTexture[PixelCoord] = float4(newPos, OriginalPos.w); - } - else - { - // 保持原位置 - OutputTexture[PixelCoord] = OriginalPos; - } -} \ No newline at end of file diff --git a/Source/BladeSmith/IronBlock.cpp b/Source/BladeSmith/IronBlock.cpp index 7c9f76c..20c681f 100644 --- a/Source/BladeSmith/IronBlock.cpp +++ b/Source/BladeSmith/IronBlock.cpp @@ -153,7 +153,7 @@ void AIronBlock::InitializePositionTexture() LocalBounds.Min.Z // 假设初始是一个平面 ); - InitialData[Index] = FLinearColor(LocalPos.X, LocalPos.Y, LocalPos.Z, 1.0f); + InitialData[Index] = FLinearColor(LocalPos.X * 1000, LocalPos.Y * 1000, LocalPos.Z * 1000, 1.0f); } } @@ -197,7 +197,7 @@ void AIronBlock::InitializePositionTexture() } // 设置变形材质 - SetupDeformationMaterial(); + SetupDeformationMaterial(TempTexture); UE_LOG(LogTemp, Log, TEXT("Position textures initialized")); } @@ -229,7 +229,7 @@ void AIronBlock::CalculateLocalBounds() } } -void AIronBlock::SetupDeformationMaterial() +void AIronBlock::SetupDeformationMaterial(UTexture2D* OrigTex) { // 创建动态材质实例 if (StaticMeshComp) @@ -250,7 +250,8 @@ void AIronBlock::SetupDeformationMaterial() if (DynMaterial) { // 初始时读取 RT0 - DynMaterial->SetTextureParameterValue(TEXT("PositionTexture"), PositionRenderTarget0); + 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); @@ -275,13 +276,14 @@ void AIronBlock::OnHammerHit(const FHitResult& HitResult) // 默认冲击力 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(); @@ -311,6 +313,8 @@ 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() @@ -343,9 +347,24 @@ void AIronBlock::ExecuteDeformationCS() (CurrentImpactPoint.X - LocalBounds.Min.X) / LocalBounds.GetSize().X, (CurrentImpactPoint.Y - LocalBounds.Min.Y) / LocalBounds.GetSize().Y ); + UE_LOG(LogTemp,Display,TEXT("[AIronBlock::ExecuteDeformationCS]LocalBounds:%s") + ,*LocalBounds.ToString()); + // 假设 LocalBounds 仍然是未缩放的原始包围盒 + // 获得 Actor 的缩放 + FVector ComponentScale = StaticMeshComp->GetComponentScale(); + + // 1. 计算缩放后包围盒的最大延伸 (在 X/Y 平面上) + // 假设您的形变发生在 XY 平面 + float MaxLocalExtentX = LocalBounds.GetExtent().X * ComponentScale.X; + float MaxLocalExtentY = LocalBounds.GetExtent().Y * ComponentScale.Y; + float MaxScaledExtent = FMath::Max(MaxLocalExtentX, MaxLocalExtentY); + + // 2. 使用这个缩放后的最大延伸进行比例计算 + // 这里的 CurrentDeformationRadius 应该是一个世界空间的值。 + const float RadiusRatio = CurrentDeformationRadius / MaxScaledExtent; // 计算更新区域 (只更新受影响部分) - const float RadiusRatio = CurrentDeformationRadius / LocalBounds.GetExtent().GetMax(); + //const float RadiusRatio = CurrentDeformationRadius / LocalBounds.GetExtent().GetMax(); FIntRect UpdateRegion; UpdateRegion.Min.X = FMath::Clamp(FMath::FloorToInt((ImpactUV.X - RadiusRatio) * TexSize), 0, TexSize - 1); UpdateRegion.Min.Y = FMath::Clamp(FMath::FloorToInt((ImpactUV.Y - RadiusRatio) * TexSize), 0, TexSize - 1); @@ -356,6 +375,12 @@ void AIronBlock::ExecuteDeformationCS() if (UpdateRegion.Min.X >= UpdateRegion.Max.X) UpdateRegion.Max.X = UpdateRegion.Min.X + 1; if (UpdateRegion.Min.Y >= UpdateRegion.Max.Y) UpdateRegion.Max.Y = UpdateRegion.Min.Y + 1; + // 临时代码,先更新全部区域 + UpdateRegion.Min.X = 0; + UpdateRegion.Min.Y = 0; + UpdateRegion.Max.X = TexSize; + UpdateRegion.Max.Y = TexSize; + // --- 关键修改:使用 RDG --- ENQUEUE_RENDER_COMMAND(ExecuteDeformationCS_RDG)( [ @@ -394,6 +419,9 @@ void AIronBlock::ExecuteDeformationCS() Params->Plasticity = CurrentPlasticity; Params->UpdateRegionParam = FIntVector4(UpdateRegion.Min.X, UpdateRegion.Min.Y, UpdateRegion.Max.X, UpdateRegion.Max.Y); Params->TextureSize = FIntVector(TexSize, TexSize, 1); + UE_LOG(LogTemp,Display,TEXT("[AIronBlock::ExecuteDeformationCS]ImpactForce:%f, ImpactPoint:%s,ImpactNormal:%s,DeformationRadius:%f,Plasticity:%f,UpdateRegion:%s") + ,Params->ImpactForce,*Params->ImpactPoint.ToString(),*Params->ImpactNormal.ToString(),Params->DeformationRadius,Params->Plasticity,*Params->UpdateRegionParam.ToString()); + // 5. ✨ 魔法发生的地方:RDG 为我们创建 SRV 和 UAV // 这就是解决你 nullptr 问题的核心 diff --git a/Source/BladeSmith/IronBlock.h b/Source/BladeSmith/IronBlock.h index efd1c7c..d7915e2 100644 --- a/Source/BladeSmith/IronBlock.h +++ b/Source/BladeSmith/IronBlock.h @@ -54,7 +54,7 @@ protected: void GetStaticMeshVertexPositions(TArray& OutPositions); /** 设置动态材质实例和参数 */ - void SetupDeformationMaterial(); + void SetupDeformationMaterial(UTexture2D* OrigTex); /** 安全地获取 RenderTarget 的 RHI 资源 */ FTextureRHIRef GetRenderTargetRHI(UTextureRenderTarget2D* RT);