Shader实现棋盘效果

这篇博客介绍了如何使用Shader在Unity中实现两种棋盘效果:黑白棋盘和裁剪棋盘。关键在于运用floor()函数和frac()函数对屏幕坐标进行处理,通过改变网格大小和奇偶判断来创建交错的棋盘图案。透明棋盘利用clip()指令裁剪像素,而黑白棋盘则通过checker的值决定颜色。

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.10.251
在这里插入图片描述在这里插入图片描述在这里插入图片描述

而第一行在使用完 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

如有理解错误的地方,欢迎批评指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨亦妖_JRegn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值