// 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; } }