fbb2baa854
design/04 仅保留加工硬化与晶粒演化,应力/淬火部分引用 design/05、design/06。design/05 涵盖温度区间、冷却速率、Sigmoid 硬度映射、相态系统、三阶段可视化(过程高辨识→冷却过渡→真实回火色)。 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
22 KiB
22 KiB
物理模拟-加工硬化与晶粒演化设计
项目: BladeSmith
文档类型: 技术设计(专题)
版本: 2.0
最后更新: 2026-08-11
状态: 整合自原 2026-01-22-物理模拟架构细节.md
本文档描述加工硬化与晶粒演化的技术实现。需求见 ../requirements/04-加工硬化与晶粒演化需求.md。总体架构见 00-锻造系统总体技术架构.md。
注意: 应力分布系统的详细技术内容见 06-应力累积系统设计.md。淬火退火相变系统的详细技术内容见 05-淬火退火相变系统设计.md。本文档仅简要引用这两部分。
1. 技术背景
加工硬化(Work Hardening)和晶粒演化是锻造过程中的核心物理现象:
- 加工硬化: 金属在塑性形变后变硬,屈服强度提高,机理是位错密度增加、晶格畸变。加热到再结晶温度(约600°C)后可软化。
- 晶粒演化: 温度和应变影响微观组织。细晶粒高强度高韧性(Hall-Petch关系),粗晶粒高温下更容易形变。
2. 数据结构
2.1 扩展体素结构
USTRUCT(BlueprintType)
struct FTemperatureVoxel
{
GENERATED_BODY()
// ===== 已有字段(保留) =====
UPROPERTY()
float Temperature; // 温度(°C)
UPROPERTY()
float PlasticityCoefficient; // 塑性系数(0-1)
UPROPERTY()
uint8 Flags; // 标志位(bit 0: 表面体素)
// ===== 新增字段 =====
// 平均应变率(记录形变活跃度)
UPROPERTY()
float AverageStrainRate; // 0-1范围,归一化的应变率
// 冷却速率(用于淬火判断,详见设计文档05)
UPROPERTY()
float CoolingRate; // °C/s
// 相态标记(详见设计文档05)
UPROPERTY()
EPhaseState PhaseState; // 奥氏体/马氏体/珠光体
// 淬火标记(是否经历过快速冷却,详见设计文档05)
UPROPERTY()
bool bHasBeenQuenched; // 淬火状态
FTemperatureVoxel()
: Temperature(20.0f)
, PlasticityCoefficient(0.0f)
, Flags(0)
, AverageStrainRate(0.0f)
, CoolingRate(0.0f)
, PhaseState(EPhaseState::Austenite) // 初始为奥氏体
, bHasBeenQuenched(false)
{}
};
2.2 相态枚举
/**
* 相态枚举
* 相变系统详细内容见设计文档05
*/
UENUM(BlueprintType)
enum class EPhaseState : uint8
{
Austenite UMETA(DisplayName = "奥氏体"), // 高温软相(>800°C)
Martensite UMETA(DisplayName = "马氏体"), // 淬火硬相
Pearlite UMETA(DisplayName = "珠光体"), // 缓冷软相
Bainite UMETA(DisplayName = "贝氏体"), // 中间相
Cracked UMETA(DisplayName = "开裂") // 永久缺陷
};
2.3 顶点属性结构
class ADynamicIronBlock
{
private:
// ===== 顶点自定义属性层 =====
// 初始位置(用于无漂移纹理采样)
TDynamicMeshVertexAttribute<FVector>* InitialPositions;
// 累积塑性应变(0-1,归一化)
TDynamicMeshVertexAttribute<float>* AccumulatedStrain;
// 当前硬度系数(0-1,0=最软,1=最硬)
TDynamicMeshVertexAttribute<float>* HardnessCoefficient;
// 打磨度(表面状态,0=生锈,1=光亮)
TDynamicMeshVertexAttribute<float>* PolishAmount;
// 晶粒尺寸(0-1,归一化,0=细晶粒,1=粗晶粒)
TDynamicMeshVertexAttribute<float>* GrainSize;
// 应力值(简化标量,0-1,0=无应力,1=高应力)
// 应力系统详细内容见设计文档06
TDynamicMeshVertexAttribute<float>* StressValue;
// 应力方向(可选,三维向量)
TDynamicMeshVertexAttribute<FVector>* StressDirection;
public:
// 初始化所有顶点属性
void InitializeVertexAttributes();
};
3. 加工硬化模型
3.1 物理原理
加工硬化(Work Hardening):
- 现象: 金属在塑性形变后变硬,屈服强度提高
- 机理: 位错密度增加,晶格畸变
- 可逆性: 加热到再结晶温度(约600°C)后软化
3.2 应变-硬度映射
/**
* 应变-硬度映射(简化经验公式)
* 基于真实钢的应力-应变曲线拟合
*/
float CalculateHardnessFromStrain(float AccumulatedStrain)
{
// 参数(可调)
const float InitialHardness = 0.2f; // 初始硬度
const float MaxHardness = 1.0f; // 最大硬度
const float SaturationStrain = 0.5f; // 饱和应变
// Ludwik方程简化版:σ = σ₀ + k·εⁿ
float HardnessIncrease = MaxHardness - InitialHardness;
float StrainEffect = FMath::Pow(AccumulatedStrain / SaturationStrain, 0.5f);
return InitialHardness + HardnessIncrease * FMath::Min(StrainEffect, 1.0f);
}
3.3 温度软化因子
高温下硬度降低(模拟动态回复)。
/**
* 温度软化因子
* 高温下硬度降低(模拟动态回复)
*/
float CalculateThermalSoftening(float Temperature, float Hardness)
{
// 再结晶温度(简化)
const float RecrystallizationTemp = 600.0f; // °C
if (Temperature < RecrystallizationTemp)
return Hardness; // 低温:无软化
// 高温:软化
float Overheating = Temperature - RecrystallizationTemp;
float SofteningFactor = FMath::Clamp(Overheating / 400.0f, 0.0f, 0.8f);
return Hardness * (1.0f - SofteningFactor);
}
3.4 锤击时更新硬度和应变
/**
* 锤击时更新硬度和应变
*/
void ADynamicIronBlock::OnHammerImpact(
FVector HitLocation,
float ImpactRadius,
float ImpactForce)
{
FVector LocalHitPos = GetTransform().InverseTransformPosition(HitLocation);
DynamicMesh->EditMesh([&](FDynamicMesh3& Mesh)
{
for (int32 VID : Mesh.VertexIndicesItr())
{
FVector VertexPos = Mesh.GetVertex(VID);
float Distance = FVector::Dist(VertexPos, LocalHitPos);
if (Distance < ImpactRadius)
{
// 1. 计算局部形变量(简化)
float DistanceRatio = Distance / ImpactRadius;
float LocalDeformation = FMath::Pow(1.0f - DistanceRatio, 2.0f);
float StrainIncrease = LocalDeformation * ImpactForce * 0.0001f;
// 2. 累积应变
float CurrentStrain = AccumulatedStrain->GetValue(VID);
float NewStrain = FMath::Min(1.0f, CurrentStrain + StrainIncrease);
AccumulatedStrain->SetValue(VID, NewStrain);
// 3. 从温度体素采样温度
FVector VoxelPos = VertexPos / VoxelSize;
float Temperature = SampleTemperatureFromVoxel(VoxelPos);
// 4. 计算硬度(应变硬化)
float StrainHardness = CalculateHardnessFromStrain(NewStrain);
// 5. 温度软化
float FinalHardness = CalculateThermalSoftening(Temperature, StrainHardness);
// 6. 更新硬度
HardnessCoefficient->SetValue(VID, FinalHardness);
// 7. 硬度影响形变阻力(可选:反馈到形变计算)
// 下一锤击时,高硬度区域形变小
}
}
});
}
4. 晶粒演化模型
4.1 物理原理
晶粒尺寸影响材料特性:
- 细晶粒: 高强度、高韧性(Hall-Petch关系)
- 粗晶粒: 高温下更容易形变
晶粒演化因素:
- 再结晶: 高温+应变 → 新晶粒形成
- 晶粒长大: 高温下晶粒合并
- 晶粒细化: 大应变+低温 → 细化
4.2 晶粒尺寸演化
/**
* 晶粒尺寸演化(简化标量模型)
*/
float EvolveGrainSize(
float CurrentGrainSize, // 当前晶粒尺寸(归一化0-1)
float Temperature, // 当前温度(°C)
float Strain, // 累积应变
float DeltaTime) // 时间步长
{
const float RecrystallizationTemp = 600.0f;
const float GrainGrowthTemp = 900.0f;
// 1. 再结晶:大应变+高温 → 晶粒细化
if (Temperature > RecrystallizationTemp && Strain > 0.3f)
{
float RecrystallizationRate = 0.1f; // 可调
return CurrentGrainSize * (1.0f - RecrystallizationRate * DeltaTime);
}
// 2. 晶粒长大:高温 → 晶粒粗化
if (Temperature > GrainGrowthTemp)
{
float GrowthRate = 0.05f * (Temperature - GrainGrowthTemp) / 300.0f;
return FMath::Min(1.0f, CurrentGrainSize * (1.0f + GrowthRate * DeltaTime));
}
// 3. 晶粒细化:大应变 → 晶粒细化
if (Strain > 0.5f)
{
float RefinementRate = 0.02f;
return FMath::Max(0.1f, CurrentGrainSize * (1.0f - RefinementRate * DeltaTime));
}
return CurrentGrainSize;
}
4.3 更新顶点晶粒尺寸
/**
* 更新顶点晶粒尺寸
*/
void ADynamicIronBlock::UpdateGrainStructure(float DeltaTime)
{
DynamicMesh->EditMesh([&](FDynamicMesh3& Mesh)
{
for (int32 VID : Mesh.VertexIndicesItr())
{
float CurrentGrainSize = GrainSize->GetValue(VID);
float Strain = AccumulatedStrain->GetValue(VID);
// 采样温度
FVector Pos = Mesh.GetVertex(VID);
float Temperature = SampleTemperatureFromVoxel(Pos);
// 演化晶粒尺寸
float NewGrainSize = EvolveGrainSize(CurrentGrainSize, Temperature, Strain, DeltaTime);
GrainSize->SetValue(VID, NewGrainSize);
}
});
}
4.4 大马士革花纹模拟
/**
* 初始化层状材料(用于大马士革钢)
*/
void InitializeLayeredMaterialStructure()
{
DynamicMesh->EditMesh([&](FDynamicMesh3& Mesh)
{
TDynamicMeshVertexAttribute<int32>* MaterialLayerID =
new TDynamicMeshVertexAttribute<int32>(&Mesh);
for (int32 VID : Mesh.VertexIndicesItr())
{
FVector Pos = Mesh.GetVertex(VID);
// 简单层状分布:沿Z轴
// 每层厚度2mm
int32 LayerID = (int32)FMath::Floor(Pos.Z / 2.0f) % 2;
MaterialLayerID->SetValue(VID, LayerID);
}
});
}
4.5 大马士革花纹材质HLSL
// 材质中基于MaterialLayerID采样不同颜色
float LayerID = MaterialLayerAttribute; // 从顶点属性读取
float3 HighCarbonColor = float3(0.15, 0.1, 0.08); // 深色层
float3 LowCarbonColor = float3(0.75, 0.7, 0.65); // 浅色层
float3 BaseColor = lerp(HighCarbonColor, LowCarbonColor, LayerID);
// 添加扭曲(基于形变)
float Distortion = length(AccumulatedStrain) * 5.0;
float3 WarpedPattern = WarpedNoise(BaseColor, Distortion);
FinalColor = BaseColor * (0.8 + WarpedPattern * 0.2);
5. GPU Compute Shader集成
5.1 Shader结构
MiceShaders/Source/MiceShaders/Private/
├── MetallurgyComputeShader.usf
├── MetallurgyComputeShader.h
└── MetallurgyComputeShader.cpp
5.2 Metallurgy Compute Shader HLSL
// MetallurgyComputeShader.usf
#define VOXEL_SIZE 50
#define THREAD_COUNT 32
// 输入/输出缓冲区
RWStructuredBuffer<float4> TemperatureBufferA; // 温度 + 塑性系数
RWStructuredBuffer<float4> TemperatureBufferB; // Ping-Pong
RWStructuredBuffer<float4> MetallurgyBuffer; // 应变率 + 冷却速率 + 相态 + 淬火标记
// 参数
cbuffer MetallurgyParams
{
float DeltaTime;
float3 VoxelWorldMin;
float VoxelSize;
float3 Padding;
};
/**
* 计算 Metallurgy Shader 主函数
*/
[numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
void MetallurgyComputeShader(uint3 ThreadId : SV_DispatchThreadID)
{
uint VoxelIndex = ThreadId.x + ThreadId.y * VoxelSize;
// 读取温度
float Temperature = TemperatureBufferA[VoxelIndex].r;
float Plasticity = TemperatureBufferA[VoxelIndex].g;
// 读取应变率
float StrainRate = MetallurgyBuffer[VoxelIndex].r;
// 1. 应变率衰减(模拟时效)
StrainRate *= 0.99;
// 2. 计算冷却速率(相变判断基础,详见设计文档05)
float3 WorldPos = VoxelToWorldPosition(VoxelIndex);
float SurfaceFactor = IsSurfaceVoxel(WorldPos) ? 1.0 : 0.1;
float CoolingRate = SurfaceFactor * (Temperature - 20.0) * 0.1;
// 3. 相态判断(详细相变逻辑见设计文档05)
uint PhaseState = 0; // 奥氏体
if (CoolingRate > 100.0 && Temperature > 800.0)
{
PhaseState = 1; // 马氏体(淬火)
}
else if (Temperature < 600.0)
{
PhaseState = 2; // 珠光体(缓冷)
}
// 写回
MetallurgyBuffer[VoxelIndex] = float4(StrainRate, CoolingRate, PhaseState, 0.0);
}
/**
* 辅助函数:体素索引转世界坐标
*/
float3 VoxelToWorldPosition(uint Index)
{
uint X = Index % VoxelSize;
uint Y = (Index / VoxelSize) % VoxelSize;
uint Z = Index / (VoxelSize * VoxelSize);
return VoxelWorldMin + float3(X, Y, Z) * VoxelSize;
}
/**
* 辅助函数:判断是否为表面体素
*/
bool IsSurfaceVoxel(float3 WorldPos)
{
// 简化:边界体素为表面
// 实际应使用法线判断
return false;
}
5.3 C++ Shader封装
// MetallurgyComputeShader.h
class FMetallurgyComputeShader
{
public:
static void Dispatch(
FRHICommandListImmediate& RHICmdList,
FStructuredBufferRHIRef TemperatureBufferA,
FStructuredBufferRHIRef TemperatureBufferB,
FStructuredBufferRHIRef MetallurgyBuffer,
float DeltaTime,
FIntVector VoxelResolution);
};
5.4 C++ Shader调用
// MetallurgyComputeShader.cpp
void FMetallurgyComputeShader::Dispatch(
FRHICommandListImmediate& RHICmdList,
FStructuredBufferRHIRef TemperatureBufferA,
FStructuredBufferRHIRef TemperatureBufferB,
FStructuredBufferRHIRef MetallurgyBuffer,
float DeltaTime,
FIntVector VoxelResolution)
{
// 设置Shader
TShaderMapRef<FMetallurgyComputeShader> ComputeShader(GetGlobalShaderMap(GMaxRHIFeatureLevel));
// 设置参数
RHICmdList.SetComputeShader(ComputeShader.GetComputeShader());
ComputeShader->SetParameters(RHICmdList, TemperatureBufferA, TemperatureBufferB,
MetallurgyBuffer, DeltaTime, VoxelMin, VoxelSize);
// Dispatch
int32 ThreadGroupCount = (VoxelResolution.X + 31) / 32;
RHICmdList.DispatchComputeShader(ThreadGroupCount, ThreadGroupCount, 1);
}
5.5 异步Dispatch模式
ENQUEUE_RENDER_COMMAND(FMetallurgyComputeDispatch)(
[this, DeltaTime](FRHICommandListImmediate& RHICmdList)
{
FMetallurgyComputeShader::Dispatch(
RHICmdList,
TemperatureBufferA,
TemperatureBufferB,
MetallurgyBuffer,
DeltaTime,
TemperatureResolution
);
bMetallurgyComputeComplete = true;
}
);
// CPU 继续其他工作,不等待GPU
6. 材质可视化
6.1 硬度可视化
// 材质中:基于硬度调整颜色
float Hardness = SampleHardnessFromVoxel(WorldPos);
float3 SoftColor = float3(0.6, 0.5, 0.4); // 软:棕色
float3 HardColor = float3(0.8, 0.8, 0.85); // 硬:银白色
float3 HardnessColor = lerp(SoftColor, HardColor, Hardness);
6.2 应力可视化
注意: 应力分布系统的详细可视化见 06-应力累积系统设计.md。此处为简要引用。
// 顶点颜色.A通道存储应力
float Stress = VertexColor.a;
float3 LowStressColor = float3(0.3, 0.5, 0.7); // 低应力:蓝色
float3 HighStressColor = float3(1.0, 0.3, 0.1); // 高应力:红色
float3 StressColor = lerp(LowStressColor, HighStressColor, Stress);
// 混合到基础颜色
BaseColor = lerp(BaseColor, StressColor, Stress * 0.5);
6.3 相态可视化
注意: 淬火相变系统的详细可视化见 05-淬火退火相变系统设计.md。此处为简要引用。
// 从体素采样相态
float PhaseState = SamplePhaseStateFromVoxel(WorldPos);
float3 AusteniteColor = float3(1.0, 0.8, 0.6); // 奥氏体:浅橙色
float3 MartensiteColor = float3(0.9, 0.85, 0.8); // 马氏体:银白色
float3 PearliteColor = float3(0.7, 0.6, 0.5); // 珠光体:深灰色
float3 PhaseColor;
if (PhaseState < 0.5)
PhaseColor = AusteniteColor;
else if (PhaseState < 1.5)
PhaseColor = MartensiteColor;
else
PhaseColor = PearliteColor;
// 根据温度过渡
float Temp = SampleTemperatureFromVoxel(WorldPos);
float MixFactor = smoothstep(600.0, 800.0, Temp);
BaseColor = lerp(PhaseColor, AusteniteColor, MixFactor);
7. 性能优化
7.1 GPU优化策略
// 1. 使用共享内存(GroupShared)
groupshared float SharedTemperature[THREAD_COUNT * THREAD_COUNT];
// 2. 波前优化(Wave Intrinsics)
uint WaveSize = GetWaveSize();
float WaveSum = WaveActiveSum(StrainRate);
// 3. 避免分支 divergence
if (CoolingRate > 100.0) // 差:条件跳转
PhaseState = 1.0;
PhaseState = step(100.0, CoolingRate); // 好:无分支
7.2 CPU-GPU异步
// 异步Dispatch
ENQUEUE_RENDER_COMMAND(FMetallurgyComputeDispatch)(
[this, DeltaTime](FRHICommandListImmediate& RHICmdList)
{
FMetallurgyComputeShader::Dispatch(
RHICmdList,
TemperatureBufferA,
TemperatureBufferB,
MetallurgyBuffer,
DeltaTime,
TemperatureResolution
);
// 标记完成
bMetallurgyComputeComplete = true;
}
);
// CPU继续其他工作,不用等待GPU
7.3 LOD策略
// 根据摄像机距离调整计算频率
float DistanceToCamera = FVector::Dist(GetActorLocation(), CameraLocation);
int32 ComputeFrequency;
if (DistanceToCamera < 200.0f)
ComputeFrequency = 1; // 每帧计算
else if (DistanceToCamera < 500.0f)
ComputeFrequency = 2; // 每2帧计算
else
ComputeFrequency = 5; // 每5帧计算
static int32 FrameCounter = 0;
if (++FrameCounter % ComputeFrequency == 0)
{
DispatchMetallurgyComputeShader();
}
8. 参数配置示例
8.1 碳钢(C105)
// 加工硬化参数
InitialHardness = 0.25f;
SaturationStrain = 0.6f;
WorkHardeningExponent = 0.55f;
// 相变参数(详见设计文档05)
AustenitizingTemp = 800.0f;
QuenchingCriticalRate = 120.0f;
MartensiteHardness = 0.95f;
// 晶粒参数
InitialGrainSize = 0.5f;
RecrystallizationTemp = 650.0f;
8.2 高碳钢(C150)
// 更容易硬化
InitialHardness = 0.35f;
SaturationStrain = 0.4f;
// 淬火更敏感(详见设计文档05)
QuenchingCriticalRate = 80.0f; // 更容易淬火
MartensiteHardness = 1.0f; // 更硬
8.3 低碳钢(C20)
// 难硬化
InitialHardness = 0.15f;
SaturationStrain = 0.8f;
// 难淬火(详见设计文档05)
QuenchingCriticalRate = 200.0f; // 很难淬火
MartensiteHardness = 0.7f;
9. 调试工具
9.1 体素数据可视化
void ADynamicIronBlock::DebugDrawVoxelData()
{
for (int32 Z = 0; Z < TemperatureResolution.Z; ++Z)
{
for (int32 Y = 0; Y < TemperatureResolution.Y; ++Y)
{
for (int32 X = 0; X < TemperatureResolution.X; ++X)
{
FIntVector Coord(X, Y, Z);
int32 Index = GetTemperatureIndex(Coord);
const FTemperatureVoxel& Voxel = TemperatureGrid[Index];
// 只绘制表面体素
if (!(Voxel.Flags & VOXEL_FLAG_SURFACE))
continue;
FVector WorldPos = VoxelCoordToWorldPos(Coord);
// 颜色:温度
FLinearColor Color = FLinearColor(
FMath::Clamp(Voxel.Temperature / 1200.0f, 0.0f, 1.0f),
0.0f,
1.0f - FMath::Clamp(Voxel.Temperature / 1200.0f, 0.0f, 1.0f)
);
DrawDebugPoint(GetWorld(), WorldPos, 3.0f, Color.ToFColor(), false, 0.1f);
}
}
}
}
9.2 应力热图
注意: 应力热图的详细实现见 06-应力累积系统设计.md。此处为简要引用。
void ADynamicIronBlock::DebugDrawStressHeatmap()
{
if (!DynamicMesh->HasMesh())
return;
for (int32 VID : DynamicMesh->VertexIndicesItr())
{
if (VID % 50 != 0) // 稀疏采样
continue;
float Stress = StressValue->GetValue(VID);
FVector WorldPos = GetActorTransform().TransformPosition(DynamicMesh->GetVertex(VID));
// 蓝色(低应力)→ 红色(高应力)
FColor HeatColor = FLinearColor::LerpUsingHSV(
FColor::Blue,
FColor::Red,
Stress
).ToFColor();
DrawDebugPoint(GetWorld(), WorldPos, 5.0f, HeatColor, false, 5.0f);
}
}
10. 已知限制与未来改进
10.1 当前限制
- 简化模型: 所有物理模型均为经验公式,非严格物理计算
- 无热-力耦合: 温度场和应力场独立计算,未考虑形变生热
- 无磁-电效应: 忽略了电磁场对相变的影响
- 各向同性: 假设材料各向同性,真实钢有晶粒取向
- 晶粒模型极度简化: 真实晶粒有复杂3D形状与取向,当前用标量GrainSize
10.2 适用场景
游戏娱乐级,足够真实感但非科研级精度。
11. 引用
- 对应需求: ../requirements/04-加工硬化与晶粒演化需求.md
- 总体架构: 00-锻造系统总体技术架构.md
- 原始设计文档(归档): ../_archive/plans/2026-01-22-物理模拟架构细节.md
- 相关专题(淬火系统): 05-淬火退火相变系统设计.md
- 相关专题(应力系统): 06-应力累积系统设计.md