Shader实现棋盘效果
效果如下,分两种,一种是黑白棋盘,一种是通过裁剪实现的棋盘效果。
黑白棋盘

通过裁剪的棋盘效果

具体实现代码(参考自Unity官方中文手册 )
Shader "..."
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
// 注意:此结构中没有 SV_POSITION
struct v2f {
float2 uv : TEXCOORD0;
};
v2f vert (
float4 vertex : POSITION, // 顶点位置输入
float2 uv : TEXCOORD0, // 纹理坐标输入
out float4 outpos : SV_POSITION // 裁剪空间位置输出
)
{
v2f o;
o.uv = uv;
outpos = UnityObjectToClipPos(vertex);
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target
{
// screenPos.xy 将包含像素整数坐标。
screenPos.xy = floor(screenPos.xy * 0.25) * 0.5;
// floor函数为“向下取整”
float checker = -frac(screenPos.r + screenPos.g);
// frac函数返回标量或每个矢量中各分量的小数部分。
// 如果值为负,则 clip HLSL 指令停止渲染像素
clip(checker);
// 对于保留的像素,读取纹理并将其输出
fixed4 c = tex2D (_MainTex, i.uv);
return c;
}
ENDCG
}
}
}
//而对于黑白棋盘,则将
float checker = -frac(screenPos.r + screenPos.g);
clip(checker);
fixed4 c = tex2D (_MainTex, i.uv);
return c;
//改为
float checker = frac(screenPos.r + screenPos.g);
return checker*2;
解析
上面最关键的部分便是:
screenPos.xy = floor(screenPos.xy * 0.25) * 0.5;
float checker = -frac(screenPos.r + screenPos.g);
首先看第一行,
利用 floor() 函数将屏幕坐标下的任意点都处理成等于该点所处的网格下的左下角的点的坐标。
即,点(0.37, 0.55),使用floor函数后变为(0, 0);点(1.77, 0.21),使用floor函数后变为(1, 0);
而乘以0.25则是将原本网格的范围扩大,如图

反之同理,如果将0.25缩小为0.1,则网格大小更大。
| 0.1 | 0.25 | 1 |
|---|---|---|
![]() | ![]() | ![]() |
而第一行在使用完 floor() 函数后,又乘了0.5,这一步是为了进行奇偶区分。
因为经过 floor() 函数计算后,得到只能是整数,而得到的整数经过除2,再利用 frac() 函数去取小数,最终只有两种结果——0和0.5
如果之前的整数是偶数则为0,奇数则为0.5
这样一来,便可形成交错的棋盘网格。
而透明棋盘与黑白棋盘的区别则是最后对checker的变化。
透明棋盘利用了clip(number)指令中如果‘number’是负值,则不进行clip/裁剪
float checker = -frac(screenPos.r + screenPos.g);这样一来,得到结果为偶数的那些像素点将被裁剪,而奇数的那些则不被裁剪。
黑白棋盘则是直接将checker的值乘2返回,因为乘2后,checker的值只有0和1两种,分别对应黑色(0,0,0,0)和白色(1,1,1,1)
float checker = frac(screenPos.r + screenPos.g); return checker*2;
本文参考自Unity官方中文手册 与 https://zhuanlan.zhihu.com/p/49165180
如有理解错误的地方,欢迎批评指出。
这篇博客介绍了如何使用Shader在Unity中实现两种棋盘效果:黑白棋盘和裁剪棋盘。关键在于运用floor()函数和frac()函数对屏幕坐标进行处理,通过改变网格大小和奇偶判断来创建交错的棋盘图案。透明棋盘利用clip()指令裁剪像素,而黑白棋盘则通过checker的值决定颜色。




3211

被折叠的 条评论
为什么被折叠?



