调试计算形变的shader,执行了,但是初始贴图数据就不对。
This commit is contained in:
Binary file not shown.
@@ -53,6 +53,7 @@ void MainCompute( // 注意: 建议使用 MainCompute,如果 C++ 注册的是
|
||||
{
|
||||
// 虽然我们调度时已经只调度了需要的区域,但为了安全起见,保留检查。
|
||||
// 理论上,如果 C++ 端调度正确,这个检查应该很少触发。
|
||||
OutputTexture[PixelCoord] = float4(100,100,100,100);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 问题的核心
|
||||
|
||||
@@ -54,7 +54,7 @@ protected:
|
||||
void GetStaticMeshVertexPositions(TArray<FVector3f>& OutPositions);
|
||||
|
||||
/** 设置动态材质实例和参数 */
|
||||
void SetupDeformationMaterial();
|
||||
void SetupDeformationMaterial(UTexture2D* OrigTex);
|
||||
|
||||
/** 安全地获取 RenderTarget 的 RHI 资源 */
|
||||
FTextureRHIRef GetRenderTargetRHI(UTextureRenderTarget2D* RT);
|
||||
|
||||
Reference in New Issue
Block a user