如何在Shader中仅绕Z轴旋转方向向量?附具体旋转示例
没问题!在Shader里绕Z轴旋转你的向上向量(0, 1, 0)其实很直观,刚好可以用你提到的两种方式——标量角度或者目标向量B来实现,咱们一个个拆解:
方法一:用旋转角度(标量)实现
绕Z轴旋转的核心是2D旋转矩阵,因为Z轴作为旋转轴时,只有X、Y分量会发生变化,Z分量保持不变。对应你说的顺时针旋转90°场景,我们需要用顺时针旋转的矩阵公式:
[ cosθ sinθ 0 ] [ -sinθ cosθ 0 ] [ 0 0 1 ]
当θ=90°时,cos90°=0,sin90°=1,把原向量(0,1,0)代入矩阵乘法,就能得到(1,0,0),完全符合你的预期。
在GLSL(主流Shader语言)里,你可以封装成一个函数来复用:
// 传入原始向量和顺时针旋转的角度(度数) vec3 rotateAroundZ(vec3 vec, float angleDeg) { float angleRad = radians(angleDeg); // 转成弧度(Shader三角函数用弧度) float cosA = cos(angleRad); float sinA = sin(angleRad); // 构造顺时针旋转矩阵 mat3 rotationMat = mat3( cosA, sinA, 0.0, -sinA, cosA, 0.0, 0.0, 0.0, 1.0 ); return rotationMat * vec; } // 调用示例:把(0,1,0)顺时针转90° vec3 originalUp = vec3(0.0, 1.0, 0.0); vec3 rotatedVec = rotateAroundZ(originalUp, 90.0); // rotatedVec 结果就是 (1.0, 0.0, 0.0)
方法二:用目标向量B实现
如果你已经知道最终要指向的目标向量B(注意:B的Z分量必须为0,因为绕Z轴旋转不会改变向量的Z值),可以直接用B来推导旋转结果,甚至跳过三角函数计算,性能更优。
简化版:直接复用目标向量
如果B已经是XY平面内的单位向量,那直接提取它的X、Y分量,加上原向量的Z分量即可:
vec3 rotateToTarget(vec3 originalVec, vec3 targetVec) { // 确保目标向量在XY平面,先归一化再提取分量 vec2 targetXY = normalize(targetVec.xy); return vec3(targetXY.x, targetXY.y, originalVec.z); } // 调用示例:转到(1,0,0)方向 vec3 originalUp = vec3(0.0, 1.0, 0.0); vec3 targetB = vec3(1.0, 0.0, 0.0); vec3 rotatedVec = rotateToTarget(originalUp, targetB); // 结果就是 (1.0, 0.0, 0.0)
进阶版:用目标向量构造旋转矩阵
如果需要复用旋转矩阵(比如要旋转多个向量),可以用目标向量的分量直接构造旋转矩阵,避免三角函数计算:
vec3 rotateWithTargetVec(vec3 originalVec, vec3 targetVec) { vec2 targetXY = normalize(targetVec.xy); // 用目标向量分量构造旋转矩阵(原理来自旋转矩阵的三角函数对应关系) mat3 rotationMat = mat3( targetXY.y, targetXY.x, 0.0, -targetXY.x, targetXY.y, 0.0, 0.0, 0.0, 1.0 ); return rotationMat * originalVec; }
内容的提问来源于stack exchange,提问作者MaT
相关产品推荐
相关产品推荐

