当SDL窗口大小改变时,如何保持OpenGL视口静止?

3
我有一个包含OpenGL视口的SDL窗口。当用户通过拖动窗口边缘来调整窗口大小时,我希望(1)视口扩展以填充窗口,(2)视口内容保持静止。
例如:
------------------------
|          |           |
|  <------ |           |
|          |        X  |
|  <------ |           |
|          |           |
------------------------

如果将窗口的左边缘进一步向左拖动,则OpenGL视口中的对象X应保持静止。
我发现我在SDL_VIDEORESIZE事件上调用的代码不仅没有实现这一点,还导致了一些可怕的闪烁。
SDL_FreeSurface(window);
window = SDL_SetVideoMode(_w, _h, 32, SDL_OPENGL | SDL_RESIZABLE);

glViewport(0, 0, _w, _h);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

const double w_2 = _w/2.0;
const double h_2 = _h/2.0;

gluOrtho2D(-w_2, w_2, -h_2, h_2);

// adjust model matrix
const double s_cosT = _scale*cos(_theta);
const double s_sinT = _scale*sin(_theta);

model[ 0] =  s_cosT;
model[ 1] =  s_sinT;
model[ 4] = -s_sinT;
model[ 5] =  s_cosT;
model[12] =  s_cosT*_x - s_sinT*_y;
model[13] =  s_sinT*_x + s_cosT*_y;

glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(model);

当窗口被调整大小时,这段代码似乎会将旧视口中心的内容转换为新视口中心。当使用GLUT而非SDL时,相同的代码表现符合我的预期——使用GLUT,通过拖动边缘调整窗口大小不会导致视口内容重新居中。
是什么原因造成了这种差异?我该如何解决它?

1
你没有展示你代码的其余部分。具体来说,你没有展示当窗口大小改变时如何更新视口/投影矩阵。 - Nicol Bolas
添加了更新模型矩阵的代码。 - uckelman
1个回答

2
唯一的方法是让视图矩阵随窗口移动。这意味着除了在调整大小时更改转换矩阵外,还必须在单击并拖动窗口时进行调整。为了证明移动窗口和重复调整大小的等效性,请考虑如果您进行一系列增量调整大小,会发生什么:
|---------------|                   1.  Starting window

        |-------|                   2.  Resize left edge

        |---------------|           3.  Resize right edge

因此,为了获得所需的行为,每次窗口移动/调整大小(或者在绘制所有内容的帧的开始时)应将您的gluOrtho2D矩阵设置为以下值:
int wind_x, wind_y;
SDL_GetWindowPosition(window, &wind_x, &wind_y);
gluOrtho2D(wind_x, wind_x + w, wind_y, wind_y + h);

1
好观点。大多数拖动右边缘的解决方案在拖动左边缘时可能会出现严重问题。这个解决方案应该适用于两种情况。 - Ben Voigt
据我所知,SDL_GetWindowPosition函数并不存在。 - uckelman
你使用的是哪个版本?它在最新的构建中:http://wiki.libsdl.org/moin.cgi/SDL_GetWindowPosition?highlight=%28%5CbCategoryVideo%5Cb%29%7C%28CategoryStruct%29%7C%28CategoryEnum%29 - Mikola
啊,那么你将被迫使用本地调用来获取窗口坐标。或者,你也可以升级你的libsdl版本... - Mikola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接