简体   繁体   English

旋转由几何着色器制作的四边形

[英]Rotate quad made in geometry shader

I'm drawing a quad using Geometry Shader, but can't figure out how to rotate it with angle. 我正在使用“几何着色器”绘制四边形,但无法弄清楚如何旋转角度。

void main(void)
{
float scaleX = 2.0f / u_resolution.x;
float scaleY = 2.0f / u_resolution.y;

float nx = (u_position.x * scaleX) - 1.0f;
float ny = -(u_position.y * scaleY) + 1.0f;

float nw = u_size.x * scaleX;
float nh = u_size.y * scaleY;


gl_Position = vec4( nx+nw, ny, 0.0, 1.0 );
texcoord = vec2( 1.0, 0.0 );
EmitVertex();

gl_Position = vec4(nx, ny, 0.0, 1.0 );
texcoord = vec2( 0.0, 0.0 ); 
EmitVertex();

gl_Position = vec4( nx+nw, ny-nh, 0.0, 1.0 );
texcoord = vec2( 1.0, 1.0 ); 
EmitVertex();

gl_Position = vec4(nx, ny-nh, 0.0, 1.0 );
texcoord = vec2( 0.0, 1.0 ); 
EmitVertex();


EndPrimitive(); 
}

Should I use a rotation matrix or sin and cos? 我应该使用旋转矩阵还是sin和cos? I'm not too great at math. 我的数学不太好。

You don't have to use matrices, but you need to use those sine functions. 您不必使用矩阵,但是您需要使用这些正弦函数。 Here is a way to rotate a 3D position about some arbitrary axis by some angle specified in degrees: 这是一种将3D位置围绕任意轴旋转以度数指定的某个角度的方法:

// This is the 3D position that we want to rotate:
vec3 p = position.xyz;

// Specify the axis to rotate about:
float x = 0.0;
float y = 0.0;
float z = 1.0;

// Specify the angle in radians:
float angle = 90.0 * 3.14 / 180.0; // 90 degrees, CCW

vec3 q;
q.x = p.x * (x*x * (1.0 - cos(angle)) + cos(angle))
    + p.y * (x*y * (1.0 - cos(angle)) + z * sin(angle))
    + p.z * (x*z * (1.0 - cos(angle)) - y * sin(angle));

q.y = p.x * (y*x * (1.0 - cos(angle)) - z * sin(angle))
    + p.y * (y*y * (1.0 - cos(angle)) + cos(angle))
    + p.z * (y*z * (1.0 - cos(angle)) + x * sin(angle));

q.z = p.x * (z*x * (1.0 - cos(angle)) + y * sin(angle))
    + p.y * (z*y * (1.0 - cos(angle)) - x * sin(angle))
    + p.z * (z*z * (1.0 - cos(angle)) + cos(angle));

gl_Position = vec4(q, 1.0);

If you know that you are rotating about some standard x-, y-, or z-axis, you can simplify the "algorithm" a lot by defining it explicitly for that standard axis. 如果您知道围绕某个标准x轴,y轴或z轴旋转,则可以通过为该标准轴显式定义“算法”来简化很多操作。

Notice how we rotate about the z-axis in the above code. 注意上面的代码中我们如何绕z轴旋转。 For example, rotation about the x-axis would be (x,y,z) = (1,0,0) . 例如,围绕x轴的旋转将是(x,y,z) = (1,0,0) You could set the variables to anything, but the values should result in the axis being a unit vector (if that even matters.) 您可以将变量设置为任何值,但是值应使轴成为单位矢量(即使这很重要)。

Then again, you might as well use matrices: 再一次,您不妨使用矩阵:

vec3 n = vec3(0.0, 0.0, 1.0); // the axis to rotate about

// Specify the rotation transformation matrix:
mat3 m = mat3(
  n.x*n.x * (1.0f - cos(angle)) + cos(angle),       // column 1 of row 1
  n.x*n.y * (1.0f - cos(angle)) + n.z * sin(angle), // column 2 of row 1
  n.x*n.z * (1.0f - cos(angle)) - n.y * sin(angle), // column 3 of row 1

  n.y*n.x * (1.0f - cos(angle)) - n.z * sin(angle), // column 1 of row 2
  n.y*n.y * (1.0f - cos(angle)) + cos(angle),       // ...
  n.y*n.z * (1.0f - cos(angle)) + n.x * sin(angle), // ...

  n.z*n.x * (1.0f - cos(angle)) + n.y * sin(angle), // column 1 of row 3
  n.z*n.y * (1.0f - cos(angle)) - n.x * sin(angle), // ...
  n.z*n.z * (1.0f - cos(angle)) + cos(angle)        // ...
);

// Apply the rotation to our 3D position:
vec3 q = m * p;
gl_Position = vec4(q, 1.0);

Notice how the elements of the matrix are laid out such that we first complete the first column, and then the second, and so on; 注意矩阵的元素是如何布置的,这样我们首先完成第一列,然后完成第二列,依此类推; the matrix is in column-major order. 矩阵按列优先顺序排列。 This matters when you try to transfer a matrix written in mathematical notation into a data type in your code. 当您尝试将以数学符号表示的矩阵转换为代码中的数据类型时,这一点很重要。 You basically need to transpose it (to flip the elements diagonally) in order to use it in your code. 为了在代码中使用它,您基本上需要对其进行转置(以对角线翻转元素)。 Also, we are essentially multiplying a matrix on left with a column vector on right. 同样,我们实质上是将左边的矩阵与右边的列向量相乘。

If you need a 4-by-4 homogeneous matrix, then you would simply add an extra column and a row into the above matrix, such that both the new rightmost column and bottommost row would consist of [0 0 0 1] : 如果您需要一个4×4的齐次矩阵,则只需在上面的矩阵中添加一个额外的列和一行,这样新的最右边的列和最下面的行都将由[0 0 0 1]

vec4 p = position.xyzw; // new dimension
vec3 n = ...; // same

mat4 m = mat4( // new dimension
  ...
  0.0,

  ...
  0.0,

  ...
  0.0,

  0.0,
  0.0,
  0.0,
  1.0
);

vec4 q = m * p;
gl_Position = q;

Again, notice the order of the multiplication when applying the rotation, it is important because it affects the end result. 同样,请注意应用旋转时的乘法顺序,这一点很重要,因为它会影响最终结果。 What happens in the multiplication is basically that a new vector is formed by calculating the dot-product of the position vector and each column in the matrix; 乘法发生的基本上是通过计算位置向量与矩阵中每一列的点积来形成一个新向量。 each coordinate in the resulting vector is the dot-product of the original vector and a single column in the matrix (see the first code example.) 所得向量中的每个坐标是原始向量与矩阵中单个列的点积(请参见第一个代码示例)。

The

q.x = p.x * (x*x * (1.0 - cos(angle)) + cos(angle))
    + p.y * (x*y * (1.0 - cos(angle)) + z * sin(angle))
    + p.z * (x*z * (1.0 - cos(angle)) - y * sin(angle));

Is same as: 与:

q.x = dot(p, m[0]);

One could even compose the matrix with itself: m = m*m; 一个人甚至可以自己组成矩阵: m = m*m; which would result in a 180-degree counterclockwise rotation matrix, depending on the angle used. 根据所使用的angle ,这将导致180度逆时针旋转矩阵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM