调试计算形变的shader,执行了,但是初始贴图数据就不对。

This commit is contained in:
zhangqing
2025-11-12 19:16:34 +08:00
parent b027ec6487
commit c58581180b
5 changed files with 37 additions and 98 deletions
Binary file not shown.
@@ -53,6 +53,7 @@ void MainCompute( // 注意: 建议使用 MainCompute,如果 C++ 注册的是
{
// 虽然我们调度时已经只调度了需要的区域,但为了安全起见,保留检查。
// 理论上,如果 C++ 端调度正确,这个检查应该很少触发。
OutputTexture[PixelCoord] = float4(100,100,100,100);
return;
}
-90
View File
@@ -1,90 +0,0 @@
// DeformationCS.usf
#include "/Engine/Public/Platform.ush"
// -----------------------------------------------------------------------------
// 1. 输入输出定义
// -----------------------------------------------------------------------------
// 必须与 C++ 的 SHADER_PARAMETER_RDG_TEXTURE_SRV 匹配
Texture2D<float4> InputTexture;
// 必须与 C++ 的 SHADER_PARAMETER_RDG_TEXTURE_UAV 匹配
RWTexture2D<float4> 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;
}
}
+34 -6
View File
@@ -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);
@@ -281,7 +282,8 @@ void AIronBlock::OnHammerHit(const FHitResult& HitResult)
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 问题的核心
+1 -1
View File
@@ -54,7 +54,7 @@ protected:
void GetStaticMeshVertexPositions(TArray<FVector3f>& OutPositions);
/** 设置动态材质实例和参数 */
void SetupDeformationMaterial();
void SetupDeformationMaterial(UTexture2D* OrigTex);
/** 安全地获取 RenderTarget 的 RHI 资源 */
FTextureRHIRef GetRenderTargetRHI(UTextureRenderTarget2D* RT);