povray[1] = 天空

在「第一幅画」中,绘制了一个黄颜色的球体。现在将这个球体的颜色换成天蓝色:

sphere {
  <0, 1, 2>, 2
  texture {
    pigment { color rgb<0.1, 0.25, 0.75> }
  }
}

于是,它就变成了天蓝色的球体:

sky-blue-sphere

由于光源位于球体的右上方,所以球体的左下侧表面出现了阴影。然而现实中,天空是没有阴影的。要消除球体上的阴影,需要将其表面设置为不散射来自光源的光:

sphere {
  <0, 1, 2>, 2
  texture {
    pigment {color rgb <0.1, 0.25, 0.75>}
    finish {
      diffuse 0
    }
  }
}

结果这个球体失去了三维感,并且变得很暗:

sky-blue-sphere-no-diffuse

要让这个球体在保持现在的状态下恢复它的三维感,需要建立参照物,譬如一张漫无边际的穿过球体的平面:

plane {
  y, 0
  texture {
    pigment {
      checker color Red, color Blue
    }
  }
}

这个平面垂直于 y 方向并穿过原点:

sky-blue-sphere-no-diffuse-with-land

恢复这个球体三维感的不止是这个平面,球体在这个平面上的影子也起了很重要的作用。

现在,再来考虑怎样让这个球体变的亮一些。由于它不散射来自光源的光,那让它变亮,就只有增强环境光。举个例子,房间外面阳光明媚,但是房间内的物体却没有散射阳光。我们之所以能看见这些物体,是因为环境光的作用。下面的代码为球体增加了很强的环境光:

sphere {
  <0, 1, 2>, 2
  texture {
    pigment {color rgb <0.1, 0.25, 0.75>}
    finish {
      ambient <1, 1, 1> 
      diffuse 0
    }
  }
}

于是,它就亮了,呈现出了万里无云的天空的颜色:

sky-blue-sphere-no-diffuse-with-land-and-ambient

万里无云,太夸张了,这个球体的半径只是 2 而已。那么就将它放大 5000 倍吧,并且让它的中心与坐标系原点重合:

sphere {
  <0, 0, 0>, 5000
  texture {
    pigment {color rgb <0.1, 0.25, 0.75>}
    finish {
      ambient <1, 1, 1> 
      diffuse 0
    }
  }
}

于是,我们就看到了蔚蓝的天空下一望无际的棋盘格的大平原:

sky-and-land

还记得我们的相机是怎么设置的吗?

camera {
  location <0, 2, -3>
  look_at  <0, 1,  2>
}

现在,将镜头中心对准更远的地方,并在场景中再添加一个球体:

camera {
  location <0, 2, -3>
  look_at  <0, 3,  8>
}

sphere {
  <3, 1, 5>, 1
  texture {
    pigment {color Yellow}
  }
}

现在,场景变为:在蔚蓝色的天空下,在棋盘格的地面上,躺着一个略微有点变形的黄颜色的球体。

sky-and-land-and-sphere

这个球体之所以会略微有点变形,是透视投影的自然结果。如果它位于相机的镜头中心轴线上,

sphere {
  <0, 2.5, 2.5>, 1
  texture {
    pigment {color Yellow}
  }
}

结果就不会变形:

sky-and-land-and-sphere-no-distortion

球心的位置是根据相机的位置及其观测位置计算所得,使之恰好落在镜头中心轴线上。

天空没有云,太单调了。我们可以像构建天空那样构建云层吗?

云层是什么?如果不是晴朗的清晨与黄昏,云层无非是白色、灰色以及透明色随机混合的结果而已。先来看如何实现多种颜色的混合,拿刚才绘制的那个黄色的球体(球心为 <0, 2.5, 2.5>,半径为 1 的那个球体)下手:

sphere {
  <0, 2.5, 2.5>, 1
  texture{ 
    pigment{ 
      gradient y
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
    }
    finish {ambient 1 diffuse 0}
  }
}

结果可得:

gradient-sphere

这是 povray 的梯度颜色机制的效果。「gradient y」表示「梯子」的「横杆」垂直于 y 轴。上述示例中的梯子,第一根横杆是非常浅的灰色,第二根横杆是白色,第三根横杆是比第一根横杆深一点的灰色,第四根与第五根横杆是透明的。

若将这架梯子的尺寸缩小一些,

sphere {
  <0, 2.5, 2.5>, 1
  texture{ 
    pigment{ 
      gradient y
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      scale 0.25  // <--- 这里是关键
    }
    finish {ambient 1 diffuse 0}
  }
}

它的结构会更清晰一些:

gradient-sphere-reduce

虽然整块的梯度颜色区域被缩小了,但是就像桌面壁纸有个「Tile」的功能一样,它会被 povray 重复使用,直至完全覆盖物体表面。

虽然梯子形状的云,没人见过,但是只要将梯子的各行横杆的形状随机扭曲一下:

sphere {
  <0, 2.5, 2.5>, 1
  texture{ 
    pigment{ 
      // gradient y
      bozo turbulence 0.75 // <-- 注意此处
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      scale 0.25
    }
    finish {ambient 1 diffuse 0}
  }
}

它就可以变成现实中的云:

cloud-sphere

是的,它现在还不是现实中的云,只是个水晶球,但是只要像之前构建天空那样,将这个球的球心移到坐标原点,然后把它再放大到比天空小一些,那它就是云了,即:

sphere {
  <0, 0, 0>, 4000
  texture{ 
    pigment{ 
      bozo turbulence 0.75
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      scale 0.25
    }
    finish {ambient 1 diffuse 0}
  }
}

结果却令人失望,并没有云,只是天空变的白了一点:

cloud-density

天空变白的原因很简单。我们将球体放大了 4000 倍,但是球体上的云块却没有放大,于是 povray 重复成千上万次,用这个很小云块填满偌大个的球体表面,再加上球体被放大后,球面距离我们的相机也非常的远,所以我们所看到的天空,变白了。

要解决这个问题,只需将原有的缩放比例乘以 4000:

sphere {
  <0, 0, 0>, 4000
  texture{ 
    pigment{ 
      bozo turbulence 0.75
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      scale 0.25 * 4000
    }
    finish {ambient 1 diffuse 0}
  }
}

现在,可以看到像薄棉絮一样的云了!

cloud

bozo 是 povray 提供的一组随机扰动模式中的一种,主要用来画云。其他模式有 marble(大理石)、agate(玛瑙)、granite(花岗岩)、leopard(豹纹)、spotted(斑点)以及 wood(木头)等,可以将这些随机扰动模式逐一代入到上述示例,并改改 scale 值,看看都什么效果。

像下面这种随机扰动模式:

sphere {
  <0, 0, 0>, 4000
  texture{ 
    pigment{ 
      marble
      turbulence 1
      lambda .8
      frequency 2
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      rotate 90 * z
      scale 0.3 * 800
    }
    finish {ambient 1 diffuse 0}
  }
}

可以渲染出「大马士革钢」的纹路:

cloud-damascus-steel

大马士革钢由多种钢材折叠锻打而成,表面经酸洗后,可以出现与上图相似的纹路:

blade-damascus-steel

最后,再回到薄如棉絮的云的场景中,这个场景太空荡了,可以在里面放一块大石头压压场子:

#include "stones.inc"
box {
  <0, 0, 0>, <1, 1, 3>
  texture {
    T_Stone25
  }
  rotate 30 * y
  translate 5 * z
}

stone-box

如果将光源,由原来的

light_source {
  <2, 4, -2>
  color White
}

改为

light_source {
  <2000, 4500, -100>
  color White
}

那么光源的位置便处于天空与云层之间,于是我们就像上帝那样,创造了一个太阳:

sun

虽然现实中的太阳,应该放在天空之外的,但是那个作为天空的球体会挡住阳光。

下面给出一份完整的 .pov 文件可供参考:

#version 3.7;
#include "colors.inc"

// 相机
camera {
  location <0, 2, -3>
  look_at  <0, 3,  8>
}

// 光源
light_source {
  <2000, 4500, -100>
  color White
}

// 天空
sphere {
  <0, 0, 0>, 5000
  texture {
    pigment {color rgb <0.1, 0.25, 0.75>}
    finish {
      ambient <1, 1, 1> 
      diffuse 0
    }
  }
}

// 云
sphere {
  <0, 0, 0>, 4000
  texture{ 
    pigment{ 
      bozo turbulence 0.75
      color_map {
        [0.0  color rgb <0.95, 0.95, 0.95>]
        [0.05  color rgb <1, 1, 1>]
        [0.15 color rgb <0.85, 0.85, 0.85>]
        [0.55 color rgbt <1, 1, 1, 1>]
        [1.0 color rgbt <1, 1, 1, 1>]
      }
      scale 0.25 * 4000
    }
    finish {ambient 1 diffuse 0}
  }
}

// 大地
plane {
  y, 0
  texture {
    pigment {
      checker color Red, color Blue
    }
  }
}

// 大石块
#include "stones.inc"
box {
  <0, 0, 0>, <1, 1, 3>
  texture {
    T_Stone25
  }
  scale 3
  rotate 45 * y
  translate 5 * z
}

就这样,不务正业了一个周末的下午和晚上。

发表评论

电子邮件地址不会被公开。 必填项已用*标注