我在OpenGL(WebGL)中有一个对象,我对它的外观很满意,并希望将它向左移动一点。然而,当我这样做时,它的视角发生了变化。我希望保持它与它完全一样,只是让它在不同的地方呈现。
我正在使用一个相当标准的设置,使用投影和模型视图矩阵。我尝试以各种方式改变它们,但我只能让我的物体在3D空间中移动,而不是在平面屏幕或眼睛坐标中移动。任何想法如何做到这一点(没有渲染到纹理)?
一些代码摘录。这些功能显而易见,它们来自Mozilla WebGL教程。我认为确切的定义并不重要。
// set perspective matrix
var perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
loadIdentity();
// set modelview matrix
mvTranslate([0, 0, -12]);
mvRotate(rotationAngle, [0, 1, 0]);
// and then I just draw an object...
在顶点着色器中:
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
说实话,我认为具体的代码对于这个问题并不那么重要。请不要挂断它。我可以使用Three.js,或DirectX,或手写的光线跟踪器。我将重新提出这个问题:在标准形式主义中,屏幕坐标是通过矩阵乘法从模型坐标计算的:
u = Perspective * ModelView * x
我想在屏幕上移动u
。我可以手工完成:
u.x += deltaX
u.y += deltaY
但是有没有办法使用透视矩阵来获得相同的效果?是否有一种在视图空间中引入变换的“标准”方式? OpenGL中有一个便利功能吗?
答案 0 :(得分:0)
以下将一个单位翻译成左侧,一个单位翻译成一侧。
var shift = Matrix.Translation($V([-1, -1, 0]));
如果您的对象位于屏幕中间(0,0),并且您的坐标从左下角(-1,-1)到右上角(1,1),则会将对象的中间放置在左下角。
现在要记住的是,矩阵乘法通常是非交换的。所以你不能perspective x something
,它必须是something x perspective
。这样,当您对模型矢量进行操作时,首先应用透视,然后应用您的移位:
var shiftedPerspectiveMatrix = shift.x(perspectiveMatrix)
作为奖励,以下是如何在像素坐标中执行此操作:
// for referece:
var perspectiveMatrix = makePerspective(45, 640.0/480.0, 0.1, 100.0);
var trans = Matrix.Translation($V([-1, -1, 0]));
var scale = Matrix.Diagonal([320, 240, 1, 1]);
// move 100 pixels to the left
var viewShift = Matrix.Translation($V([-100, 0, 0]));
let transI = trans.inv();
let scaleI = scale.inv();
var newPerspectiveMatrix = transI.x(scaleI).x(viewShift).x(scale).x(trans).x(perspectiveMatrix);
要记住的是,当 M 是一个矩阵时, M -1 M 是一个无操作。应用 M 后,您将生活在不同的坐标系中。因此,如果要在不同的坐标系中定义要应用的变换 A ,则可以执行 x' = M -1 AM x 。
很抱歉,如果我弄乱订单的话。解析几何和线性代数已经很久了。
现在上面的代码是做什么的,它将坐标转换为人类可理解的系统(屏幕像素,虽然原点在中心),应用我想要的转换,并转换回OpenGL可理解系统。请注意,应用程序是从右到左,我以相反的顺序撤消操作。