Article
【重现】天涯明月刀中分形闪电的Unity实现
Updated a year ago
916
0
【重现】天涯明月刀中分形闪电的Unity实现

1. 闪电路径的制作
2. 网格的生成
3. 渲染
4. 后处理

路径

``````private void GetFractcalLightning(LightningSegment lightningSegment, int fractalTime, int maxFractalTime, float baseAttenuation, Vector2 offsetRange, Vector3 direction, Vector3 forward, Vector3 right, float branchChance = 0f)
{
if (!lightningSegment.isLeaf() || fractalTime > maxFractalTime)
return;
//制作Z型片段
float zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y);
float xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y);
Vector3 mid = lightningSegment.Middle() + xOffset * right + zOffset * forward;
lightningSegment.LeftChild = new LightningSegment(lightningSegment.start, mid);
lightningSegment.RightChild = new LightningSegment(mid, lightningSegment.end);
GetFractcalLightning(lightningSegment.LeftChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance);
GetFractcalLightning(lightningSegment.RightChild, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance);
if (Random.Range(0f, 1f) < branchChance)
{
//制作H形片段
zOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y);
xOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y);
float yOffset = Mathf.Exp(-baseAttenuation * fractalTime) * Random.Range(offsetRange.x, offsetRange.y);
Vector3 branchEnd = lightningSegment.Middle() + xOffset * right + zOffset * forward + yOffset * direction;
lightningSegment.Branch = new LightningSegment(mid, branchEnd);
GetFractcalLightning(lightningSegment.Branch, fractalTime + 1, maxFractalTime, baseAttenuation, offsetRange, direction, forward, right, branchChance);
}
}``````

网格

``````private void SegmentToMesh(LightningSegment lightningSegment, List<Vector3> vertices, List<int> triangle, List<Vector2> uv, Vector3 obPos, float radius, float attenuation, ref int idx)
{
if (lightningSegment.isLeaf())
{
Vector3 zMid = lightningSegment.Middle();
Vector3 zNormal = Vector3.Cross(zMid - obPos, lightningSegment.end - lightningSegment.start).normalized;
var finalR = radius * attenuation;
if (lightningSegment.Branch == null)
{
//Z型片段的Mesh生成
idx += 4;
}
}
else
{
SegmentToMesh(lightningSegment.LeftChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx);
SegmentToMesh(lightningSegment.RightChild, vertices, triangle, uv, obPos, radius, attenuation, ref idx);
if (lightningSegment.Branch != null)
SegmentToMesh(lightningSegment.Branch, vertices, triangle, uv, obPos, radius * attenuation, attenuation, ref idx);
}``````

渲染

``````……
lightningSegment.LeftChild = new LightningSegment(lightningSegment.start, mid);
lightningSegment.LeftChild.fractal = fractalTime + 1;
lightningSegment.LeftChild.uv = lightningSegment.uv - LightningCreator.arrayForUV[lightningSegment.LeftChild.fractal];
lightningSegment.RightChild = new LightningSegment(mid, lightningSegment.end);
lightningSegment.RightChild.fractal = fractalTime + 1;
lightningSegment.RightChild.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.RightChild.fractal];
……
Vector3 branchEnd = lightningSegment.Middle() + xOffset * right + zOffset * forward + yOffset * direction;
lightningSegment.Branch = new LightningSegment(mid, branchEnd);
lightningSegment.Branch.fractal = fractalTime + 1;
lightningSegment.Branch.uv = lightningSegment.uv + LightningCreator.arrayForUV[lightningSegment.Branch.fractal];``````

结语

Github：https://github.com/noobdawn/Fractal-Lightning-Unity

参考文献

1. https://blog.csdn.net/u012945598/article/details/18862091
2. http://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CJFQ&dbname=CJFD2011&filename=SJSJ201110067&v=MTE3Mjg3RGgxVDNxVHJXTTFGckNVUkxLZllPWnRGeW5nVnJ2Sk5pZllaTEc0SDlETnI0OURZNFI4ZVgxTHV4WVM=