Skip to content

仅边框立方体

方案一 物理建模

该方案在需要缩放时会表现出劣势:当XYZ缩放不一致时,线框的宽度可能会出现走形。

整体思路:创建仅边框的立方体,并导入Unity,修改碰撞体为Box,调整材质。

模型

  1. 使用Blender创建基础的立方体,进入编辑模式,全选并Delet,选择“仅删除面”。

image-20251227123508658

  1. 添加蒙皮修改器

image-20251227123548213

  1. 编辑模式Ctrl+A调整边框的粗细,直到效果合适。

image-20251227124356197

  1. 导出为fbx模型并导入Unity。

方案二 手写Shader

该方案在缩放不规则时仍然变现不佳,因立方体六个面默认共用UV。

该问题是可解的:使用带World Space UV的Shader。

整体思路:在 Shader 内部画边框。在计算边框宽度时,除以物体的缩放倍数

$$\text{Distance} = (\text{物体半尺寸} \times \text{缩放}) - (|\text{对象空间坐标}| \times \text{缩放})$$

📎 点击此处下载示例文件

以下为Shader Graph的详细步骤:

一、输入属性

材质应包含以下三个可控的输入属性:

  • Border Width :发光线框的宽度。
  • Emission Color:发光线框的颜色。
  • Base Alpha:基础透明度,控制非线框部分的透明度,默认为0。

二、获得绝对物理坐标

这一步得到的结果是经过缩放后,上、正和右(或和它们相对的面)距离中心的距离,也就是半径。 因为矩形的对称性,只需要三个分量就可以表示六个面的情况。

  1. 创建一个Position节点,Space选择Object

  2. 创建一个Absolute节点,将Position的输出连进来,得到坐标的绝对值。

  3. 创建一个Object节点和一个Multipty节点,将坐标的绝对值(2.)和ObjectScale相乘。

易混淆点

在Shader中,Position节点不是指物体的坐标,而是当前正在渲染的像素点的坐标,也就是说它是一个不断变化的值。这使得它和下一步的结果是全然不同的含义。

Object节点中的Position属性才是物体的坐标。

三、获得立方体边界

这一步得到的结果是缩放*0.5的向量,用于后续判断。

  1. 创建一个Multipty节点。
  2. 将第二步创建的Object节点的Scale属性和0.5相乘。

四、计算距离

这一步得到的是三个值为1或0的整数,代表当前像素点在三个方向上是否接近边界。

边界判定

当一个点与边界的距离小于指定的Borden Width时,我们认为它是靠近边界的,也就是说它在边框线上。

  1. 创建一个Subtract节点,用第三步得到的立方体边界坐标减去第二步得到的当前像素坐标,计算出每个点和x、y、z的边界的距离。
  2. 创建一个Split节点,将(1.)得到的、点和三个边界的距离分解成三个分量。
  3. 创建三个Step节点,将(2.)三个距离分量分别和EdgeBorder Witdh)进行对比。
  4. 由于Step的逻辑是输入小于阈值输出 0,否则输出 1;而实际我们需要像素和边界的距离小于Border Witdh时显示,和Step的逻辑相反,因此需要对(3.)三个结果分别应用One Minus

五、逻辑判断

观察立方体可知,对于立方体内的任意一点,假如它在三个方向上与边界的距离已知,则有:

如果三个距离分量中有且仅有一个分量是靠近边界的,则认为它在一个面附近; 如果三个距离分量中有两个是靠近边界的,则认为它在一条边附近; 如果三个距离分量均靠近边界,则认为它在一个顶点附近。

这一步通过对比当前点在三个方向上的情况,判定当前点是否为透明。

在上一步中我们得到了三个1或0的值,只要其中有两个或以上的1,则这个点位于边框上。

  1. 创建两个Add节点,将三个分量相加。
  2. 创建一个Step节点,将三个分量的和与Edge进行对比。这里的Edge可以是$1-2$之间的任意浮点数。
  3. 创建一个Multipty节点,将上一步的结果和Emission Color相乘,得到颜色,连入输出节点的Color
  4. 将(2.)的输出连到输出节点的Alpha节点

基于方案二的单个对象泛光效果

在不需要全局泛光的情况下,可以对方案二的Shader进行修改以实现单个对象泛光。