我渲染了一个三维物体,它在图像中的二维投影是正确的。但是现在我想将2d投影对象移动一些像素。我如何实现这一目标?
请注意,简单地翻译3d对象不起作用,因为在透视投影下,2d投影对象可能会发生变化。我的目标是只移动图像中的2d对象而不改变其形状和大小。
答案 0 :(得分:2)
如果您正在使用可编程管道,则可以在应用投影转换后应用转换。
唯一需要注意的是,应用投影矩阵后的变换坐标有一个w
坐标,用于透视分割。要使额外的翻译量在屏幕空间中保持不变,您必须将其乘以w
。顶点着色器的关键片段如下所示:
in vec4 Position;
uniform mat4 ModelViewProjMat;
uniform vec2 TranslationOffset;
void main() {
gl_Position = ModelViewProjMat * Position;
gl_Position.xy += TranslationOffset * gl_Position.w;
}
在w
的透视除法之后,这将产生固定的偏移量。
可编程和固定管道的另一种可能性是移动视口。假设窗口大小为vpWidth
次vpHeight
,并且您要应用的偏移量为(xOffset, yOffset)
,则可以将视口设置为:
glViewport(xOffset, yOffset, vpWidth + xOffset, vpHeight + yOffset);
这里需要注意的是,几何体仍将被相同的视图体积剪切,但仅在应用剪切后通过视口变换进行移动。如果几何体完全适合原始视口,则可以正常工作。但是,如果几何体最初被剪切,它仍将被相同的平面剪切,即使在应用移位后它实际上可能在窗口内。
答案 1 :(得分:2)
作为Reto Koradi答案的补充:您不需要着色器,也不需要修改您使用的视口(具有答案中提到的剪辑问题)。您可以通过预乘一些转换来简单地修改投影矩阵(实际上将在投影转换后最后应用):
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glTranstlate(x,y,z); // <- this one was added
glFrustum(...) or gluPerspective(...) or whatever you use
glFrustum
和gluPerspective
会将当前矩阵与它们构建的投影转换矩阵相乘,这就是人们通常首先加载身份的原因。但是,它不一定是身份,这种情况是少数情况下应该加载其他内容的情况之一。
由于您想要移动像素,但是在剪辑空间中应用了该转换,因此您需要进行一些单位转换。由于剪辑空间只是标准化设备空间的同质表示,其中平截头体在所有3个维度中都是[-1,1](因此视口在该空间中大于2x2单位),您可以使用以下内容:
glTranslate(x * 2.0f/viewport_width, y * 2.0f/viewport_height, 0.0f);
将输出移动(x,y)
像素。
请注意,虽然我为固定功能GL编写了这个,但数学当然也适用于着色器,你可以用同样的方式修改着色器使用的投影矩阵。