数学可视化(03)——函数可视化

  1. 1. 更新

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 全象限
uv.y = 1.0 - uv.y;
uv = uv * 2 - 1;
// (-5,5)
const int uvScale = 5;
uv = uv * uvScale;
// 绘制坐标轴
half axis = smoothstep(0.01, 0.0, abs(uv.y)) + smoothstep(0.01, 0.0, abs(uv.x)); // 绘制 y=0 x=0
// 绘制坐标网格
half mesh = smoothstep(0.01, -0.01, abs((uv.y - 1) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.y + 1) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.y - 2) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.y + 2) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.y - 3) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.y + 3) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.y - 4) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.y + 4) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.x - 1) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.x + 1) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.x - 2) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.x + 2) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.x - 3) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.x + 3) / uvScale))
+ smoothstep(0.01, -0.01, abs((uv.x - 4) / uvScale)) + smoothstep(0.01, -0.01, abs((uv.x + 4) / uvScale));

// 绘制函数 y = x^5
half func = uv.y - pow(uv.x, 5);
// 绘制
half plot = smoothstep(lerp(0.001, 0.02, length(uv)), 0.0, abs(func / uvScale));
return half3(axis + mesh, axis + mesh, axis + mesh) + half3(0, plot, 0);

  • 绘制坐标轴的前半段代码,相当于绘制y = 0的函数,相当于abs(function = 0)

1
2
// sin(y^2) = sin(x^2)
half func = sin(pow(uv.y, 2)) - sin(pow(uv.x, 2));

更新

  • 代码优化
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
Shader "Unlit/FunctionGraph"
{
Properties
{
[HideInInspector] _MainTex ("Texture", 2D) = "white" {}
_UV_Scale ("UV Scale", Range(0, 20)) = 3.3
_Color_BG ("Color_BG", Color) = (1,1,1,1)
_Color_Axis ("Color_Axis", Color) = (1,0,0,1)
_Color_Func ("Color_Func", Color) = (0.3,0,1,1)
_Color_Mesh ("Color_Mesh", Color) = (0,0,0,1)
_Size_Func ("Size_Func", Range(2, 32)) = 16
_Size_Mesh ("Size_Mesh", Range(1, 5)) = 1
_Size_Axis ("Size_Axis", Range(1, 5)) = 1.6
}
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha

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;
};

sampler2D _MainTex;
float4 _MainTex_ST;
float _UV_Scale;
float4 _Color_BG;
float4 _Color_Axis;
float4 _Color_Func;
float4 _Color_Mesh;
float _Size_Func;
float _Size_Mesh;
float _Size_Axis;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}

float fwidth (float v)
{
return abs(ddx(v)) + abs(ddy(v));
}
float func(float x)
{
return sin(x) * cos(x) + pow(x, 3) - 2 * x;//pow(x, 5);
}
float plotFunc(float2 uv)
{
float f = func(uv.x);
return smoothstep(f - 0.0001, f + 0.0001, uv.y);
}

fixed4 frag (v2f i) : SV_Target
{
// 背景色
fixed4 col = _Color_BG;
// 全象限
i.uv = i.uv * 2 - 1;
// 缩放
i.uv *= _UV_Scale;
// 绘制网格
float mesh = abs(frac(i.uv.x)) < fwidth(i.uv.x) * _Size_Mesh || abs(frac(i.uv.y)) < fwidth(i.uv.y) * _Size_Mesh;
// 绘制坐标轴
float axis = abs(i.uv.y) < fwidth(i.uv.y) * _Size_Axis || abs(i.uv.x) < fwidth(i.uv.x) * _Size_Axis;
// 绘制函数图像
float count = 0;
const int AA = 4;
for (int m = 0; m < AA; m++)
{
for (int n = 0; n < AA; n++)
{
float2 offset = (float2(m, n) - 0.5 * AA) / AA * 2.0;
count += plotFunc(i.uv + offset / _Size_Func);
}
}
if (count > AA * AA * 1.0 / 2.0)
{
count = AA * AA * 1.0 - count;
}
count = count * 2.0 / (AA * AA * 1.0);
// 混合
col = lerp(col, _Color_Mesh, mesh);
col = lerp(col, _Color_Axis, axis);
col = lerp(col, _Color_Func, count);
return col;
}
ENDCG
}
}
}