MacOS openGL 렌더링 시 화면 비율 문제

나우히즈·2024년 11월 1일

trialAndErrors

목록 보기
2/5

문제 상황

화면의 해상도를 640 * 480 으로 설정하였으나, 실행 후 첫 화면이 아래와 같이 4분의 1만 찍혀나오는 것을 확인하였음.

그 상태에서 창을 조금 움직이거나 크기를 조절하면 배경색이 입혀지는 일이 발생함.

로그를 찍어 창 크기를 확인해본 결과 아래와 같이 초기 설정한 값으로 윈도우가 생성되지 않고 이보다 width, height 모두 두 배씩 증가한 창으로 생성되는 상황이었음.

640 * 480 은 내가 처음 세팅한 창의 크기값이 맞는데, 창은 이의 두배 씩을 값으로 받아들여서 사실상 4분의 1만 렌더링이 되어 초기에 이미지로 출력되고 있는 상황임.


원인 파악

  • 입력 확인
    우선 WINDOW_WIDTH, WINDOW_HEIGHT 와 연관된 모든 변수들에 적절한 값이 들어가고 있는지를 확인함.
    -> 문제 없음.

  • 변수값 변경

SPDLOG_INFO("Create glfw window");	
auto window = glfwCreateWindow(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2, WINDOW_NAME, nullptr, nullptr); 

glfw에서 창을 생성하는 과정에서 창 크기를 입력받는 크기의 절반으로 생성하게 해보았음.

그 결과 정상적으로 창에 딱 맞는 사이즈로 생성됨을 확인함.

glfw에서 값을 이상하게 두배로 쓰는 것 같다는 생각이 들었음.
검색을 통해 유사한 증상을 겪는 사람들이 있는지 확인.

OpenGL created window size twice as large
https://stackoverflow.com/questions/35715579/opengl-created-window-size-twice-as-large

동일한 증상이 있었다.

현재 내가 사용하는 환경은 M1 macbook retina display로 고해상도 이미지를 지원하는 디스플레이다. 레티나 디스플레이는 일반적인 화면의 픽셀보다 작은 크기를 가지기 때문에 픽셀밀도가 높은 고해상도 디스플레이이다.

만약 내가 창의 크기로 200 * 100 만큼을 해상도로 주게 된다면, 레티나 디스플레이 환경에서는 픽셀밀도가 높기 때문에 이의 두배인 400 * 200 만큼의 픽셀을 사용하는 프레임버퍼가 생겨나는 것이다.

이후 쉐이더 처리 과정에서는 기존에 입력했던 창의 크기만큼의 해상도를 가지고 처리를 한다. 따라서 전체 프레임버퍼 영역의 좌측하단부에 렌더링이 되고 나머지는 비어져 나오는 것이었다.

창의 크기가 프레임버퍼 크기와 일치해야 창에 꽉 차게 렌더링되어 나올것임.
그래서 창의 크기를 기존에 입력하던 것의 절반으로 주었을 때, 딱 맞는 크기로 렌더링되었던 거였다.

원인 : 레티나 디스플레이 특성 상 일반 디스플레이 픽셀 하나에 4개의 픽셀이 구성된다. (픽셀밀도가 더 높아 고해상도 이미지가 나타나는 것)
-> 이에 따라 입력해준 창의 해상도 픽셀값의 가로 두 배 세로 두 배인 프레임 버퍼가 생성되었고, glViewport 함수에서 프레임버퍼의 렌더링영역을 기존 창크기로 설정하여 문제가 됨.


해결책

  1. 레티나 디스플레이 옵션 해제
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GL_FALSE);

glfw 에 레티나 디스플레이의 고해상도 픽셀 기능을 해제한다.
이렇게 하면 입력한 창의 크기 그대로 프레임버퍼가 생성되어 편하다.
다만 레티나 디스플레이가 가지는 고해상도의 강점을 잃는다.

실제로 렌더링해보면 상당히 저화질로 느껴진다...

  1. 프레임버퍼로 입력되는 사이즈를 맞춰주기.

기존에 창의 사이즈로 입력되는 사이즈의 두 배가 프레임버퍼로 적용되었으니,
프레임버퍼가 원하는 사이즈만큼으로 조정되게 해주었다.
하드코딩으로 "/ 2" 를 입력해주는게 좀 불편하지만 결과로는 위보다 고화질의 이미지를 얻을 수 있었다.

3개의 댓글

comment-user-thumbnail
2024년 11월 1일

옵션 해제 후 나름의 방법을 찾으셨군요

1개의 답글
comment-user-thumbnail
2025년 8월 27일

창 크기와 프레임버퍼를 일치하고 싶으면 glfwGetFramebufferSize 이 함수를 이용하시면 됩니다.

 int width, height;
 glfwGetFramebufferSize(window_, &width, &height);
 glViewport(0, 0, width, height);

비율을 알고 싶으면 glfwGetWindowContentScale 이 함수를 사용하시면 됩니다.

float x_scale, y_scale;
glfwGetWindowContentScale(window_, &x_scale, &y_scale);
답글 달기