榨干Dot的最后一点油,你不在意的点乘应用

在上一篇Unity3d Shader中的小芝麻(Dot点乘解惑篇)的文尾巴,我留了一个引子,“关于dot的应用无非是求边缘和求非边缘?”,

确实Dot在shader中的应用主要是求边缘或者非边缘(也就是面),但是并不是全部,本文的目的是结合向量点积的定义,收集和总结向量点乘Dot(点积)在Unity(game)中的应用。下面看一下向量点积的定义

使用矩阵乘法并把(纵列)向量当作n×1 矩阵,点积还可以写为:

a·b=a^T*b,这里的a^T指示矩阵a的转置

不用说太多的数学知识,我们把定义分为这三种吧,1、几何意义,2、代数意义,3、矩阵乘法(向量投影)相关。下面我们就用实际中的例子来继续解释这三种定义在游戏开发中的应用。

实现

a.b = x1x2+y1y2

代数意义,实际上如果数学一般的同学,看到这个数学式子,应该是没有什么感觉的我也是如此,后来在不断学习中发现,这么小的一个式子应用竟然如此广泛

A、计算向量长度和平方(模的平方)

如果说你对a.b = x1x2+y1y2 不敏感的话,如果dot中的参数相同也就是 a.a = x1x1+y1y2(勾股定理?),是的向量长度的平方,这个的一个应用是在点光源的衰减因子计算上(与到光源的距离平方成反比)

红框部分的代码已经很清楚了,详情参考链接 http://gad.qq.com/program/translateview/7173934 Unity渲染教程(五):多个光源

B、实现灰度公式的快速计算

计算灰度在游戏中是一种常用的图像操作,比如人物死后的画面,不能点击的按钮,死人的头像等等。求灰度的公式是什么呢?

对于彩色转灰度,有一个很著名的心理学公式:
Gray = R*0.299 + G*0.587 + B*0.114

看到这个式子,可能大家都笑了,这次我们对于算式开始敏感了,这就不是点积吗?我们看下例子中的Shader代码

效果如下:

代码很简单,这里就不详细说了,复杂的例子可以看这几篇

http://blog.csdn.net/sgnyyy/article/details/25713791 Unity图片变灰的方式

http://blog.csdn.net/nanggong/article/details/53008460 Unity Shaders——屏幕灰度效果(Screen Effect)

http://blog.csdn.net/puppet_master/article/details/52423905 Unity Shader-后处理:简单的颜色调整(亮度,饱和度,对比度)

补充实际上灰度化也可以使用颜色平均值,这种简便高效的方式

具体参考,http://blog.csdn.net/nanggong/article/details/53035245 Unity中实现灰度图效果

几何意义,实际上一篇中应用的也是几何意义,求边缘的依据也是归一化向量夹角的cos值

A、Dot正负值应用,判断主角与目标的前后位置,

    我们补充一个常用的dot几何意义的补充,根据Dot值,获得目标的位置信息,通过正负值,判断目标前后位置(负值在求边缘中被我们舍弃的部分),文字不好描述上图和代码很清晰了

判断敌我方位

1.判断目标在自己的前后方位可以使用下面的方法:

   Vector3.Dot(transform.forward, target.position-transform.position)

       返回值为正时,目标在自己的前方,反之在自己的后方

2.判断目标在机子的左右方位可以使用下面的方法:

   Vector3.Cross(transform.forward, target.position-transform.position).y

      返回值为正时,目标在自己的右方,反之在自己的左方

想学习详情的看这篇 http://www.cnblogs.com/weiqiangwaideshijie/p/6633267.html  Unity3D之点乘和差乘

补充计算目标左右方的代码参考一下代码

public static bool RotationDirection(Vector3 currentDir, Vector3 previousDir) {

if (Vector3.Cross(currentDir, previousDir).z > 0) {

//顺时针 return true; } else {

//逆时针 return false;

}

}

作者:影子丢了

链接:http://www.jianshu.com/p/6bd8623a825e

來源:简书

 

B、求向量夹角

我想通过Dot几何意义的求向量夹角,可能是我们最熟悉的了,具体就是应用高中的反余弦函数大家都懂

void OnGUI ()  
{  
        //点积的返回值  
        float c = Vector3.Dot (a, b);  
        //向量a,b的夹角,得到的值为弧度,我们将其转换为角度,便于查看!  
        float angle = Mathf.Acos (Vector3.Dot (a.normalized, b.normalized)) * Mathf.Rad2Deg;  
        GUILayout.Label ("向量a,b的点积为:" + c);  
        GUILayout.Label ("向量a,b的夹角为:" + angle);  
  
  
        //叉积的返回值  
        Vector3 e = Vector3.Cross (a, b);  
        Vector3 d = Vector3.Cross (b, a);  
        //向量a,b的夹角,得到的值为弧度,我们将其转换为角度,便于查看!  
        angle = Mathf.Asin (Vector3.Distance (Vector3.zero, Vector3.Cross (a.normalized, b.normalized))) * Mathf.Rad2Deg;  
        GUILayout.Label ("向量axb为:" + e);  
        GUILayout.Label ("向量bxa为:" + d);  
        GUILayout.Label ("向量a,b的夹角为:" + angle);  

当然都通过叉乘也可以求夹角,这部分代码是我引用的这篇文章中,详细资料请自行参考

http://blog.csdn.net/wingfourever/article/details/27714311?utm_source=tuicool Unity3D之Vector3.Dot和Vector3.Cross的使用

矩阵乘法相关(向量投影)

实际也代数意义相关,在向量的旋转计算中我们引入了旋转矩阵,根据背景中列出的3部分,我们可以用点积来进行矩阵运算的式子分解

如算式敏感的同学的旋转矩阵的应用

这里我们反的看(c是cos,sin是sin)

uv = float2(uv.x*c - uv.y*s, uv.x*s + uv.y*c);
尼玛,我算式敏感了,这是什么?这不是点积嘛,然后我们得出
uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c)));
我的数学天赋有上升了一个层次根据“a·b=a^T*b,这里的a^T指示矩阵a的转置”然后我们得出了





关于旋转矩阵不是本篇要涉及的内容,所以不在这里说了,这方面的文章很多自行 脑补吧,下面是我参考的文章
http://www.cnblogs.com/joeshifu/p/5489761.html Shader实例:扭曲,漩涡
漂亮的效果图



 
 

旋转.gif (638.68 KB, 下载次数: 2)

下载附件  保存到相册

2017-8-24 08:48 上传

关于如何通过点积获得的旋转,也就是

uv = float2(dot(uv, float2(c, -s)), dot(uv, float2(s, c)));

是如何证明的参考一下这篇文章吧,满满的数学知识,从另一个侧面揭示了矩阵乘法的本质

http://blog.csdn.net/ubunfans/article/details/45676433

总结

以上两篇文中提到知识点,是我关于Dot向量点乘的在图形图像(game)应用的总结,以我羸弱的数学知识来说实属不易,最后慨叹一下点积 a.b=|a||b|cos(a,b)这个小小的数学公式竟然有这么大的威力!希望以上知识对你有用。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值