前言

出去旅行了一周多,回来继续干活了 ✊
云南的自然风光真是爽心悦目,坐到我小小的桌前倒有些不习惯了哈哈。


效果

按照指定的混合程度图混合草地和岩石,地皮按照世界空间铺设

👉展示备份(国内节点)
👇效果展示 (科学上网)


代码

附件:贴图
链接:https://pan.baidu.com/s/1_BS-VJculY-L3sKWgTtYAg
提取码:6ue3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
Shader "Unlit/AloeaShader05"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {} // 材质1,草皮用
_Rock ("Texture", 2D) = "white" {} // 材质2,岩石用
_Pattern ("Texture", 2D) = "grey" {} // 材质3,混合程度
}

SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos: TEXCOORD1;
};

sampler2D _MainTex;
sampler2D _Rock;
sampler2D _Pattern;

v2f vert (appdata v)
{
v2f o;
// 转换为世界坐标
o.worldPos = mul( UNITY_MATRIX_M, v.vertex);

// 本地空间转化为相机的剪辑空间
o.vertex = UnityObjectToClipPos(v.vertex);

o.uv = v.uv;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
// 材质按照世界坐标xz表
float2 topDownProjection =i.worldPos.xz;
fixed4 moss = tex2D(_MainTex, topDownProjection);
fixed4 rock = tex2D(_Rock, topDownProjection);
// 混合 Alpha
float pattern = tex2D(_Pattern, topDownProjection);
float4 finalColor = lerp(moss, rock, pattern);

return finalColor;
}
ENDCG
}
}
}

这个案例混合部分的知识点和 练习1 是一样的,用到 lerp 函数混合,不同的是练习1是传入是色彩,这里是材质。

地皮采用世界坐标花了点时间,关键点需要 1. 得到绝对的世界坐标;2. 将材质匹配倒世界坐标。

1
2
1. o.worldPos = mul( UNITY_MATRIX_M, v.vertex);
2. fixed4 moss = tex2D(_MainTex, i.worldPos.xz);

知识点

材质基础

从本质上来说,材质就是一张贴图、一张图片。但从表现来说,我们除了把材质当作贴图,比如这个练习中的草皮和岩石,我们也可以用材质表达混合程度、法线方向、位移程度。总之,我们需要理解图片中表达的色彩的本质是数字,数字可以用到处理任何事情。

材质有几个基本属性

  1. 分辨率:纹理的像素数,通常以宽度和高度表示。
  2. 格式:纹理存储像素数据的方式,如 RGB、RGBA、ARGB、DXT 等。
  3. 过滤模式:指定纹理在放大或缩小时如何进行插值计算,常见的有点采样、双线性插值、三线性插值等。
  4. 包裹模式:指定纹理坐标超出 [0,1] 范围时如何处理,常见的有重复、镜像、夹取等。
  5. Mipmap:一组预先计算的纹理级别,用于在不同距离和角度下呈现更好的纹理效果。
  6. 压缩:将纹理数据压缩以减小内存占用和提高渲染性能,常见的有 DXT、PVRTC、ETC 等格式。
  7. 纹理类型:指定纹理用于什么目的,如 Albedo(漫反射)、Normal(法线)、Metallic(金属度)、Emission(自发光)等。

先要有个大致的了解,每一块再之后的练习中再展开聊聊。


处理坐标转化

untiy shaderlab 中有一系列引擎定义的内置变量供使用,包括我们之前用到的 _Time ,还有这次练习中用到的 UNITY_MATRIX_M 。这个练习中使用 unity_ObjectToWorld 替换也是一样的。
实现上,将当前的顶点乘以(mul)变化矩阵得到目标信息。

变量 含义
unity_ObjectToWorld 一个 4x4 的矩阵,表示从对象空间到世界空间的变换矩阵。它包含了物体的旋转、缩放和平移信息,可以将对象空间中的顶点坐标转换为世界空间中的顶点坐标。
UNITY_MATRIX_M 一个 3x4 的矩阵,表示从对象空间到视图空间的变换矩阵。它只包含了物体的旋转和平移信息,不包括缩放信息,可以将对象空间中的顶点坐标转换为视图空间中的顶点坐标。

文档: https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html