函数原型:
void glViewport(GLintx, GLinty, GLsizeiwidth, GLsizei height)
函数作用:
改变OpengL描绘结果原点在屏幕的位置及尺寸
参数说明:
x 以像素为单位,设置投影结果的原点在屏幕水平方向的位置,屏幕最左端为-width/2(世界坐标系中的-1),右端为width/2(世界坐标的1);
y 以像素为单位,设置投影结果的原点在屏幕垂直方向的位置,屏幕最顶端为height/2(世界坐标系中的1)底端为-height/2(世界坐标系中的-1);
width 屏幕的宽度
height 屏幕的高度
OpenGL默认的屏幕坐标如下:
(-width/2, height/2) (width/2, height/2)
|
(width/2, -height/2)
(-width/2, -height/2)
以上来自于我个人的理解。下面以两个例子作为说明
例一:
代码:
void TriangleWindow::render()
{
const qreal retinaScale = devicePixelRatio();
// 设置世界坐标系原点在屏幕的中央
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
//glViewport(-width() * retinaScale/2.0f, -height() * retinaScale/2.0f, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
// 单位矩阵
matrix.setToIdentity();
// 移动后水平-5000.0f缩放后为世界坐标的-1.0f, 水平5000.0f变为1.0f
matrix.scale(1/5000.0f, 1.0/2.0f, 0.0f);
// 移动后水平0.0f变为-5000.0f, 水平10000.0f变为5000.0f
matrix.translate(-5000.0f,1.0f, 0.0f);
m_program->setUniformValue(m_matrixUniform, matrix);
GLfloat vertices[] = {0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
10000.0f, -1.0f,0.0f};
if(nBegin > 5.0f)
{
nBegin = -5.0f;
}
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
运行结果:
图一
例二:
代码:
void TriangleWindow::render()
{
const qreal retinaScale = devicePixelRatio();
// 设置世界坐标系原点在水平最左端,垂直中间
//glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glViewport(-width() * retinaScale/2.0f, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
// 单位矩阵
matrix.setToIdentity();
// 移动后水平-5000.0f缩放后为世界坐标的-1.0f, 水平5000.0f变为1.0f
matrix.scale(1/5000.0f, 1.0/2.0f, 0.0f);
// 移动后水平0.0f变为-5000.0f, 水平10000.0f变为5000.0f
matrix.translate(-5000.0f,1.0f, 0.0f);
m_program->setUniformValue(m_matrixUniform, matrix);
GLfloat vertices[] = {0.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
10000.0f, -1.0f,0.0f};
GLfloat colors[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
运行结果:
图二
规律:
由于OpenGL水平及垂直方向-1 到1 的结果显示出来,而图二把世界坐标的原点左移屏幕的一半,则图二自然也就是图一显示的一半。
以上是我个人的实践结果。