本节教程为南京字节工坊原创文章,转载请留此信息:https://blog.csdn.net/gcj2450/article/details/104523738
南京字节工坊,专业从事各类互动软件定制开发,三维可视化应用开发定制,VR,AR类互动应用定制开发。
今天我们来学习通过Unity Shader实现数学直角坐标系的Shader,以让大家更加熟悉Unity Shader中常用的数学方法。数学坐标系由XY轴,XY轴方向的箭头以及单位网格构成。最终效果如下图
第一步我们使用基本的数学方法来绘制方格。在Unity中新建一个Unlit Shader。删除_MainTexture属性及相关的变量,定义网格shader所需的属性。属性定义如下所示
Properties
{
//背景色
_BgColor("BgColor",color)=(1,1,1,1)
//十分线颜色
_LinesColor("LinesColor",color) = (0.7, 0.7, 0.7,1.0)
//次级线颜色
_SubLinesColor("SubLinesColor",color)=(0.95, 0.95, 0.95,1.0)
//缩放
_Scale("Scale",range(1,100)) = 10
_Subdiv("Subdiv",range(1,10)) = 10
}
这里的属性分别是背景色,十分线颜色,次级线的颜色,缩放值和最小刻度细分值。
在Fragment Shader中输入如下代码
vec2 pos = i.uv;
定义一个pos变量,并将其缩放。
pos *= _Scale;
通过取余运算,得到重复的值,加入_Scale=10,将在0-1之间重复10次
pos=frac(pos);
vec4 fragColor = _BgColor;
通过step方法,返回左下角的值,这里step方法,相当于if判断,
step(a, x) | Returns (x >= a) ? 1 : 0 |
vec2 bl = step(0.01,pos); // 左下
vec2 tr = step(0.01,1.0-pos); // 右上
将上面两次运算的结果相乘,就会得到全部>0的位置
float alpha =bl.x * bl.y * tr.x * tr.y;
再通过mix方法,混合线的颜色和基础色。
fragColor = mix(fragColor, _LinesColor, 1-alpha);
将pos放大Subdiv倍,重复上面运算,得到十分位刻度的方格
vec2 bl2 = step(0.01,frac(pos*_Subdiv)); // 左下
vec2 tr2 = step(0.01,1.0-frac(pos*_Subdiv)); // 右上
float alpha2 =bl2.x * bl2.y * tr2.x * tr2.y;
fragColor = mix(fragColor, _SubLinesColor, 1-alpha2);
返回最终颜色。
return fragColor;
得到的最终上述效果完成后,得到最终效果如下:下图_Scale=2,_Subdive=5
完整代码如下:
Shader "Unlit/StepGrid"
{
Properties
{
//背景色
_BgColor("BgColor",color)=(1,1,1,1)
//十分线颜色
_LinesColor("LinesColor",color) = (0.7, 0.7, 0.7,1.0)
//次级线颜色
_SubLinesColor("SubLinesColor",color)=(0.95, 0.95, 0.95,1.0)
//缩放
_Scale("Scale",range(1,100)) = 10
_Subdiv("Subdiv",range(1,10)) = 10
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define vec2 half2
#define vec3 half3
#define vec4 half4
#define mix lerp
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
float _Scale;
float _Subdiv;
fixed4 _BgColor;
fixed4 _LinesColor;
fixed4 _SubLinesColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
vec2 pos = i.uv;
pos *= _Scale;
pos=frac(pos);
vec4 fragColor = _BgColor;
vec2 bl = step(0.01,pos); // 左下
vec2 tr = step(0.01,1.0-pos); // 右上
float alpha =bl.x * bl.y * tr.x * tr.y;
fragColor = mix(fragColor, _LinesColor, 1-alpha);
vec2 bl2 = step(0.01,frac(pos*_Subdiv)); // 左下
vec2 tr2 = step(0.01,1.0-frac(pos*_Subdiv)); // 右上
float alpha2 =bl2.x * bl2.y * tr2.x * tr2.y;
fragColor = mix(fragColor, _SubLinesColor, 1-alpha2);
return fragColor;
}
ENDCG
}
}
}
通过上面的简单Shader,实现了一个基本的带十分刻度网格的Shader。下一节我们将继续对其进行优化。