当窗口大小调整时,如何使 SDL 窗口中的 OpenGL 视口保持静止?

发布于 2024-11-17 08:34:29 字数 1164 浏览 1 评论 0原文

我有一个包含 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 时,通过拖动边缘来调整窗口大小不会导致视口的内容重新居中。

造成这种差异的原因是什么?我该如何修复它?

I have an SDL window containing an OpenGL viewport. When the user resizes the window by dragging a window edge, I'd like for (1) the viewport to expand to fill the window, and (2) for the contents of the viewport to remain stationary.

For example:

------------------------
|          |           |
|  <------ |           |
|          |        X  |
|  <------ |           |
|          |           |
------------------------

If the left edge of the window is dragged further left, then the object X in the OpenGL viewport should remain stationary.

I'm finding that the code I'm calling on SDL_VIDEORESIZE events is not only not doing this, but also causing some awful flickering:

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);

What this code seems to do when a window is resized is to translate what was at the center of the old viewport to be at the center of the new viewport. The same code behaved as I expected when used with GLUT instead of SDL---with GLUT, resizing the window by dragging the edges did not cause the contents of the viewport to recenter.

What accounts for this difference? How can I fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

(り薆情海 2024-11-24 08:34:29

做到这一点的唯一方法是让视图矩阵随窗口移动。这意味着除了在调整大小时更改变换矩阵之外,还必须在单击并拖动窗口时对其进行调整。为了演示移动窗口和重复调整大小的等效性,请考虑如果您像这样进行一系列增量调整大小会发生什么:

|---------------|                   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);

The only way to do this is to also have view matrix move with the window. This means that in addition to changing your transformation matrix when you resize, you must also adjust it when you click and drag the window. To demonstrate the equivalence of moving a window and repeated resizing, consider what would happen if you do a bunch of incremental resizings like so:

|---------------|                   1.  Starting window

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

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

Thus, to get the desired behavior you should set your gluOrtho2D matrix to the following value every time your window moves/gets resized (or alternatively at the start of the frame where you draw everything):

int wind_x, wind_y;
SDL_GetWindowPosition(window, &wind_x, &wind_y);
gluOrtho2D(wind_x, wind_x + w, wind_y, wind_y + h);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文