From c58581180b09d52eb5af36d264a695b9816758f1 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Wed, 12 Nov 2025 19:16:34 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E8=AF=95=E8=AE=A1=E7=AE=97=E5=BD=A2?= =?UTF-8?q?=E5=8F=98=E7=9A=84shader=EF=BC=8C=E6=89=A7=E8=A1=8C=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E4=BD=86=E6=98=AF=E5=88=9D=E5=A7=8B=E8=B4=B4=E5=9B=BE?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B0=B1=E4=B8=8D=E5=AF=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Content/Materials/M_Iron.uasset | Bin 15059 -> 16302 bytes .../Shaders/Private/DeformationCS.usf | 1 + Shaders/DeformationCS.usf | 90 ------------------ Source/BladeSmith/IronBlock.cpp | 42 ++++++-- Source/BladeSmith/IronBlock.h | 2 +- 5 files changed, 37 insertions(+), 98 deletions(-) delete mode 100644 Shaders/DeformationCS.usf diff --git a/Content/Materials/M_Iron.uasset b/Content/Materials/M_Iron.uasset index 07ff7edfad647cfa469251ef678a554ee4c6b032..31b9dde5170d9f8b10777f100f3efb34b6dbe254 100644 GIT binary patch delta 7279 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 xnH+~24hEPQa~2h1ytb$c?G!($lh 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 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);