MY BLOG DIRECTORY:
YivanLee:专题概述及目录INTRODUCTION:
我们的游戏里经常会用到统计功能,需要制作各种曲线图像,上一篇文章我做的雷达统计图,然后下面就有人在问曲线统计图怎么做,我这里试一下在shader里用很少的计算来制作统计曲线图。
Forward declaration:
本文章内容过于浅显rua鸡,如有错误还请斧正。
MAIN CONTENT:
【1】f(x) = kx + b
![v2-e85b4a1d22073d377c4a7f922e65aa4c_b.gif](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-e85b4a1d22073d377c4a7f922e65aa4c_b.gif)
材质节点如下:
![v2-77e32bd6079712c51f1fb6762a2ff097_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-77e32bd6079712c51f1fb6762a2ff097_b.jpg)
材质的思路非常简单,首先计算坐标系,把UV坐标变换成y轴向上,o点在面片中心的状态,如UV坐标一开始就是这样了那就不需要变换了。然后我们构造一个fx,把x值输入到fx里做自变量然后由这个函数计算出fx的值。然后比较fx的值和UV的y坐标的距离。
![v2-c5fabdbdaa5984778ef1f61fcff3e6c4_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-c5fabdbdaa5984778ef1f61fcff3e6c4_b.jpg)
然后我们把它clamp在【0,1】的范围内然后再反一下。
然后再把函数值稍稍加一点上去,让离函数曲线比较近的像素的值能大于1,然后再用floor把大于1的值等于1,小于1的值为0,这样就画出了我们的函数。后面如果想画其他函数只需要变化fx节点即可
【2】f(x) = sin(x)
![v2-e8d4eab00e428fbe3e773b24df76d00a_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-e8d4eab00e428fbe3e773b24df76d00a_b.gif)
![v2-9513227d39f9d490f11421f1d1562e1c_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-9513227d39f9d490f11421f1d1562e1c_b.jpg)
【3】f(x) = Ax^2 + b
![v2-f9b7ae2978123a774c54a701f5ee4937_b.gif](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-f9b7ae2978123a774c54a701f5ee4937_b.gif)
![v2-51bdc08c5939303fe56b203f28f46617_b.jpg](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-51bdc08c5939303fe56b203f28f46617_b.jpg)
【4】f(x) = a^x
![v2-e1f1438a883af5f15af34f0d7781a942_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-e1f1438a883af5f15af34f0d7781a942_b.jpg)
【5】Piecewise function
我们先把我们的材质再美化一下
![v2-931e7e0fbeaccdc51eecc4bc82cfc25a_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-931e7e0fbeaccdc51eecc4bc82cfc25a_b.jpg)
![v2-afd45e416c67f7fadb2d34e7388f0d6d_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-afd45e416c67f7fadb2d34e7388f0d6d_b.jpg)
做了一个坐标系方便看结果是否正确。下面就开始做曲线统计表。假设现在的游戏里有四个统计时段,玩家的时间和得分分别是【0,0】,【2,4】,【6,1】,【8,8】,我们用线性函数的两点式。
我的代码如下:
float TwoPointFunction(float2 p1, float2 p2, float x)
{
float fx = ((x - p1.x)/(p1.x - p2.x) + p1.y / (p1.y - p2.y)) * (p1.y - p2.y);
fx = x > p1.x ? fx : 0;
fx = x < p2.x ? fx : 0;
return fx;
}
float CustomNode_FX(float x)
{
float Ret = 0;
float2 p1 = float2(0, 0);
float2 p2 = float2(2, 4);
float2 p3 = float2(6, 1);
float2 p4 = float2(8, 8);
Ret = TwoPointFunction(p1, p2, x);
Ret += TwoPointFunction(p2, p3, x);
Ret += TwoPointFunction(p3, p4, x);
return Ret;
}
效果如下:
![v2-11d5566246094558306c51976dede362_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-11d5566246094558306c51976dede362_b.jpg)
为了让曲线粗细一致,我们需要更改一下距离公式
![v2-253d27e222cf9484e8cc2bd1938402c2_b.jpg](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-253d27e222cf9484e8cc2bd1938402c2_b.jpg)
之前是算L的长度,现在使用S的长度。对函数F(x)求导求得 。然后用
求得
进而求得s的长度。
![v2-3337c41cc5706aad85f39580819a5559_b.jpg](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-3337c41cc5706aad85f39580819a5559_b.jpg)
![v2-da472d7dcf45b333bcd5cfa40d81f77c_b.jpg](https://ss.csdn.net/p?https://pic1.zhimg.com/v2-da472d7dcf45b333bcd5cfa40d81f77c_b.jpg)
这样函数图像的粗细就均匀了,不会因为斜率过大而变得很细。
SUMMARY AND OUTLOOK:
至此我们可以在游戏里做各种统计图了,Enjoy it。
NEXT:
todo...