庄懂技美课的shader复现2

Lec5

做一下三ambient。直接莽就行~

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
Shader "ZhuangDong/Lec5/TripleAmbient"
{
Properties
{
}
SubShader
{
Pass {
CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"

struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};

v2f vert(appdata_base v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}

fixed4 frag(v2f i) : SV_TARGET {
float3 worldNorm = normalize(i.worldNormal);
fixed3 colorUp = unity_AmbientSky;
fixed3 colorPara = unity_AmbientEquator;
fixed3 colorDown = unity_AmbientGround;
fixed3 upNorm = max(worldNorm.y, 0);
fixed3 downNorm = max(-worldNorm.y, 0);
fixed3 paraNorm = 1 - upNorm - downNorm;
fixed3 color = colorUp * upNorm + colorPara * paraNorm + colorDown * downNorm;
return fixed4(color, 0);
}

ENDCG
}


}
FallBack "Diffuse"
}

Lec6

一、散乱分布高光

遇到了一些奇奇怪怪的问题,基本思路就是xjb采样噪声纹理。

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 "ZhuangDong/Lec6/MultipleGrapes"
{
Properties
{
_DiffuseColor ("Diffuse Color", Color) = (1,1,1,1)
_NoiseTex ("Noise Texture", 2D) = "white" {}
_SpecMaxRange ("Specular Range Max", Range (1, 200)) = 20
_AmbientStength ("Ambient Strength", Float) = .1
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNorm : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};

sampler2D _NoiseTex;
float4 _NoiseTex_ST;
float _AmbientStength;
fixed4 _DiffuseColor;
float _SpecMaxRange;

v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _NoiseTex);
o.worldNorm = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
float3 worldNorm = normalize(i.worldNorm);
fixed3 colorUp = unity_AmbientSky;
fixed3 colorPara = unity_AmbientEquator;
fixed3 colorDown = unity_AmbientGround;
fixed3 upNorm = max(worldNorm.y, 0);
fixed3 downNorm = max(-worldNorm.y, 0);
fixed3 paraNorm = 1 - upNorm - downNorm;
fixed3 ambient = colorUp * upNorm + colorPara * paraNorm + colorDown * downNorm;
ambient = ambient * _AmbientStength;
float3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
float3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 texRGB = tex2D(_NoiseTex, i.uv);
float3 diffuse = max(dot(worldNorm, lightDir), 0) * _DiffuseColor * texRGB;
float3 halfDir = normalize(lightDir + viewDir);
float specAmount = tex2D(_NoiseTex, viewDir.xz).r * _SpecMaxRange;
float3 specular = pow(max(dot(halfDir, worldNorm), 0), specAmount);
fixed3 col = saturate(ambient + diffuse + specular);
return fixed4(col, 1.0);
}
ENDCG
}
}
}

二、铁锈

基本思想就是根据噪声采样。先得到采样结果:

1
fixed3 texRGB = tex2D(_NoiseTex, i.uv);

然后根据某个范围_RustRange对texRGB的R通道进行step

1
fixed texRC = step(_RustRange, texRGB.r);

再进行lerp

1
diffuse *= lerp(ironColor, _RustColor, texRC);

就做完了。完整的shader:

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 "ZhuangDong/Lec6/IronRust"
{
Properties
{
_IronColor ("Diffuse Color", Color) = (1,1,1,1)
_RustColor ("Rust Color", Color) = (1,1,1,1)
_NoiseTex ("Noise Texture", 2D) = "white" {}
_SpecMaxRange ("Specular Range Max", Range (1, 200)) = 20
_RustRange ("Rust Range", Range(0,1)) = .4
_FresnelPow ("Fresenel Power", Float) = 3.0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNorm : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};

sampler2D _NoiseTex;
float4 _NoiseTex_ST;
fixed4 _IronColor;
fixed4 _RustColor;
float _SpecMaxRange;
float _RustRange;
float _FresnelPow;

v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _NoiseTex);
o.worldNorm = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
float3 worldNorm = normalize(i.worldNorm);
float3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
float3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 texRGB = tex2D(_NoiseTex, i.uv);
float3 diffuse = dot(worldNorm, lightDir) * .5 + .5;
fixed texRC = step(_RustRange, texRGB.r);
float3 halfDir = normalize(lightDir + viewDir);
float specAmount = tex2D(_NoiseTex, viewDir.xz).r * _SpecMaxRange;
float3 specular = pow(max(dot(halfDir, worldNorm), 0), specAmount);
float3 ironColor = _IronColor + specular;
diffuse *= lerp(ironColor, _RustColor, texRC);
fixed3 col = saturate(diffuse);
fixed fresnel = pow(1-dot(viewDir, worldNorm), _FresnelPow);
col = lerp(col, fixed3(1.0,1.0,1.0), fresnel);
return fixed4(col, 1.0);
}
ENDCG
}
}
}

三、Shader Forge的叠加

对其讨论,我们都取颜色是$A, B$

(1)变暗系

Darken:取每个分量的较小值
$$
C=\min(A,B)
$$

1
saturate(min(float4(Color1),float4(Color2))).rgb

Multiply:不用说,直接乘起来,雅名正片叠底
$$
C=AB
$$

1
saturate((_Color1.rgb*_Color2.rgb))

Colorburn:颜色加深
$$
C = A - \frac{\overline{A}\cdot \overline{B}}{B} = 1-\frac{1-A}{B}
$$
效果上是颜色距离$.5$越大的点,偏离就越远,此时可能产生大量溢出。

1
saturate((1.0-((1.0-_Color2.rgb)/_Color1.rgb)))
image-20210801143347800

Linearburn:线性加深
$$
C=A+B-1
$$

1
saturate((_Color1.rgb+_Color2.rgb-1.0))

(2)变亮系

Lighten:变亮
$$
C=\max(A,B)
$$

1
saturate(max(_Color1.rgb,_Color2.rgb))

Screen:滤色
$$
C=1-(1-A)(1-B)
$$
绿色的作用是,原来比较暗的部分会变量。这个比较常用,我们举个例子,假设B是$(.5,.5,.5)$,那么$C=1-0.5(1-A)=0.5+0.5A$,也就是把$A$的范围扩张到了$(0.5,1)$。因此,滤色常用于增加亮度。

其实从另一个层面来说,Screen和Multiply正好是对偶的。

1
saturate((1.0-(1.0-_Color1.rgb)*(1.0-_Color2.rgb)))
image-20210801144258965

Color Dodge:颜色减淡
$$
C = \frac{1-A}{B}
$$

1
saturate((_Color2.rgb/(1.0-_Color1.rgb)))

按照颜色1的三个通道,颜色2的通道都一定程度上的变大。一个极端是Color1为白色,那么Color2发生严重的溢出。结果和Color Burn互补。

Linear Dodge:就是Add,线性减淡
$$
C=A+B
$$

1
saturate((_Color1.rgb+_Color2.rgb))

(3)综合系

Overlay:叠加
$$
C=\begin{cases}2AB&B\le0.5\1-(1-2(B-.5)(1-A))&B>0.5\end{cases}
$$
把两种东西综合,比较亮的部分让它更亮,比较暗的地方让它更暗。但是这里起决定作用的是B,所以黑白的区分比较明显。

1
saturate(( _Color2.rgb > 0.5 ? (1.0-(1.0-2.0*(_Color2.rgb-0.5))*(1.0-_Color1.rgb)) : (2.0*_Color2.rgb*_Color1.rgb) ))

Hard Light:强光
$$
C=\begin{cases}2AB&B\le0.5\1-(1-2(A-.5)(1-B))&B>0.5\end{cases}
$$
其中$x$是B的$x$值。把两种东西综合,比较亮的部分让它更亮,比较暗的地方让它更暗。但这里起决定作用的是A,所以整体效果是变亮。相当于A这束强光打到了B上,发生一系列作用。

1
saturate(( _Color2.rgb > 0.5 ? (1.0-(1.0-2.0*(_Color1.rgb-0.5))*(1.0-_Color2.rgb)) : (2.0*_Color2.rgb*_Color1.rgb) ))

Vivid Light:亮光
$$
C=\begin{cases}\dfrac{B}{2(1-A)}&B>0.5\1-\dfrac{1-B}{2A}&B\le 0.5\end{cases}
$$
会让饱和度很大幅度的增大.可以看成颜色加深和颜色减淡的组合。

1
saturate(( _Color1.rgb > 0.5 ? (_Color2.rgb/((1.0-_Color1.rgb)*2.0)) : (1.0-(((1.0-_Color2.rgb)*0.5)/_Color1.rgb))));

Linear Light:线性光
$$
C=2A+B-1
$$
它原本是对$A$大小进行讨论的。当$x>0.5$,它会增加亮度;否则会减小亮度。但二者公式是统一的,因为$2A-1$的正负恰好以$A$为分水岭。可以看成线性加深和线性减淡的组合。

1
saturate(( _Color1.rgb > 0.5 ? (_Color2.rgb + 2.0*_Color1.rgb -1.0) : (_Color2.rgb + 2.0*(_Color1.rgb-0.5))))

Pin Light:点光
$$
C=\begin{cases}\max(2A-1,B)&A>0.5\\min(2A, B)& A\le 0.5\end{cases}
$$
效果上,仍然是中间部分被替换了。感觉没什么用。

1
saturate(( _Color2.rgb > 0.5 ? max(_Color1.rgb,2.0*(_Color2.rgb-0.5)) : min(_Color1.rgb,2.0*_Color2.rgb) ));

Hard Mix:实色混合
$$
C=\left[\dfrac{A+B}{2}\right]
$$
其中$[x]$表示$\operatorname{Round}(x)$。会将相加结果变得非常硬。

1
saturate(round( 0.5*(_Color2.rgb + _Color1.rgb)))

(4)差系

Difference:差值
$$
C=|A-B|
$$
用来找差异,一般写shader妹人会把它当成混合模式。

1
saturate(abs(_Color2.rgb-_Color1.rgb))

Exclusion:排除
$$
C=\frac{1-(2A-1)(2B-1)}{2}
$$
没差值模式那么激进,效果比较类似。

1
saturate((0.5 - 2.0*(_Color2.rgb-0.5)*(_Color1.rgb-0.5)))

Substract:相减
$$
C=A-B
$$
…相煎何太急

1
saturate((_Color2.rgb-_Color1.rgb))

Divide:相除
$$
C=\frac{A}{B}
$$

1
saturate((_Color2.rgb/_Color1.rgb))

用基色进行划分。如果$A\ge B$,会划分出白色,否则让颜色变暗。

Author

LittleRewriter

Posted on

2021-08-03

Updated on

2021-12-02

Licensed under

Comments