ShaderToy奇巧:液晶显示逻辑

在浏览ShaderToy上的无限图书馆的过程中,我发现对于图书馆的每一层,都会有相应的编号:

我想看看它是怎么实现的,结果发现代码没啥注释,而且几个无限图书馆的代码都一模一样,你抄我我抄你。最重要的是还有bug,没办法只能自己分析然后改好了。
找到最后有个核心函数ShowDig,传入2D坐标,和要显示的0-9数字,就能返回是否在显示范围内。跟电梯液晶屏一样。如果要显示数字8,大概是这样子:

由于在着色范围内的点都返回1,于是就可以用于着色判断了:
会显示一个绿色的8。
那我们来看这个神奇的函数是怎么实现的:
经过分析,DigSeg用来画液晶的小长方块,DSG表示如果当前k为奇数,就画当前小块。
ShowDig中,vp,vm,vo分别是液晶中心点到各个小长方块中心点的偏移,由于对称关系,所以只需要写3个。
于是关键来了,k是什么,从0-9对应的那些magic number:119,36,93...又是什么。
由DSG想到辗转相除法,想到二进制。测试了一下,没错了。
以数字1为例,它对应36,36辗转相除,也就是2进制转换为100100

由于液晶屏上只有7个小块,所以我们补齐为0100100,如果用自然数,从高位开始数,那么意思是2,5号块需要显示。根据倒数2,3行DSG代码内容,可以得到液晶小块的顺序关系如上图黄色所示,那么2,5号亮起,的确是数字1的样子。
额外的,如果传入-1,用4号块亮起,当作负数的符号。
至此,我们能显示单个数字0-9和负号了。
由于shadertoy上的函数有问题,所以我只能写点逻辑,显示十进制数:
测试成功:

利用类似的逻辑,我们不仅可以设计液晶屏,还可以设计点阵,画一些ASCII符号:

分析起来简单,但是实际自己要做,对于我来说不是很容易,因为没有”那种“思维。也许我应该多玩玩《SHENZHEN IO》
