element3ds.com
TA-Shader Shader 实现取色器
发布于
2018-5-7
2300
11

您需要 登录 才可以下载或查看,没有账号?注册

x
33885af025d112a61.png

教程不是源码,不是只上源码,涵盖作者的分析思路 。

首先,我认真分析了它颜色的分布规则,发现了一个很有趣的规律 :

作者手稿,勿喷:
318285af0261315c77.png

这样的分配,大概每一部就是RGB三色其中的一个在变化,而且变化规律也就像右边写的。

那么这样就总结出一个规律,我画了一张图:


大概按刚刚那样的分组,一次加减为一组,一共分了三组。横坐标就是UV的x值了

纵坐标看起来有点矮,其实应该都是从 0 到 1 的 。

那么,我们就想道了,分别实现一个变化曲线,来控制RGB三个颜色的变化:

拿绿色的举例:


在 1/6 处上升为 1 , 并保持 到 3/6 ,然后再减到 1 此时是 4/6 。



其他的同理啦,就是一个平移变化嘛 。



第二步,构造这个函数图像的表达式 :

打开一个在线网页,就是来画函数图像的:


好,那怎么构造呢 ?

首先我们想要一个锯齿装的图像,基本思路就是 取模和取绝对值混用。

我为了得到1/6这个点 , 那就取6的倍数了:

y = mod(6x , 6 )
   = 6*x % 6 :
得到图像:


显然还不够,我想把他做成那种左右对称的锯齿状,如果现在直接abs的化,是没有效果的,所以之前要先向下平移3个单位:

y = mod(6x , 6 )  - 3
   = 6*x % 6 - 3 :

然后对他abs:


大概效果已经差不多了,但是取值范围这些还没有确定,我们还得修改:

如果我们放大一下图像就会看到:


在 0 - 1 的范围内是这样的,而我们之前的想法是 在1/6 到 3/6 保持不变的,那么也就是 1/3的范围 , 我们怎么找这样一个范围 ?

看到这个图像我想到了,直接向下平移一些距离,使得 x1 + 1/3 = x2

那么我们就解这个方程:

设 x1, x2
且 x1 + 1/3  =  x2
且 f(x1 ) = f(x2)
f(x) = 6*x % 6 - 3
最后解得:y = 1  

那么我们就让 y 减去 1 就行了:

y = abs( 6 * x % 6 - 3 ) -1  

有了这个,我们其余得部分就不要了,用 clamp 函数把 0 , 1 之外的减去,

y =  clamp(abs( 6 * x % 6 - 3 ) -1,0,1)

OK , 基本快完成了 , 然后 G 要平移一下,我们把 4/6 点直接平移到坐标原点就行了。

clamp(abs( 6 * (x+4/6) % 6 - 3 ) -1,0,1)

这就是RGB中,G随 UV.x 的变化曲线 .

那么现在,就可以来写shader 了,

为了方便阅读,我把他么分成了几个函数来 :

第一步,计算偏移量:

            float computeOffset(float x , float off )
            {
                return (x + off /6);
            }
第二步,计算 模

            float computeMod(float x ,float offset )
            {
                return 6  *  computeOffset(x,offset)  % 6 - 3 ;
            }
第三步,计算 绝对值

            float computeABS( float x ,float offset )
            {
                return abs(computeMod(x,offset))-1 ;
            }
最后一步直接写道代码里把:

                float R = clamp(computeABS(c.x,0),0,1);
                float G = clamp(computeABS(c.x,4),0,1);
                float B = clamp(computeABS(c.x,2),0,1);
                vec3 rgb = vec3(R,G,B);
此时,效果就是这样了:


看到颜色似乎过度太明显了,我们修正一下:

我直接用图形学基本公式了:

-2 * pow(x,3 ) + 3 * pow( x , 2 )
它的曲线张这样:


经常会使用到的平滑曲线,然后得到平滑后的图像:


最后一步就是,我们还要增加他的亮度变化,直接用uv.y 进行叠加就OK:


rgb = uv.y * rgb

最后还有一个饱和度的叠加,我们要引入第三个变量了

saturation ("radies", Range(0.0,1.0)) = 1.0

rgb = uv.y * mix( fixed3(1.0,1.0,1.0), rgb, saturation );
最后就可以用  saturation 调节饱和度了:


源码:收100意思一下啦~~

价格:100元素币(或10余额) 包含源代码 销售总额:200元素币 购买人数:2

尊敬的游客 ,本内容需要支付 100元素币十分之一的[余额] 来购买.
您可以[充值][发帖] [悬赏] [任务]来赚取积分。

参与人数 1 元素币 +99 活跃度 +99

本帖被以下画板推荐:

还没有设置签名!您可以在此展示你的链接,或者个人主页!

使用道具 举报 登录

回复 <
qq_马卡龙_WRh  发表于 2018-11-10 10:20:23  
2#
从业不识微元素,做遍项目也枉然
回复 收起回复
使用道具
laopi123  发表于 2018-11-10 10:58:18  
3#
我们先定一个能达到的小目标,先赚它一亿元素币
回复 收起回复
使用道具
wolfram  发表于 2018-11-10 12:09:13  
4#
从业不识微元素,做遍项目也枉然
回复 收起回复
使用道具
qq_叫我小明_LUo  发表于 2018-11-10 14:01:39  
5#
666666666666666666666
回复 收起回复
使用道具
不能好好起名  发表于 2018-11-10 14:44:26  
6#
很好的帖子
回复 收起回复
使用道具
bili23  发表于 2018-11-10 21:01:57  
7#

从业不识微元素,做遍项目也枉然
回复 收起回复
使用道具
G长远36  发表于 2018-11-11 07:04:29  
8#

感谢楼主的分享!!!
回复 收起回复
使用道具
星舰与太阳  发表于 2019-2-13 15:06:05  
9#
回复 收起回复
使用道具
lh1031464180  发表于 2019-2-13 22:23:26  
10#
帅的一批 赞赞咋
回复 收起回复
使用道具
MasterZjy  发表于 2019-2-18 09:55:44  
11#
哇,好牛
回复 收起回复
使用道具
qq945546905  发表于 2019-2-18 17:08:35  
12#
虽然看不懂 哈哈哈哈哈还觉得很牛批  
回复 收起回复
使用道具

快来发表你宝贵的意见吧!

静心-养病-等待 实名

通过了实名认证的内容创造者

  

主题
2
精华
0
超神
0
扩散
0
微金
0
智慧
0
余额
0
在线时间
32 小时

短杖 学徒法袍

快速回复 返回顶部 返回列表