2023-06-29 11:55:02 +08:00

53 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 前言
思路是使用平面方程来判断模型裁切之后在另一面使用UnLit的自发光材质显示剖面。但Ue4的BlendingMaterialAttributes不能指定UnLit作为ShaderModel。所以可以使用我之前开发的多Pass插件搞定。
## 外部普通表面材质
使用平面方程来做一个Mask即可。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/OutsideSurfaceMaterial.png)
## 内部剖面材质
坡面材质需要使用UnLit材质模型这样就不会有阴影与法线的干扰了。但Unlit不能翻转法线所以需要再勾选**双面渲染**选项。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/InsideCrossSectionMaterial.png)
## 使用方法说明
https://zhuanlan.zhihu.com/p/69139579
1. 使用上面链接介绍的代码新建一个蓝图类并且挂载UStrokeStaticMeshComponent。
2. 赋予UStrokeStaticMeshComponent所需剖切的模型以及上文制作好的外部表面材质。
3. 赋予SecondPassMaterial内部剖面材质并勾选UStrokeStaticMeshComponent的NeedSecondPass变量。
4. 将蓝图类拖到关卡中并且设置2个材质的PlaneNormal与PlanePoint。PlanePoint为世界坐标PlaneNormal需要归一化。
## 最终效果
锯齿是因为垃圾笔记本散热差,把效果开低的关系。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/CrossSectionMaterial.png)
## 错误的尝试
之前还尝试WorldPositionOffset的思路来做不过后来发现没有实用性。因为剖面的大小与形状是不确定的用投射的方式来平移内部可见顶点会造成多余的顶点平移到平面外的问题。所以只适合拿来做规整模型的剖切效果。
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/SectionCuttingPlaneShow1.png)
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/SectionCuttingPlaneShow3.png)
错误结果:
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/SectionCuttingPlaneShow2.png)
实现节点如下:
![](https://cdn.jsdelivr.net/gh/blueroseslol/ImageBag@latest/ImageBag/Images/CrossSectionFailedd.PNG)
CustomNode代码
```
// Input PlaneNormal
// Input PlanePoint
// Input WorldPosition
float NormalPower2= pow(PlaneNormal.x,2) + pow(PlaneNormal.y,2) + pow(PlaneNormal.z,2);
float D=dot(PlaneNormal.xyz,PlanePoint.xyz)*-1;
float posX= ((pow(PlaneNormal.y,2) + pow(PlaneNormal.z,2))*WorldPosition.x-PlaneNormal.x*(PlaneNormal.y*WorldPosition.y+PlaneNormal.z*WorldPosition.z+D))/NormalPower2;
float posY=((pow(PlaneNormal.x,2) + pow(PlaneNormal.z,2))*WorldPosition.y-PlaneNormal.y*(PlaneNormal.x*WorldPosition.x+PlaneNormal.z*WorldPosition.z+D))/NormalPower2;
float posZ=((pow(PlaneNormal.x,2) + pow(PlaneNormal.y,2))*WorldPosition.z-PlaneNormal.z*(PlaneNormal.x*WorldPosition.x+PlaneNormal.y*WorldPosition.y+D))/NormalPower2;
return float3(posX,posY,posZ)-WorldPosition.xyz;
```