天天看点

OpenGL中向量加减乘除运算的几何意义

Vector arithmetic is fundamental to 3D graphics, physics and animation and it is useful to understand it in depth to get the most out of Unity. Below are descriptions of the main operations and some suggestions about the many things they can be used for. \

向量运算是三维图形,物理和动画的基础,对它深入了解,对Unity非常有帮助。下面是一些主要运算的描述,可用于对很多事情的描述和建议。

Addition 加法

When two vectors are added together, the result is equivalent to taking the original vectors as "steps", one after the other. Note that the order of the two parameters doesn't matter, since the result is the same either way.

当两个向量相加,是体格向量的头到另一个向量的尾,一前一后。请注意,这两个参数的顺序并不重要,因为无论哪种方式结果是相同的。

If the first vector is taken as a point in space then the second can be interpreted as an offset or "jump" from that position. For example, to find a point 5 units above a location on the ground, you could use the following calculation:-

如果第一个向量空间中的点,那么第二个可以解释为从这个点位移或"跳跃" 。例如,要找到地面上的某个点5个以上的单位的位置,你可以使用以下的计算

var pointInAir = pointOnGround + new Vector3(0, 5, 0);      

If the vectors represent forces then it is more intuitive to think of them in terms of their direction and magnitude (the magnitude indicates the size of the force). Adding two force vectors results in a new vector equivalent to the combination of the forces. This concept is often useful when applying forces with several separate components acting at once (eg, a rocket being propelled forward may also be affected by a crosswind).

如果向量代表的力,那么可以更直观的表示为在他们自己的方向上的力(长度表示力的大小)。两个力相加的结果是这两个力的合力。这个概念经常用到,当几个分利同时执行的时候(例如,推动火箭也可能受侧风的影响)。

Subtraction 减法

Vector subtraction is most often used to get the direction and distance from one object to another. Note that the order of the two parameters does matter with subtraction:-

向量减法经常用来计算一个对象从一个点到另一个的方向和距离。请注意,这两个参数的顺序与减法的问题:

// The vector d has the same magnitude as c but points in the opposite direction. var c = b - a; var d = a - b;      

As with numbers, adding the negative of a vector is the same as subtracting the positive.

类似于数字计算,加上一个负的等于减去一个正的。

// These both give the same result. var c = a - b; var c = a + -b;      

The negative of a vector has the same magnitude as the original and points along the same line but in the exact opposite direction.

负的向量跟正的向量在同一条直线上 并且方向相反。

Scalar Multiplication and Division 标量乘法和除法

When discussing vectors, it is common to refer to an ordinary number (eg, a float value) as a scalar. The meaning of this is that a scalar only has "scale" or magnitude whereas a vector has both magnitude and direction.

当我们讨论的向量,它常用他的标量作为一个普通的数字(例如,一个float值) 。这表示标量只有大小,而向量的大小和方向。

Multiplying a vector by a scalar results in a vector that points in the same direction as the original. However, the new vector's magnitude is equal to the original magnitude multiplied by the scalar value.

向量乘以一个标量方向和位置仍为原来的方向和位置。然而,新的向量的大小等于原来的大小乘以标量。

Likewise, scalar division divides the original vector's magnitude by the scalar.

同样,标量的除法结果就是标量的几分之一。

These operations are useful when the vector represents a movement offset or a force. They allow you to change the magnitude of the vector without affecting its direction.

向量代表一个移动或力时,这些运算是非常有用的。他们允许你改变向量的大小而不影响其方向。

When any vector is divided by its own magnitude, the result is a vector with a magnitude of 1, which is known as a normalized vector. If a normalized vector is multiplied by a scalar then the magnitude of the result will be equal to that scalar value. This is useful when the direction of a force is constant but the strength is controllable (eg, the force from a car's wheel always pushes forwards but the power is controlled by the driver).

任何向量除以他自己的大小,其结果是一个长度为1的向量,这被称为单位向量。如果一个单位向量乘以一个标量,那么结果的长度将标量的大小。当力的方向是不变的,但力是可控的时.这是非常有用的.(例如,一辆车的车轮的力总是向前的,但力的大小是由司机控制) 。

Dot Product 点乘

The dot product takes two vectors and returns a scalar. This scalar is equal to the magnitudes of the two vectors multiplied together and the result multiplied by the cosine of the angle between the vectors. When both vectors are normalized, the cosine essentially states how far the first vector extends in the second's direction (or vice-versa - the order of the parameters doesn't matter).

两个向量想成的结果是一个标量。此标是等于两个向量长度相乘结果乘以向量之间的夹角的余弦。当两个向量都为单位向量时,余弦的定义就表示为第一个向量在第二个向量上面的射影长度(或反之亦然 - 参数的顺序并不重要) 。

It is easy enough to think in terms of angles and then find the corresponding cosines using a calculator. However, it is useful to get an intuitive understanding of some of the main cosine values as shown in the diagram below:-

容易想像,在角度方面可以通过计算器计算余弦值。然而,下面图标中的一些主要的余弦值是会经常用到的。

The dot product is a very simple operation that can be used in place of the Mathf.Cos function or the vector magnitude operation in some circumstances (it doesn't do exactly the same thing but sometimes the effect is equivalent). However, calculating the dot product function takes much less CPU time and so it can be a valuable optimization.

点程是一个非常简单的操作,可以在需要矢量长度操作的地方用Mathf.Cos功能(它不会做同样的事情,但有时效果是等价的)。尽管如此,计算点乘功能需要CPU时间要少得多,因此它可以是一个有价值的优化。

Cross Product 叉乘

The other operations are defined for 2D and 3D vectors and indeed vectors with any number of dimensions. The cross product, by contrast, is only meaningful for 3D vectors. It takes two vectors as input and returns another vector as its result.

其他操作被定义为二维和三维向量和任意维数向量。叉乘只能用来计算3D向量,它需要输入两个向量返回结果是另一个向量。

The result vector is perpendicular to the two input vectors. The "left hand rule" can be used to remember the direction of the output vector from the ordering of the input vectors. If the first parameter is matched up to the thumb of the hand and the second parameter to the forefinger, then the result will point in the direction of the middle finger. If the order of the parameters is reversed then the resulting vector will point in the exact opposite direction but will have the same magnitude.

得到的结果垂直于输入的两个向量。"左手坐标系"可以用来表示输入和输出的向量的方向。如果第一个参数匹配手的拇指和食指匹配第二个参数,结果将是中指的方向。如果参数的顺序是相反的结果向量将指向正好相反的方向,但将有相同长度。

The magnitude of the result is equal to the magnitudes of the input vectors multiplied together and then that value multiplied by the sine of the angle between them. Some useful values of the sine function are shown below:-

结果的大小等于输入向量的乘积,然后通过它们之间的角度的正弦值乘以该值的大小。

The cross product can seem complicated since it combines several useful pieces of information in its return value. However, like the dot product, it is very efficient mathematically and can be used to optimize code that would otherwise depend on slow transcendental functions.

叉乘比较复杂,因为在其返回值结合了一些有用的信息。但是像点乘那样,这些非常有效的数学可以用来优化代码,否则将依赖于缓慢的超越函数。

举个栗子

OpenGL中向量加减乘除运算的几何意义
#version 450 core

out vec4 FragColor;

in VS_OUT
{
  vec3 FragPos;     //传入地面在世界空间中的坐标
  vec3 Normal;
  vec2 TexCoords;
} fs_in;

uniform sampler2D floorTexture;
uniform vec3 lightPos;                //光源位置
uniform vec3 viewPos;                 //观察者位置
uniform bool blinn;                   //是否是blinn-phong光照模型

void main()
{
  vec3 color = texture(floorTexture, fs_in.TexCoords).rgb;
  //ambient
  vec3 ambient = 0.05 * color;     //环境光照分量
  //diffuse
  //向量减法经常用来计算一个对象从一个点到另一个的方向和距离。请注意,这两个参数的顺序与减法的问题 
  vec3 lightDir = normalize(lightPos - fs_in.FragPos);   //光源位置到地面位置的距离
  vec3 normal = normalize(fs_in.Normal);
  float diff = max(dot(lightDir, normal), 0.0f);
  vec3 diffuse = diff * color;     散射光照分量
  //specular
  //观察者位置到地面位置的距离
  vec3 viewDir = normalize(viewPos - fs_in.FragPos);
  vec3 reflectDir = reflect(-lightDir, normal);
  float spec = 0.0f;
  if(blinn)   //blinn-phong光照模型
  {
    vec3 halfwayDir = normalize(lightDir + viewDir);
    spec = pow(max(dot(normal, halfwayDir), 0.0f), 32.0f);  //镜面光照分量
  }
  else
  {
    vec3 reflectDir = reflect(-lightDir, normal);
    spec = pow(max(dot(viewDir, reflectDir), 0.0f), 8.0f);  //phong光照模型
  }
  
  vec3 specular = vec3(0.3) * spec; // assuming bright white light color
  FragColor = vec4(ambient + diffuse + specular, 1.0f);


}      

运行效果