ZhangZhihui's Blog  

 

1

上图是Blender中我按照教程创建的雪山,请帮我理解Shader Editor中的工作流,特别是图片Rocks.jpg的作用。

 

可以。这张节点图其实是一个很典型的 “高度分层 + 岩石纹理 + 位移” 的雪山材质。你现在最需要理解的,是 Rocks.jpg 并不是主要拿来给山体“上色”的,而是主要参与生成表面凹凸/位移

我按照你的节点从左到右拆开讲。


一、先看整个工作流

你的节点实际上可以分成 两条线路

线路 1:决定山体颜色

Geometry → Separate XYZ → ColorRamp → Principled BSDF → Material Output

作用:

根据山体的 Z 高度,判断哪里是雪、哪里是岩石,并产生不同的颜色。


线路 2:制造山体表面的岩石凹凸

Texture Coordinate → Mapping → Rocks.jpg → Mix → Displacement → Material Output

同时:

ColorRamp → Mix 的 Factor

作用:

根据山体高度,决定哪些区域使用 Rocks.jpg 产生表面细节。

所以你可以把整个材质理解成:

 
                 高度 Z
                  │
                  ▼
             Color Ramp
              │       │
              │       └──────────┐
              ▼                  ▼
          山体颜色             Mix Factor
              │                  ▲
              ▼                  │
        Principled BSDF          │
                                 │
Rocks.jpg ──────────────────────►Mix
                                  │
                                  ▼
                             Displacement
                                  │
                                  ▼
                              山体凹凸
 

二、首先理解 Geometry → Separate XYZ

你这里:

Geometry 的 Position

连接到:

Separate XYZ 的 Vector

然后取:

Z

这一步非常重要。

Geometry 的 Position 是什么?

它代表当前着色位置的三维坐标:

 
X → 左右
Y → 前后
Z → 高度
 

你现在只取:

Z

所以 Blender 实际上是在问:

“这个山体表面上的这个点,现在处于什么高度?”

例如:

 
             ▲ Z
             │
          /‾‾‾‾\
        /        \
      /            \
____/________________\____
 

山顶:

Z 较大

山脚:

Z 较小

于是就可以利用 Z 来判断:

高处 → 雪
低处 → 岩石

这就是雪山材质最常见的做法之一。


三、Color Ramp 是整个材质的“雪线控制器”

你的:

Z → ColorRamp Factor

然后 ColorRamp 输出:

Color

连接到了:

Principled BSDF → Base Color

所以 Color Ramp 的作用就是:

把“高度数值”转换成“颜色”。

例如:

 
Z 高度
  │
  ▼
Color Ramp

黑 ─────────────── 白
│                  │
岩石               雪
 

因此它实际上形成了一条:

雪线(Snow Line)

例如可以理解成:

 
             白色
       ❄❄❄❄❄❄❄
      /          \
     /            \
    /--------------\ ← 雪线
   /                \
  /                  \
 岩石                岩石
 

你在 Color Ramp 上移动白色控制点,本质上就是:

改变雪覆盖到多低的位置。

这也是为什么雪山教程里经常会看到:

Geometry → Separate XYZ → ColorRamp

这个组合。


四、重点来了:Rocks.jpg 到底干什么?

你的问题核心就在这里。

你的 Rocks.jpg 并没有直接连接:

Base Color

而是:

Rocks.jpg → Mix → Displacement

所以它主要不是负责山体颜色。

它负责的是:

给山体表面增加岩石纹理的高度变化。

可以把 Rocks.jpg 理解成一张:

“凹凸地图”

例如这张图片假设是:

 
白色区域
████████
    ↑
    高

灰色
████████

黑色区域
████████
    ↑
    低
 

当它进入 Displacement:

 
白 → 凸起
灰 → 基准
黑 → 凹陷
 

于是原本平滑的山:

 
──────────────
 

变成:

 
_/\/\___/\/\____/\/\_
 

这样才有岩石的真实质感。


五、为什么 Rocks.jpg 前面还要放 Mapping?

你这里:

Texture Coordinate → Mapping → Rocks.jpg

而且 Mapping 里:

 
Scale X = 25
Scale Y = 75
Scale Z = 1
 

这个设置很值得理解。

Mapping 的作用就是:

控制这张 Rocks.jpg 在山体表面如何铺开。

例如原本图片:

 
┌─────────────┐
│     岩石     │
│   纹理       │
└─────────────┘
 

如果直接使用,可能会:

  • 太大
  • 太小
  • 拉伸
  • 重复次数不够

所以通过 Mapping:

 
Scale X = 25
Scale Y = 75
 

相当于把纹理在 X/Y 方向进行缩放/重复,使岩石纹理更加密集。


六、为什么 X=25、Y=75 不一样?

这其实就是一个比较有意思的地方。

你设置:

X = 25

Y = 75

意味着:

Rocks.jpg 在 Y 方向的纹理变化频率比 X 方向高。

所以这张图片不是简单地“等比例缩放”。

这可能是教程作者为了适应这个 Mountain 的实际形状和比例。

不过需要注意:

如果你想要真实的岩石纹理,一般不建议随意把 X/Y 拉得差异太大。

否则 Rocks.jpg 里的岩石可能会变成:

 
正常:

██ ██ ██
██ ██ ██

↓

拉伸:

████████
████████
████████
 

产生明显的方向性。

你可以自己试一下:

X = 25,Y = 25

然后:

X = 50,Y = 50

看看山体纹理有什么变化。

这也是理解 Mapping 最好的办法。


七、最关键:为什么 Rocks.jpg 要经过 Mix?

你的节点中:

Rocks.jpg → Mix

同时:

ColorRamp → Mix Factor

这实际上非常聪明。

因为作者不是想:

整座山都使用 Rocks.jpg。

而是想:

只有特定高度区域才出现岩石细节。

所以:

ColorRamp 决定“哪里使用岩石”

Rocks.jpg 决定“岩石长什么样”


举个例子

假设:

 
ColorRamp

黑色 ─────────── 白色
低处              高处
 

那么:

 
低海拔
    ↓
Factor = 0
    ↓
Mix 使用 A
    ↓
没有 Rocks.jpg
 

而:

 
高海拔
    ↓
Factor = 1
    ↓
Mix 使用 B
    ↓
使用 Rocks.jpg
 

所以就形成:

 
                山顶
          Rocks.jpg
        /\/\/\/\/\/\/\
       /\/\/\/\/\/\/\/\
------ 雪线 -----------
     平滑区域
_______________________
 

这就是为什么Rocks.jpg 不应该直接连接 Displacement

否则整座山都会出现岩石纹理。


八、Mix 节点的 A、B 是什么?

从你的截图来看,Mix:

  • A 是一个灰色默认值
  • BRocks.jpg
  • Factor 来自 ColorRamp

所以它实际上是在做:

根据高度,在“灰色基础值”和“Rocks.jpg”之间进行混合。

可以理解成:

 
低处:

A = 灰色
B = Rocks.jpg
Factor = 0

结果 ≈ 灰色
 

而:

 
高处:

A = 灰色
B = Rocks.jpg
Factor = 1

结果 = Rocks.jpg
 

最后:

Mix Result → Displacement Height


九、Displacement 节点在干什么?

你的:

Mix → Displacement Height

然后:

Displacement → Material Output Displacement

这里就是真正产生:

山体表面高低变化

的地方。

你的参数:

 
Midlevel = 0.500
Scale = 0.010
 

其中:

Midlevel = 0.5

意思是:

中间灰度值 0.5 作为基准高度。

所以:

 
黑色 0
     ↓
向下

灰色 0.5
     ↓
基本不变

白色 1
     ↓
向上
 

Scale = 0.010

决定:

这个高度变化到底有多强。

也就是说:

 
Scale = 0

完全平

Scale = 0.01

轻微岩石起伏

Scale = 0.1

非常明显的凹凸
 

对于你这个 2420m × 2420m 的巨大 Mountain0.01 的位移属于非常小的表面细节。


十、所以 Rocks.jpg 最准确的理解是什么?

你可以记住这一句话:

Rocks.jpg 是“岩石表面细节的高度信息”,而 ColorRamp 是“决定这些岩石细节出现在哪些高度”的遮罩。

它们两个配合:

ColorRamp = Where(在哪里)

Rocks.jpg = What(是什么纹理)

Displacement = How much(凸凹多少)

这个思路非常重要。


十一、为什么不用 Rocks.jpg 直接接 Base Color?

当然可以。

例如:

 
Rocks.jpg
    ↓
Base Color
 

这样会产生:

岩石颜色纹理

但是你教程现在的做法不是这样。

它采用:

Base Color

由:

高度 → ColorRamp

控制。

因此整个山体可以实现:

 
低海拔
    ↓
岩石颜色

高海拔
    ↓
雪白颜色
 

同时:

Displacement

由:

Rocks.jpg

控制。

所以最终效果是:

 
               ❄❄❄❄❄
            ❄❄❄❄❄❄❄❄
          /\/\/\/\/\/\/\
        /\/\/\/\/\/\/\/\/\
       /\/\/\/\/\/\/\/\/\/\
      /____________________\
        岩石区域
 

颜色负责“看起来是什么”,Displacement负责“表面长什么样”。


十二、还有一个你现在值得注意的问题

你截图里 Rocks.jpg 使用的是:

Texture Coordinate → Generated

而不是 UV。

这意味着这张岩石图片并不是根据 Mountain 的 UV 展开来贴,而是使用 Blender 根据物体包围盒生成的 0~1 Generated 坐标

所以:

 
Generated
    ↓
Mapping
    ↓
Rocks.jpg
 

实际上是一种非常方便的:

“不用 UV 展开就给山体贴程序纹理”

的方法。

这对于你这种 ANT Landscape 生成的巨大山体特别方便。

你不用专门给 Mountain 做复杂 UV。


十三、把整个节点记成一句话

你的整个雪山材质可以浓缩成:

先通过 Z 高度判断山体哪里是雪;再用同一个高度遮罩决定哪里加入 Rocks.jpg 的岩石微地形;最后把岩石纹理送进 Displacement,让山体表面产生真实的凹凸。

对应关系:

节点作用
Geometry 获取山体位置
Separate XYZ 把 XYZ 拆开
Z 获取高度
Color Ramp 根据高度生成雪线/遮罩
Texture Coordinate 获取纹理坐标
Mapping 控制 Rocks.jpg 的缩放/铺设
Rocks.jpg 提供岩石纹理细节
Mix 根据高度决定哪里使用岩石纹理
Displacement 把纹理转换成真实凹凸
Principled BSDF 控制山体整体材质/颜色
Material Output 输出最终材质

你现在最值得做的一个实验

为了真正理解 Rocks.jpg,建议你在当前文件里只做一个改动

把:

Rocks.jpg → Mix

暂时断开,然后把:

Rocks.jpg → Principled BSDF → Base Color

直接连接。

你会马上看到:

整座山变成岩石纹理。

然后再把它恢复。

接着把:

Rocks.jpg → Mix → Displacement

保留。

你就会非常直观地理解:

同一张 Rocks.jpg,可以作为“颜色纹理”,也可以作为“高度纹理”;在你这个教程里,它主要承担的是后者。

另外,你这个节点图里还有一个很值得研究的地方:ColorRamp 同时参与 Base Color 和 Mix Factor。这其实就是这个雪山材质的核心技巧——一个“高度遮罩”同时控制雪的颜色和岩石位移。如果你愿意,我可以接着给你讲清楚 为什么这个 ColorRamp 的黑白位置(尤其是 0.850)能控制“雪线”,以及怎样自己调出“积雪很多 / 积雪很少 / 只有山顶积雪”的效果。

 

 

于是就可以利用 Z 来判断:

高处 → 雪
低处 → 岩石

那为什么最后看到山脚下的地面上也都是雪(白色)?

 

对,你这个问题问得非常关键。我上一条把“Z 高度 → 高处雪、低处岩石”讲得过于简化了。
从你这张节点图来看,真正需要注意的是:ColorRamp 接收到的 Z 数值,和你直觉中的“海拔高度”不是一回事。

而你看到的“山脚下大片白色地面”,很可能正是由这个原因造成的。


1. 关键:ColorRamp 并不知道什么叫“山顶、山脚”

你的节点是:

Geometry → Position → Separate XYZ → Z → ColorRamp

这里的 Z 本质上只是:

当前着色点的 Z 坐标值

它不会自动理解:

308m 是山顶
0m 是山脚
50m 以下是岩石
200m 以上是雪

例如假设 Mountain 的 Z 坐标是:

 
山顶       Z = 308
           │
           │
           │
山腰       Z = 150
           │
           │
山脚       Z = 20
───────────────
地面       Z = 0
 

你以为 ColorRamp 会自动按照这个高度进行判断。

实际上不会。

ColorRamp 只是把输入数值映射成颜色。


2. 你的 ColorRamp 有一个很重要的特点

截图中可以看到:

黑色控制点在最左边

白色控制点大约在 0.850

也就是说它实际上类似:

 
0.0                         0.85       1.0
│----------------------------│----------│
黑                           白         白
 

超过白色点之后,就全部保持白色。

所以如果送进 ColorRamp 的 Z 值已经超过它的有效范围,结果就会变成:

白色。


3. 这就解释了为什么“山脚地面”也可能是白色

这里有一个特别容易忽略的地方:

你的 Mountain 并不一定是:

 
       山顶 Z=308
          ▲
         / \
        /   \
       /     \
      /       \
─────/─────────\──── Z=0
 

它可能是类似:

 
       山
      /\
     /  \
____/    \____________
 

也就是说 ANT Landscape 生成的是一个完整的矩形地形网格

山体周围的大片平地实际上也是:

Mountain 对象的一部分

而不是一个独立的“地面”。


4. 更重要的是:你的 Z 可能并不是 0~1

这就是理解这个节点最重要的地方。

你的 Mountain 尺寸之前是:

Z Size = 308m

所以它的实际几何高度可能是几十、几百米。

而 ColorRamp 的位置:

0.850

并不是:

0.850 米

它表示的是 ColorRamp 输入范围中的位置。

因此不能简单理解成:

Z = 0.85m → 开始下雪


5. 你可以马上做一个非常直观的实验

在你的 Shader Editor 中:

把 ColorRamp 暂时改成 Constant

ColorRamp:

Interpolation → Constant

然后拖动黑白两个控制点。

你会看到山体上的“雪线”突然变得非常明显。

例如:

 
黑
│
│    岩石
│
│────────────── ← 黑/白分界
│    雪
│
白
 

这个实验非常适合理解:

ColorRamp 实际上就是一个“高度阈值”。


6. 但我更推荐你做一个更准确的雪线控制方法

不要直接把:

Position Z → ColorRamp

当成最终方案。

建议先做:

Separate XYZ → Map Range → ColorRamp

变成:

 
Geometry
   │
 Position
   │
Separate XYZ
   │
   Z
   │
Map Range
   │
   ▼
ColorRamp
   │
   ▼
Base Color
 

7. Map Range 是干什么的?

它可以把你的实际高度:

例如:

 
Z = 0m
Z = 50m
Z = 100m
Z = 200m
Z = 308m
 

重新转换成:

 
0
0.16
0.32
0.65
1
 

然后再交给 ColorRamp。

这样你就可以非常明确地告诉 Blender:

100m 以下是岩石,200m 以上开始积雪。

例如:

Map Range:

 
From Min = 0
From Max = 308

To Min = 0
To Max = 1
 

然后:

Map Range → ColorRamp


8. 这样你就真正拥有了“雪线控制”

例如你希望:

0~150m

岩石:

 
Z = 0~150
    ↓
ColorRamp 黑
 

150~200m

逐渐积雪:

 
Z = 150~200
    ↓
黑 → 白
 

200m 以上

全部积雪:

 
Z > 200
    ↓
白
 

最终:

 
                 ❄❄❄
               ❄❄❄❄❄
             ❄❄❄❄❄❄❄
           ─────────────  ← 雪线
         /                \
       /                    \
     /       岩石           \
___/__________________________\___
 

这才是真正意义上的:

“根据实际海拔高度生成雪。”


9. 还有一个非常重要的问题:你的“白色地面”到底是不是 Mountain?

你可以马上验证。

在 3D Viewport 中:

方法一

选中 Mountain,进入:

Edit Mode

然后点击你看到的白色地面区域。

如果能选中它:

说明这个白色地面就是 Mountain 对象本身。


方法二

暂时把:

ColorRamp → Principled Base Color

这根线断开。

给 Base Color 一个明显的纯黑色。

如果:

山 + 白色地面一起变黑

那么说明这个地面确实使用了这个材质。


10. 另外还有一种可能:你的“地面”是另一个对象

如果白色地面是另外创建的 Plane,那么它可能只是:

自己的材质颜色就是白色。

这种情况下,Mountain 的 ColorRamp 根本没有控制它。

所以你可以:

选中白色地面 → 看顶部对象名称。

如果名称不是:

Mountain

而是:

Plane / Ground / Terrain

之类,那么它就是另一个对象。


11. 我建议你现在不要急着修改节点

你这个教程非常适合趁这个机会把一个概念搞透:

目前:

 
Position
   ↓
   Z
   ↓
ColorRamp
 

它表达的是:

根据坐标值生成颜色。

而不是严格意义上的:

根据海拔生成雪。

如果想建立真正可控的雪山材质:

 
实际 Z 高度
     ↓
  Map Range
     ↓
标准化 0~1
     ↓
 ColorRamp
     ↓
雪/岩石遮罩
 

这个工作流会更加合理。


你现在这个白色地面的现象,我建议你先做一个最简单的检查:

选中白色地面区域,看它是不是 Mountain 对象的一部分。

如果你确认它就是 Mountain 对象本身,你可以再告诉我,我可以根据你这张节点图进一步给你解释:为什么同一个 ColorRamp 会让山顶是雪、山腰是岩石,但最下面的平地又变成白色,以及怎样只让“山坡”产生雪而不让周围平地变白。

 

 

图中白色地面是mountain的一部分,图中的Color Ramp已经是Constant。

 

对,这两个信息非常关键:

  • 白色地面确实是 Mountain 本身的一部分
  • Color Ramp 已经是 Constant

那么现在基本可以确定原因了,而且这里需要纠正我上一条回答中的一个关键点:

你现在的 Z → ColorRamp 并不是一个 0~1 的“归一化高度”。

这正是为什么山脚的平地也会变白。


1. 你现在真正的节点关系

你的截图是:

Geometry → Position → Separate XYZ → Z → ColorRamp

注意这里不是:

Texture Coordinate → Generated → Separate XYZ

而是直接使用:

Geometry → Position

Position 输出的是当前着色点的位置坐标,而不是自动转换成 0~1 的高度比例。

假设你的 Mountain 大致是这样的:

 
             山顶
              Z=308
               ▲
              /\
             /  \
            /    \
           /      \
__________/        \________
 Z≈0                   Z≈0
 

那么山脚平地的 Z 值可能就是:

Z ≈ 0

而山顶可能:

Z ≈ 308


2. 你的 Color Ramp 为什么会把山脚变成白色?

看看你的 Color Ramp:

 
黑色点       白色点
  ↓            ↓
 0          0.850
 │------------│
 

而 Color Ramp 的输入通常按照 0~1 的范围来解释。

于是:

 
Z = 0
 ↓
ColorRamp
 ↓
黑色
 

这个看起来没问题。

但是:

 
Z = 0.85
 ↓
白色
 

而:

 
Z = 10
 ↓
超过 ColorRamp 范围
 ↓
白色
 

甚至:

 
Z = 100
 ↓
白色
 
 
Z = 300
 ↓
白色
 

所以如果你的山体 Z 坐标是:

 
0 ~ 308
 

那么实际上:

几乎所有 Z > 0.85m 的地方都会被判定成白色。

这就解释了你现在看到的现象。


3. 为什么山顶看起来是雪,山脚也有大片白色?

因为你现在的 ColorRamp 实际上是在做:

 
Z ≤ 0        → 黑
Z ≈ 0~0.85   → 黑→白
Z > 0.85     → 白
 

而不是你以为的:

 
山脚 → 黑
山腰 → 黑
山顶 → 白
 

所以如果 Mountain 的底部接近 Z=0,那么:

 
                    Z=308
                     ▲
                     │ 白
              ███████████
             █████████████
            ███████████████
           █████████████████
          ███████████████████
         █████████████████████
        ███████████████████████
       ─────────────────────────
              Z≈0
 

整个山体中只要 Z 大于 0.85m,就基本会得到白色。

你截图里的白色平地正好符合这个逻辑。


4. 那为什么教程会这样设置?

这里我反而怀疑教程作者的节点图还有一个你需要特别注意的上下文

可能教程中的 Mountain 的位置/尺寸与当前文件不同。

例如教程中的模型可能是:

 
Z = -1 ~ +1
 

那么:

 
ColorRamp 0~1
 

就比较合理。

但你的 Mountain 是 ANT Landscape 创建的:

Z Size = 308m

实际坐标范围完全不同。

所以你照抄:

ColorRamp 白色位置 = 0.850

并不意味着你的山也会在 85% 高度开始下雪。


5. 这也解释了一个非常重要的概念

你现在需要区分:

A. 实际 Z 坐标

 
Z = 0m
Z = 50m
Z = 100m
Z = 200m
Z = 308m
 

和:

B. 归一化高度

 
0.0
0.2
0.4
0.6
0.8
1.0
 

ColorRamp 更适合处理第二种。


6. 最简单的解决办法:用 Generated 坐标

如果你的目标只是:

山体底部 = 0,山顶 = 1,然后用 ColorRamp 控制雪线

我其实非常推荐你改成:

 
Texture Coordinate
       │
    Generated
       │
       ▼
Separate XYZ
       │
       Z
       │
       ▼
 Color Ramp
 

也就是:

不要使用 Geometry → Position 的 Z。

而使用:

Texture Coordinate → Generated → Z

因为 Generated 坐标会根据对象的包围盒生成 0~1 的坐标

于是你的 Mountain:

 
最高点
Z = 308m
     │
     │ Generated Z = 1
     ▼
    山顶
────────────────
Generated Z = 0.5
────────────────
    山脚
     │
     │ Generated Z = 0
     ▼
 

这时候 ColorRamp 的:

0.850

才真正可以理解成:

大约在 Mountain 高度的 85% 附近开始变化。


7. 你可以马上做这个实验

把现在:

Geometry → Position

这条线断掉。

然后添加:

Texture Coordinate

找到:

Generated

连接:

Generated → Separate XYZ → Z

保持你现在的 ColorRamp:

Constant

不动。

你再看 Rendered 结果。

你应该会发现:

白色平地消失,白色主要集中到 Mountain 的高处。

这应该就是你这个教程真正想达到的效果。


8. 不过还有一个问题:你的 0.850 可能太高

假设:

Generated Z = 0~1

而你设置:

White = 0.850

那么雪只会出现在最高的约 15% 区域。

例如:

 
                    ❄❄❄
                  ❄❄❄❄❄
                ❄❄❄❄❄❄❄
              ───────────── ← 0.85
             /             \
            /               \
           /                 \
          /      岩石         \
_________/_____________________\____
           Generated Z=0
 

如果你想让雪更多:

白色控制点往左移动

例如:

0.7

或者:

0.6

如果想让雪只存在于山顶:

0.9~0.95


9. Constant 和 Linear 的区别也正好可以在这里理解

你现在已经使用:

Constant

所以雪线会非常明确:

 
岩石
████████████████
████████████████
──────────────── ← 非常明显的雪线
白雪
░░░░░░░░░░░░░░░░
 

如果改成:

Linear

就会变成:

 
岩石
████████████████
██████████░░░░░
██████░░░░░░░░░
██░░░░░░░░░░░░░
░░░░░░░░░░░░░░░
 

即:

逐渐从岩石过渡到积雪。

真实雪山一般使用 Linear / Ease / B-Spline 等渐变方式会更自然。


10. 还有一个更专业的方案:真正按照“米”控制雪线

如果你的目标不是“模型高度的 85%”,而是:

海拔 200m 以下不下雪,200~250m 开始积雪,250m 以上全部积雪

那么就不要用 Generated。

可以保留:

Geometry → Position → Separate XYZ → Z

然后加入:

Map Range

变成:

 
Geometry
   ↓
Position
   ↓
Separate XYZ
   ↓
   Z
   ↓
Map Range
   ↓
ColorRamp
 

例如你的 Mountain:

0~308m

可以设置:

 
From Min = 0
From Max = 308

To Min = 0
To Max = 1
 

然后 ColorRamp 再控制:

 
0.70 → 开始下雪
0.85 → 完全积雪
 

这样就真正建立了:

实际高度 → 归一化高度 → 雪线

的工作流。


11. 你这个教程里,我更推荐哪一种?

对于你现在这个 ANT Landscape 的雪山:

如果只是学习 Blender 材质节点

用:

Generated → Z → ColorRamp

最简单。

如果你以后准备认真做雪山环境

我推荐:

Position Z → Map Range → ColorRamp

因为这样你可以直接按照控制雪线。

例如:

150m 开始积雪
220m 大量积雪
280m 基本全雪

这样比“85%高度”更符合实际场景逻辑。


最后总结一下你现在为什么会出现白色地面

不是因为 Constant 设置错误,也不是因为 Mountain 地面特殊。

真正原因是:

你把 Mountain 的实际 Z 坐标直接送进了 ColorRamp,而 ColorRamp 的 0.850 并不是“山体高度的 85%”。

你的 Mountain 高度是 308m,而 ColorRamp 的有效范围是 0~1。因此大量实际 Z 值超过 0.85 的区域都会被映射为白色。

最简单的修复:

Geometry → Position → Separate XYZ → Z

改成:

Texture Coordinate → Generated → Separate XYZ → Z → ColorRamp

然后你的 0.850 才真正具有“山体高度约 85%”的意义。

你这个问题其实非常值得搞清楚,因为它涉及 Blender 材质节点里一个非常核心的概念:“坐标值”和“归一化值”到底有什么区别。理解这个之后,你以后做雪线、草地高度、沙漠分层、岩石分布都会容易很多。

 

 

你这样说我就明白了,教程也没错,教程是要让平的地方有积雪,陡峭的地方没有积雪。

 

对,就是这个意思 👍

这样一来,你这个教程的节点逻辑就非常清楚了。这里的 Color Ramp 并不是简单地表示“高度越高越白”,而是在利用 Position → Z 作为一个条件,同时配合后面的材质效果,去模拟“积雪更容易停留在相对平缓的区域”。

不过这里还有一个值得注意的地方:

你截图里的 Geometry → Normal 没有参与计算,真正连接的是 Position → Z。因此严格来说,这套节点目前主要利用的是高度,不是直接判断“陡峭程度”。

所以教程最终出现:

  • 平坦区域 → 有雪
  • 陡峭山坡 → 少雪/无雪

很可能是因为山体的高度分布 + Color Ramp + 后面的位移/纹理共同产生了这种视觉效果,而不是 Color Ramp 本身在判断坡度。

如果以后你想做得更真实,可以进一步用:

Geometry → Normal → Separate XYZ → Z

来判断表面的朝向。

因为:

  • Normal Z 接近 1 → 表面朝上 → 容易积雪
  • Normal Z 接近 0 → 接近垂直 → 不容易积雪
  • Normal Z < 0 → 朝下 → 基本不会积雪

这就是真正意义上的:

根据坡度/表面朝向决定哪里积雪。

甚至可以把:

高度 Z + Normal Z

两个条件结合起来,做出更真实的雪山:

海拔高 + 表面朝上 → 厚雪
海拔高 + 陡坡 → 少雪
低海拔 + 平地 → 少量积雪
悬崖/背坡 → 无雪

这个思路以后做雪山材质会非常有用。

 

 

在你的第一次回答中你的如下判断是错的:
----------------------------------------------
你这里:
Geometry 的 Position
连接到:
Separate XYZ 的 Vector

----------------------------------------------

我的Geometry节点是用Normal连接到Separate XYZ的Vector而不是Position。所以你能不能结合我后面追加的信息重新回答一下(请帮我理解Shader Editor中的工作流,特别是图片Rocks.jpg的作用 )。

 

你说得对。**我第一次回答把 Geometry → Normal 看成了 Geometry → Position,这是我的判断错误。**结合你最开始的截图,以及你后来补充的“平地有雪、陡峭地方没有雪”,这套材质的逻辑其实比我第一次解释的更有意思。

这张图的核心并不是“根据高度决定积雪”,而是:

根据山体表面的法线方向(也就是坡度/朝向)判断哪里容易积雪,然后用 Rocks.jpg 给岩石区域增加表面凹凸。

下面重新完整解释一次。


一、先看整个 Shader 工作流

你的节点实际上可以分成两条线:

 
                    ┌──→ ColorRamp ──→ Base Color
                    │
Geometry → Normal → Separate XYZ
                    │
                    └──→ ColorRamp ──→ Mix Factor
                                      ↑
                                      │
Texture Coordinate → Mapping → Rocks.jpg
                                      │
                                      ▼
                                     Mix
                                      │
                                      ▼
                                 Displacement
 

所以整个材质可以概括为:

Normal 决定“哪里积雪”,Rocks.jpg 决定“岩石表面长什么样”,Displacement 决定“岩石表面有多凹凸”。


二、最关键的 Geometry → Normal

你这里真正连接的是:

Geometry → Normal → Separate XYZ

而不是 Position。

这非常重要。

Normal 是什么?

Normal 可以理解成:

当前表面的“朝向箭头”。

假设有一个水平地面:

 
          ↑ Normal
          │
          │
──────────●──────────
 

它的 Normal 基本朝向 Z 轴:

Normal Z ≈ 1

而一个垂直的悬崖:

 
          │
          │ → Normal
          │
          │
 

它的 Normal 主要朝 X/Y:

Normal Z ≈ 0

所以:

表面Normal Z积雪能力
水平地面 ≈ 1 很容易积雪
缓坡 0.7~1 容易积雪
较陡坡 0.3~0.7 较少
垂直悬崖 ≈ 0 很难积雪
朝下表面 < 0 基本不积雪

这正好解释了你前面发现的现象:为什么平地是白色的。

因为教程就是故意让平坦区域也积雪


三、Separate XYZ 在这里的作用

Normal 本身是一个三维向量:

 
Normal = (X, Y, Z)
 

例如:

 
Normal X = 0.2
Normal Y = 0.1
Normal Z = 0.97
 

Separate XYZ 就把它拆成:

 
X
Y
Z
 

教程只拿:

Z

继续往下。

所以这里实际上是在问:

“这个表面的法线有多少是朝向天空的?”

而不是:

“这个地方的海拔是多少?”

这是整个节点图最核心的概念。


四、Color Ramp 实际上是“积雪坡度遮罩”

你的连接是:

Normal Z → ColorRamp Factor

而 ColorRamp 设置成了:

Constant

白色控制点大约在:

0.850

这就非常有意义了。

可以把它理解为:

 
Normal Z

0.0                         0.85        1.0
│----------------------------│-----------│
陡坡                         │           平地
                             │
                             ↓
                          积雪开始
 

因为是 Constant,所以不是渐变,而是一个非常明确的阈值:

 
Normal Z < 0.85
        ↓
       黑色
        ↓
      不积雪

Normal Z ≥ 0.85
        ↓
       白色
        ↓
      积雪
 

因此你这个 Color Ramp 本质上就是:

“坡度雪线开关”


五、为什么平地是白色?

现在就非常容易理解了。

平地:

 
──────────────
       ↑
     Normal
 

它的:

Normal Z ≈ 1

而:

1 > 0.85

所以:

 
Normal Z = 1
     ↓
ColorRamp
     ↓
白色
     ↓
积雪
 

而陡峭的山壁:

 
      /
     /
    /
 

Normal 更接近水平方向:

Normal Z ≈ 0

于是:

 
Normal Z = 0.2
     ↓
ColorRamp
     ↓
黑色
     ↓
不积雪
 

所以教程的设计逻辑其实非常合理。


六、那么 Rocks.jpg 到底是什么作用?

现在重新看下面这一条线路:

 
Texture Coordinate
       ↓
   Generated
       ↓
    Mapping
       ↓
   Rocks.jpg
       ↓
      Mix
       ↓
  Displacement
 

这条线与“雪在哪里”是另一回事。

Rocks.jpg 主要负责制造岩石表面的细节。

你可以把它理解为一张:

岩石高度纹理/凹凸纹理

而不是单纯的颜色图片。


七、为什么使用 Generated

你的:

Texture Coordinate → Generated

然后:

Generated → Mapping

这里的 Generated 是 Blender 根据物体包围盒生成的 0~1 坐标

所以不用给 Mountain 做 UV 展开,也能把 Rocks.jpg 映射到整个山体。

大概相当于:

 
Mountain 包围盒

0 ─────────────── 1
│                │
│   Rocks.jpg    │
│    纹理        │
│                │
0 ─────────────── 1
 

然后 Mapping 控制这张图片在山体上重复/缩放多少。


八、你的 Mapping:X=25、Y=75 是干什么的?

你截图中:

 
Scale
X = 25
Y = 75
Z = 1
 

这意味着 Rocks.jpg 的纹理坐标被进行了较大的缩放。

可以简单理解为:

让岩石纹理在山体表面重复很多次。

为什么 X 和 Y 不一样?

因为教程作者是在调整:

Rocks.jpg 在这个特定 Mountain 上的纹理密度和比例。

你如果把:

 
X = 25
Y = 75
 

改成:

 
X = 50
Y = 50
 

你会明显看到岩石纹理的形态发生变化。


九、Rocks.jpg → Mix,这一步非常关键

现在看:

 
Normal Z
    ↓
ColorRamp
    ↓
Factor ─────────┐
                ↓
Rocks.jpg → A  Mix
                │
灰色 → B ───────┘
                ↓
             Result
                ↓
          Displacement
 

你的 Color Ramp 输出被同时用于:

① Principled BSDF → Base Color

以及:

② Mix → Factor

也就是说:

同一个“坡度遮罩”同时控制颜色和岩石细节。


十、Mix 在这里到底做了什么?

从你的截图来看:

Rocks.jpg → Mix 的 A

而另一路是一个灰色值:

B = 灰色

然后:

ColorRamp → Factor

所以它实际上是在做:

根据坡度,在“岩石纹理”和“平坦灰度”之间切换。

例如:

平坦区域

Normal Z ≥ 0.85:

 
ColorRamp = 白色
Factor = 1

       ↓

Mix 选择其中一路
       ↓

形成相应的 Displacement
 

陡坡

Normal Z < 0.85:

 
ColorRamp = 黑色
Factor = 0

       ↓

Mix 选择另一侧
       ↓

不使用/弱化 Rocks.jpg
 

因此最终效果就是:

岩石纹理的位移效果也受到坡度控制。


十一、这里有一个非常漂亮的设计思想

教程实际上是在用一个 Mask 同时控制两件事情:

Mask = Normal Z → ColorRamp

然后:

 
                 ┌──→ Base Color
                 │
Normal Z → Ramp ─┤
                 │
                 └──→ Rocks.jpg 的使用范围
 

也就是:

表面朝上的地方 → 雪

表面陡峭的地方 → 岩石

然后:

Rocks.jpg → 给岩石区域增加凹凸细节

这就是整个雪山材质的核心。


十二、Displacement 又在做什么?

最后:

Mix → Displacement Height

Displacement 的参数:

  • Midlevel = 0.500
  • Scale = 0.010

它把 Mix 得到的灰度值转换成实际的表面高度变化。

可以理解成:

 
Rocks.jpg

黑色 ───────→ 凹
灰色 ───────→ 基准
白色 ───────→ 凸
 

而:

Scale = 0.010

控制这些凹凸的幅度。

所以:

 
Rocks.jpg
     ↓
黑白灰纹理
     ↓
Displacement
     ↓
真实的岩石凹凸
 

十三、那么为什么雪区域还会使用 Rocks.jpg?

这也是你理解这个节点时可能产生的疑问。

实际上,Rocks.jpg 并不等于“只有岩石才可以使用”。

它只是提供:

表面的细节高度变化。

最终你看到的是:

 
       白雪
  ❄ ❄ ❄ ❄ ❄
 /\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\
────────────────
    岩石
 /\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\
 

雪本身可以覆盖在岩石的微小凹凸上。

所以:

ColorRamp 控制的是材质/区域的“雪与岩石关系”

而:

Rocks.jpg 控制的是表面微观起伏。

两者并不冲突。


十四、你这个节点图其实可以用三个问题来理解

以后看到类似 Shader,不要一开始就纠结每根线,而是问三个问题:

第一个问题:Where?哪里?

这里是:

Normal → Separate XYZ → Z → ColorRamp

回答:

哪些表面朝上?


第二个问题:What?是什么?

这里是:

Rocks.jpg

回答:

这些表面的细节纹理是什么样?


第三个问题:How much?有多强?

这里是:

Mix → Displacement → Scale 0.01

回答:

这些岩石凹凸到底有多明显?

这样整个节点就非常容易理解。


十五、把你的整个节点图翻译成人话

如果把你的 Shader Editor 翻译成一句自然语言,它其实是在说:

“先检查山体每个位置的表面法线,如果这个表面比较朝上(Normal Z ≥ 0.85),就把它定义为容易积雪的区域;同时利用这个遮罩控制材质颜色。然后把 Rocks.jpg 通过 Generated 坐标映射到山体表面,并根据同一个坡度遮罩控制岩石纹理的使用,最后把它转换成 Displacement,让山体产生细小的岩石凹凸。”


最后特别纠正我之前的错误

我之前说:

Geometry → Position → Separate XYZ → Z
“根据 Z 高度判断高处是雪、低处是岩石。”

这个判断是错的。

你实际节点是:

Geometry → Normal → Separate XYZ → Z

因此真正的逻辑是:

Normal Z → 表面朝向/坡度

而不是:

Position Z → 海拔高度

所以你后来观察到:

“教程就是要让平的地方有积雪,陡峭的地方没有积雪。”

完全正确。

而这也正是这个节点设计的目的。你的 Color Ramp = Constant,白色位置 0.850 可以非常直观地理解成:

Normal Z ≥ 0.85 → 积雪;Normal Z < 0.85 → 不积雪。

这比单纯按照高度下雪更接近“雪会落在山上,但在陡峭岩壁上难以停留”的效果。

 

 

“这里的 Generated 是 Blender 根据物体包围盒生成的 0~1 坐标。 ”,这句话里的“物体”指的是图片Rocks.jpg还是mountain?请详细解释一下Generated。

 

这里的“物体”明确指的是 Mountain 对象,而不是 Rocks.jpg 图片

这是理解 Blender 纹理坐标非常重要的一个概念。你可以把 Generated 理解成:

Blender 根据当前着色对象(这里就是 Mountain)的三维包围盒,自动建立的一套 0~1 的三维坐标系。

下面结合你这座 Mountain 具体解释。


1. 先回答最核心的问题

你的节点是:

Texture Coordinate → Generated → Mapping → Rocks.jpg

这里的关系是:

 
Mountain
   │
   │ Blender根据Mountain计算
   ↓
Generated坐标
   │
   ↓
Mapping
   │
   ↓
Rocks.jpg
 

所以:

Generated 的参考对象是 Mountain

而:

Rocks.jpg 是被映射进去的“纹理图片”

可以把它想象成:

Mountain 是一个盒子,Blender 给这个盒子建立一个 0~1 的坐标系,然后把 Rocks.jpg 放进这个坐标系里。


2. 什么叫“包围盒”?

你可以先把 Mountain 想象成这样:

 
              Mountain
          ┌───────────────┐
         / \             /│
        /   \           / │
       /     \         /  │
      /       \       /   │
     /_________\_____/    │
     │         │    │     │
     │         │    │     │
     │         │    │     │
     └─────────┴────┴─────┘
 

Blender 会找到这个 Mountain 的:

  • 最左边
  • 最右边
  • 最前面
  • 最后面
  • 最下面
  • 最上面

这六个边界。

然后形成一个包围 Mountain 的长方体

这个长方体就是:

Bounding Box(包围盒)

注意:

包围盒不是你看到的山体表面。

它只是一个能够把整个 Mountain 包住的“透明盒子”。


3. Blender 然后在这个盒子里建立 0~1 坐标

假设你的 Mountain 包围盒尺寸是:

 
X = 2420m
Y = 2420m
Z = 308m
 

那么 Blender 可以把它转换成:

 
X方向:

最左边                     最右边
  0 ─────────────────────── 1
 

Y方向:

 
最前面                     最后面
  0 ─────────────────────── 1
 

Z方向:

 
最低点
  0
  │
  │
  │
  │
  1
最高点
 

所以 Mountain 的任意一个点,都可以得到一个:

 
(X, Y, Z)
 

形式的 Generated 坐标。

例如:

 
Generated = (0.5, 0.5, 0.8)
 

意思不是:

X=0.5米,Y=0.5米,Z=0.8米

而是:

这个点位于 Mountain 包围盒 X/Y/Z 三个方向相应的 50%、50%、80% 位置。


4. 为什么要设计成 0~1?

因为这样纹理就不需要知道你的 Mountain 到底有多大。

比如你的 Mountain:

 
2420m × 2420m × 308m
 

另外一个 Mountain:

 
100m × 100m × 50m
 

如果都使用 Generated:

 
        Mountain A
2420m × 2420m × 308m
          ↓
     Generated
          ↓
       0~1


        Mountain B
100m × 100m × 50m
          ↓
     Generated
          ↓
       0~1
 

两者都能使用同一套纹理坐标逻辑。

这就是 Generated 非常方便的地方。


5. 那 Rocks.jpg 在这里到底是什么?

现在就容易理解了。

Rocks.jpg 本身只是一张二维图片:

 
┌────────────────────────┐
│  ///////  ////////     │
│ /////  //////  /////   │
│   ////////  //////     │
│ //////  /////////      │
└────────────────────────┘
 

它本身并不知道:

“我要贴在 Mountain 上。”

它需要一个坐标告诉它:

“Mountain 表面这个位置,应该读取图片的哪个位置?”

所以:

 
Generated
    ↓
Mapping
    ↓
Rocks.jpg
 

可以理解为:

Generated 提供“在哪里取纹理”的坐标。


6. 这里有一个非常容易误解的地方

严格来说,Rocks.jpg 是二维图片。

但是:

Generated 是三维坐标。

那么 Blender 怎么把三维坐标给二维图片使用?

这里就涉及到纹理节点的坐标处理。

对于你的 Image Texture

 
Mapping → Vector
 

Image Texture 使用输入的 Vector 来决定:

图片上的哪个位置对应当前表面。

通常可以把它简单理解成:

 
Mountain表面的位置
          ↓
Generated坐标
          ↓
Mapping调整坐标
          ↓
Image Texture
          ↓
Rocks.jpg对应位置
 

7. Mapping 又在这里干什么?

你截图里:

Mapping Scale

 
X = 25
Y = 75
Z = 1
 

这一步就是在修改 Generated 坐标

原来:

 
Generated

0 ─────────────── 1
 

经过 Mapping:

 
Scale X = 25

0 ─────────────────────────────── 25
 

所以纹理会在 X 方向重复很多次。

Y 同理:

 
Scale Y = 75
 

于是 Rocks.jpg 在 Y 方向重复更多次。

因此:

Generated 决定“坐标基准”,Mapping 决定“如何调整这个坐标”。


8. 用一块“透明胶片”来理解最直观

假设你的 Rocks.jpg 是一张岩石纹理:

 
┌───────────────────┐
│ 🪨 🪨 🪨 🪨 🪨    │
│ 🪨 🪨 🪨 🪨 🪨    │
│ 🪨 🪨 🪨 🪨 🪨    │
└───────────────────┘
 

你可以想象 Blender 先做了一个:

Mountain 的透明包围盒

 
       ┌───────────────┐
       │               │
       │   Mountain    │
       │      /\       │
       │     /  \      │
       │____/____\_____│
       └───────────────┘
 

然后把这个盒子标准化成:

 
       ┌───────────────┐
       │               │
       │    0~1       │
       │               │
       └───────────────┘
 

这个就是 Generated。

然后再把 Rocks.jpg 按这个坐标投射到 Mountain 上。


9. Generated 和 UV 有什么区别?

这个问题非常值得一起理解。

你现在使用的是:

Generated

还有一个常见的:

UV

两者最大的区别可以这样理解:

Generated

Blender 自动根据对象包围盒生成坐标。

所以:

不需要你手动展开 UV。


UV

你自己告诉 Blender,三维模型表面应该对应图片的哪个位置。

例如:

 
3D Mountain
      ↓
UV Unwrap
      ↓
二维UV展开图
      ↓
Rocks.jpg
 

UV 可以非常精确地控制:

山顶对应图片哪里
山谷对应图片哪里
左边对应图片哪里

而 Generated 更像:

“我不想展开 UV,Blender 你自己根据模型大小帮我铺一遍。”


10. Generated 最大的优点

对于你现在这种:

ANT Landscape → Mountain

特别方便。

因为你经常可能会改变:

 
X Size
Y Size
Z Size
 

比如:

 
2420 × 2420 × 308
 

改成:

 
3000 × 3000 × 500
 

Generated 会自动根据新的 Mountain 包围盒重新计算。

所以你不需要重新做 UV。


11. 但 Generated 也有一个明显缺点

这点对于你的雪山非常重要。

假设 Mountain 从:

 
2420 × 2420 × 308
 

变成:

 
5000 × 5000 × 100
 

Generated 坐标依然是:

 
0~1
 

实际空间尺寸发生了巨大变化

所以如果 Mapping 不调整:

Rocks.jpg 在模型上的实际纹理尺寸也会跟着变化。

例如原来一块岩石纹理可能覆盖:

10m

模型放大以后可能变成:

20m

所以如果你希望岩石纹理具有固定的“实际米数”,Generated 并不是最理想的方案。


12. 还有一个非常重要的地方:Generated 会跟着 Object 的包围盒走

这意味着:

如果你对 Mountain 的几何形状进行了很大的改变:

 
原来:

       /\
      /  \
_____/    \____


后来:

          /\
         /  \
        /    \
_______/      \______
 

包围盒发生变化。

那么:

Generated 坐标也会相应发生变化。

所以 Generated 是一种:

对象相关(Object-relative)的自动纹理坐标。


13. 回到你的雪山节点图

现在我们可以把你截图中的这一条线完整翻译出来:

 
Texture Coordinate
        │
        │ Generated
        ↓
     Mapping
 X=25 Y=75
        │
        ↓
   Rocks.jpg
        │
        ↓
      Mix
        │
        ↓
  Displacement
        │
        ↓
      山体
 

它表达的是:

以 Mountain 自己的包围盒作为坐标基准,在 Mountain 表面铺设 Rocks.jpg,然后通过 Mapping 调整纹理的重复密度,再将纹理的明暗转换成表面凹凸。


14. 最后把 GeneratedRocks.jpg 的关系彻底分开

这是你现在最应该记住的:

Mountain

是:

被着色的对象

Generated

是:

Blender 根据 Mountain 自动产生的 0~1 三维坐标

Mapping

是:

调整这些坐标

Rocks.jpg

是:

根据这些坐标被读取的二维纹理

Mix

是:

根据你的雪/坡度 Mask 决定使用哪一种纹理结果

Displacement

是:

把最终的灰度信息转换成真实的表面高度变化

所以整个过程其实就是:

Mountain → 产生坐标 → 坐标经过调整 → 用坐标读取 Rocks.jpg → 图片产生高度信息 → 高度信息让 Mountain 表面产生凹凸。


一个特别重要的记忆方法

以后看到:

Texture Coordinate → Generated

你就直接在脑子里翻译成:

“以当前这个材质所附着的对象为基础,Blender 自动给它建立一个 0~1 的三维坐标盒。”

在你这个案例里:

当前对象 = Mountain

所以答案非常明确:

Generated 的“物体”就是 Mountain,不是 Rocks.jpg。

Rocks.jpg 只是利用这套坐标,被“铺”到 Mountain 表面上。

 

 

请帮我理解Displacement节点中的scale参数。

 

当然可以。你这个雪山材质里 Displacement 节点的 Scale 非常值得单独理解,因为它决定了 Rocks.jpg 最终让山体表面“凹凸多少”。

你截图中的设置是:

  • HeightMix 的 Result
  • Midlevel = 0.500
  • Scale = 0.010

可以先记住一句话:

Scale 决定 Height 输入的灰度变化,最终转换成多大的实际位移距离。


1. 先理解 Height 是什么

你的 Rocks.jpg 是一张图片。

假设图片里有三个区域:

 
黑色        灰色        白色
  ↓           ↓           ↓
0.0         0.5         1.0
 

当它连接到:

Displacement → Height

时,Blender 会把图片的明暗理解成:

不同的高度。

可以想象成:

 
白色
  ▲
  │        /\      /\
  │       /  \____/  \
  │______/            \____
  │
黑色
 

所以 Height 本质上是在告诉 Displacement:

“这里应该高一点,那里应该低一点。”


2. Midlevel = 0.5 是什么意思?

这个参数特别重要。

你的:

Midlevel = 0.500

可以理解成:

把灰度 0.5 定义为“原来的表面位置”。

例如:

 
Height = 0.0
        ↓
       向下

Height = 0.5
        ↓
       不动

Height = 1.0
        ↓
       向上
 

因此:

 
             白色 1.0
               ↑
               │
               │ 向外凸
               │
───────────────┼─────────────── 原始表面
               │
               │
               │ 向内凹
               ↓
             黑色 0.0
 

所以当:

Midlevel = 0.5

时:

  • 黑色 → 负方向位移
  • 灰色 → 基本不位移
  • 白色 → 正方向位移

3. 那么 Scale 是什么?

现在进入重点。

假设:

Scale = 0.01

那么可以简单理解成:

把 Height 产生的位移范围控制在大约 0.01m 这个量级。

也就是大约:

1 cm

所以:

 
Scale = 0.01
 

意味着你的 Rocks.jpg 所产生的凹凸高度比较小。


4. 用你的雪山来理解

假设某个像素:

Rocks.jpg 黑色

 
Height = 0
 

相对于:

 
Midlevel = 0.5
 

它处于:

 
0 - 0.5 = -0.5
 

于是向内位移。


Rocks.jpg 灰色

 
Height = 0.5
 

那么:

 
0.5 - 0.5 = 0
 

基本不动。


Rocks.jpg 白色

 
Height = 1
 

那么:

 
1 - 0.5 = +0.5
 

向外位移。

而最终位移量受到:

Scale = 0.01

控制。


5. 为什么 Scale 越大,岩石越“凹凸不平”?

例如你保持:

Midlevel = 0.5

只修改 Scale。

Scale = 0.001

 
非常轻微的凹凸
 

大约是毫米级效果。


Scale = 0.01

 
明显的岩石表面细节
 

约厘米级量级。


Scale = 0.1

 
非常明显
 

约分米级量级。


Scale = 1.0

 
巨大起伏
 

已经不是“岩石纹理”,而可能变成真正的地形起伏。

所以:

Scale 越大,Height 图片对几何表面的影响越强。


6. 为什么你的教程使用 0.010?

结合你的 Mountain:

Z Size = 308m

如果 Rocks.jpg 是用来表现:

岩石表面的小尺度细节

那么:

0.01m = 1cm

其实是比较合理的思路。

因为:

 
Mountain
高度 ≈ 308m
       │
       │
       │
       │
       │
岩石纹理
   ↕
  1cm
 

也就是说:

山体的整体起伏是几百米,而 Rocks.jpg 只负责厘米级的表面细节。

这是典型的多尺度建模思想。


7. 这也解释了为什么要使用 Displacement

你可能会问:

为什么不直接把 Rocks.jpg 接到 Bump?

这是一个很好的问题。

两者都可以产生“凹凸感”,但是原理不同。

Bump

主要是:

改变表面的法线,让光照看起来像有凹凸。

实际上几何体并没有真的变形。


Displacement

则是:

真正移动几何体的表面。

所以:

 
Bump
Rocks.jpg
   ↓
改变 Normal
   ↓
看起来凹凸
 

而:

 
Displacement
Rocks.jpg
   ↓
改变几何位置
   ↓
真的凹凸
 

8. 一个非常直观的实验

你现在这个雪山文件可以直接做这个实验。

先保存一份。

然后把:

Scale = 0.010

改成:

Scale = 0.1

然后渲染。

你会看到岩石表面的起伏明显增强。

再改成:

Scale = 1.0

如果你的几何细分和渲染设置允许,你会发现:

Rocks.jpg 已经不再只是“纹理”,而开始影响山体的宏观形状。

然后再改回:

0.010

你就会非常直观地理解 Scale 的作用。


9. 但是这里有一个非常重要的限制

Displacement 并不是“Scale 越大越好”。

它受到模型几何细分程度的限制。

比如你的 Mountain 如果只有很少的顶点:

 
●────────●
│        │
│        │
●────────●
 

你给它一个非常复杂的 Rocks.jpg:

 
/\/\/\/\/\/\/\/\/\/\/
 

但是模型没有足够的几何顶点,那么 Blender 没办法把图片中的每一个细节真正变成几何形状。

所以可能出现:

图片非常精细,但 Displacement 看起来很粗糙。


10. 这也是为什么你这个 ANT Landscape 雪山比较适合做 Displacement

ANT Landscape 本身生成的地形通常有比较多的网格细分。

所以:

 
Mountain
  ↓
大量顶点
  ↓
Rocks.jpg
  ↓
Displacement
  ↓
岩石细节
 

效果会比较明显。

但是如果你创建一个只有几十个面的 Plane:

 
Plane
4个顶点
   ↓
Rocks.jpg
   ↓
Displacement
 

基本无法表现复杂的岩石纹理。


11. Scale 和 Rocks.jpg 的黑白对比还有一个容易忽略的关系

假设:

Scale = 0.01

而 Rocks.jpg 是:

 
黑       灰       白
0.0      0.5      1.0
 

以 Midlevel=0.5 为中心:

 
           +0.005m
              ↑
              │
白 1.0 ───────┤
              │
灰 0.5 ───────●──── 原始表面
              │
黑 0.0 ───────┤
              │
              ↓
           -0.005m
 

因此你可以粗略理解为:

Scale = 0.01

对应:

从中间基准面向两边扩展约 ±0.005m。

总的黑白极值高度差约:

0.01m = 1cm

这也是为什么我说 Scale 可以理解成“位移幅度”。


12. 所以你的节点可以这样理解

你现在的:

 
Rocks.jpg
    ↓
黑白灰
    ↓
Mix
    ↓
Height
    ↓
Displacement
    │
    ├── Midlevel = 0.5
    │       ↓
    │   确定“基准面”
    │
    └── Scale = 0.01
            ↓
        确定位移幅度
 

最终就是:

Rocks.jpg 告诉 Blender“哪里高、哪里低”,Midlevel 告诉 Blender“哪个灰度是基准”,Scale 告诉 Blender“高低变化到底有多大”。


13. 一个特别好记的比喻

你可以把 Displacement 想象成一块软橡皮泥

Height

告诉你:

哪里按下去、哪里拉起来。

Midlevel

告诉你:

什么位置算原来的表面。

Scale

告诉你:

你到底要把橡皮泥拉/按多深。

所以:

Height = 形状信息

Midlevel = 基准位置

Scale = 强度/高度


对你这个雪山案例,最终可以记成:

Normal Z + ColorRamp

→ 决定哪里是雪、哪里是岩石

Rocks.jpg

→ 提供岩石纹理的凹凸信息

Displacement Midlevel

→ 确定凹凸的中心基准

Displacement Scale

→ 确定凹凸有多深/多高

而你现在的:

Scale = 0.010

就是在告诉 Blender:

“Rocks.jpg 的黑白变化,只允许造成大约厘米级的表面起伏,不要把这座 308 米高的山直接变成一团巨大的波浪。”

 

posted on 2026-09-06 13:53  ZhangZhihuiAAA  阅读(6)  评论(0)    收藏  举报