OpenGL Resize Window -> 对象被“移动/翻译”

Posted

技术标签:

【中文标题】OpenGL Resize Window -> 对象被“移动/翻译”【英文标题】:OpenGL Resize Window -> objects are “moved / translated” 【发布时间】:2019-02-12 13:15:20 【问题描述】:

当窗口的resize事件被调用时,对象被移出视口/屏幕。

下面的链接是一个视频,展示了正在发生的事情: https://drive.google.com/file/d/1dBnOqBDUBNCQrwr7ChFlpS8vbBQ6wfKh/view?usp=sharing

我刚刚发现它只是在使用 QT Windowing 时发生。 GLFW 并没有发生这种情况... wooow

我使用以下代码:

void Renderer::resize(int width, int height) 
    RendererSettings* settings = RendererSettings::getInstance();

    settings->setSize(width, height);

    glViewport(0, 0, width, height);    

    if (camera != nullptr) 
    
        float aspectRatio = float(width) / float(height);
        camera->updateProjectionPerspectiveAspect(aspectRatio);
    

我不再更换相机了。

updateProjectionPerspectiveAspectglFrustum(FoV, aspect, near, far) 相同。但其他参数的数据保持不变。

void Camera::setProjectionPerspective(float fieldOfView, float aspectRatio, float near, float far) 
this->fieldOfView = fieldOfView;
this->aspectRatio = aspectRatio;
this->nearFrustum = near;
this->farFrustum = far;

float xmin, xmax, ymin, ymax;       // Dimensions of near clipping plane
float xFmin, xFmax, yFmin, yFmax;   // Dimensions of far  clipping plane

// Do the Math for the near clipping plane
ymax = near * tanf(float(fieldOfView * PI_DIV_360));
ymin = -ymax;
xmin = ymin * aspectRatio;
xmax = -xmin;

// Construct the projection matrix
projectionMatrix = Mat4f::identity();
projectionMatrix[0] = (2.0f * near) / (xmax - xmin);
projectionMatrix[5] = (2.0f * near) / (ymax - ymin);
projectionMatrix[8] = (xmax + xmin) / (xmax - xmin);
projectionMatrix[9] = (ymax + ymin) / (ymax - ymin);
projectionMatrix[10] = -((far + near) / (far - near));
projectionMatrix[11] = -1.0f;
projectionMatrix[14] = -((2.0f * far * near) / (far - near));
projectionMatrix[15] = 0.0f;   
Camera 参数不为空,并且在调整大小期间会调用此事件“resize”。参数宽度和高度是正确的。

【问题讨论】:

您好,您使用的不是普通的 OpenGL,您有某种额外的 API 覆盖它。请指定您的工具,或者如果您不知道,请向我们展示您的工具 嗨,您记录了widthheight 的值吗?他们是正确的吗?此外是cameranull 还是ifbranch 被执行? @tomerzeitune updateProjectionPerspectiveAspect 与 glFrustum 相同。在OpenGL ES中没有用到,所以上面的代码是OpenGL。 @bitflip-at 参数正确,摄像头不为空。我只更新投影矩阵相机。 @Bruno 这是 openGL ES 吗?我不明白这个相机类是什么。 【参考方案1】:

我认为你的投影矩阵是错误的,主要是因为你根本没有使用变量aspectRatio,但是你这样做的方式看起来是正确的..? (所以这只是我的猜测:P)

这是我使用纵横比参数在 C 中制作投影矩阵的方法,也许这会有所帮助

mat4 set_perspective_matrix(GLfloat fov, GLfloat aspect, GLfloat nearPlane, GLfloat farPlane)


    mat4  p;

    GLfloat f = 1.0/ tan(fov * 3.1415926/360.0);
    GLfloat c1 = -(farPlane + nearPlane) / (farPlane - nearPlane);
    GLfloat c2 = -(2.0 * farPlane * nearPlane) / (farPlane - nearPlane);

    p._[0] = f/aspect;
    p._[1] = 0.0;
    p._[2] = 0.0;
    p._[3] = 0.0;

    p._[4] = 0.0;
    p._[5] = f;
    p._[6] = 0.0;
    p._[7] = 0.0;

    p._[8]  = 0.0;
    p._[9]  = 0.0;
    p._[10] = c1;
    p._[11] = c2;

    p._[12] = 0.0;
    p._[13] = 0.0;
    p._[14] =-1.0;
    p._[15] = 0.0; 

    return p;

这是一篇描述投影矩阵设置的好文章:The Perspective Matrix

【讨论】:

他确实使用投影矩阵的纵横比 哦,我明白了。 (没有代码着色,我迷路了)好吧,也许这仍然有帮助 @bitflip-at 我用这个透视矩阵做了一些工作,比如 BSP Tree 3D,但我想我从来没有调整过调整后的大小。今晚我会试试你的建议。你可能是对的。 @bitflip-at 为了与 OpenGL 一起使用,这个投影矩阵必须被转置。 @bitflip-at 不幸的是,我尝试了代码并且发生了同样的事情。当我调整大小时,对象被翻译到窗口的右边框。但非常感谢您的提示。【参考方案2】:

问题出在 QT Windowing 上。使用以下代码调整大小已解决:

void QtOpenGLRenderer::resizeEvent(QResizeEvent* event) 
QSize size = event->size();

if (event->oldSize().isEmpty()) 

    initialScreenSize = size;
    return;


size = parentWidget->size();

float deltaX = size.width() - initialScreenSize.width();
float deltaY = size.height() - initialScreenSize.height();

renderer->resize(size.width() - deltaX, size.height() - deltaY); 

【讨论】:

以上是关于OpenGL Resize Window -> 对象被“移动/翻译”的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript/JQuery: $(window).resize 调整大小完成后如何触发?

在 Angular 2 中测试由“(window:resize)”事件触发的函数

jquery $(window).resize 事件在移动向上或向下滚动时触发

将div height设置为与window相同(在window resize时调整大小)

尝试使用 outerWidth() 和 $(window).resize() 水平居中动态宽度元素时的意外行为

vue中监听window.resize的变化