본문 바로가기

기타/컴퓨터 그래픽스 & OpenGL

[OpenGL] 리셰이프 콜백 / 2022.10.23

* 출처 : OpenGL로 배우는 3차원 컴퓨터 그래픽스, 한빛아카데미

 

리셰이프 이벤트는 1. 처음 윈도우를 열 때 2. 윈도우 위치를 옮길 때 3. 윈도우 크기를 조절할 때 발생한다

아래 코드는 원래 뷰 포트의 중심과 변경된 뷰 포트의 중심을 일치시키면서도 물체 크기와 종횡비를 그대로 유지하는 방법이다.

1. 흰색 바탕에 회색 사각형을 그리는 프로그램을 통해 설명해보자

 

#include <glut.h>
#include <gl/GL.h>
#include <gl/GLU.h>

void MyDisplay() {
	glClear(GL_COLOR_BUFFER_BIT); // 컬러 버퍼에 초기화 색을 가함
	glColor3f(0.5, 0.5, 0.5); //회색
	glBegin(GL_POLYGON); //사각형
		glVertex3f(-0.5, -0.5, 0.0);
		glVertex3f(0.5, -0.5, 0.0);
		glVertex3f(0.5, 0.5, 0.0);
		glVertex3f(-0.5, 0.5, 0.0);
	glEnd();
	glFlush();
}

void MyReshape(int NewWidth, int NewHeight) {
	glViewport(0, 0, NewWidth, NewHeight);
	// 뷰 포트의 폭과 높이의 증가율 계산
	GLfloat WidthFactor = (GLfloat)NewWidth / (GLfloat)300;
	GLfloat HeightFactor = (GLfloat)NewHeight / (GLfloat)300;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.0 * WidthFactor, 1.0 * WidthFactor, -1.0 * HeightFactor, 1.0 * HeightFactor, -1.0, 1.0);
	// 투상면의 크기 조절 -> 투상면과 뷰 포트의 종횡비가 일치 -> 왜곡 방지
}

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB);
	glutInitWindowSize(300, 300);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("OpenGL Example Drawing");
	glClearColor(1.0, 1.0, 1.0, 1.0); //초기화 색은 백색
	glutDisplayFunc(MyDisplay);
	glutReshapeFunc(MyReshape);
	glutMainLoop();
	return 0;
}

 

MyReshape(int NewWidth, int NewHeight) :

- 사용자가 윈도우 크기를 조절한 결과 GLUT가 읽어들인 윈도우 폭과 높이를 파라미터로 사용

- glViewport() : 뷰 포트 크기를 변경된 윈도우 크기와 일치시킴

- glOrtho() : 가시 부피의 모습을 조절함으로써 왜곡을 해소 -> 가시 부피 : 화면에 보이고자 하는 물체의 범위

- 뷰 포트의 폭과 높이의 증가율을 계산하여 glOrtho 함수를 이용해 투상면의 크기를 조절해 왜곡을 방지한다

 

300,300 윈도우 창

 

윈도우 창 크기 늘렸을 때

 

윈도우 창 크기 줄였을 때

 

2. 위 코드는 창의 크기를 늘리거나 줄여도 물체의 크기에는 변함이 없다.

창 크기의 변화율에 비례하여 물체의 크기도 변화하도록 해보자.

 

#include <glut.h>
#include <gl/GL.h>
#include <gl/GLU.h>

void MyDisplay() {
	glClear(GL_COLOR_BUFFER_BIT); // 컬러 버퍼에 초기화 색을 가함
	glColor3f(0.5, 0.5, 0.5); //회색
	glBegin(GL_POLYGON); //사각형
		glVertex3f(-0.5, -0.5, 0.0);
		glVertex3f(0.5, -0.5, 0.0);
		glVertex3f(0.5, 0.5, 0.0);
		glVertex3f(-0.5, 0.5, 0.0);
	glEnd();
	glFlush();
}

void MyReshape(int NewWidth, int NewHeight) {
	glViewport(0, 0, NewWidth, NewHeight);
	// 폭과 높이 중 작은 것에 맞추어서 물체 크기 변화
	GLfloat Min = NewWidth; 
	if (NewHeight < NewWidth) Min = NewHeight;
	// 뷰 포트의 폭과 높이의 증가율 계산
	GLfloat WidthFactor = (GLfloat)NewWidth / (GLfloat)Min;
	GLfloat HeightFactor = (GLfloat)NewHeight / (GLfloat)Min;
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-1.0 * WidthFactor, 1.0 * WidthFactor, -1.0 * HeightFactor, 1.0 * HeightFactor, -1.0, 1.0);
	// 투상면의 크기 조절 -> 투상면과 뷰 포트의 종횡비가 일치 -> 왜곡 방지
}

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB);
	glutInitWindowSize(300, 300);
	glutInitWindowPosition(0, 0);
	glutCreateWindow("OpenGL Example Drawing");
	glClearColor(1.0, 1.0, 1.0, 1.0); //초기화 색은 백색
	glutDisplayFunc(MyDisplay);
	glutReshapeFunc(MyReshape);
	glutMainLoop();
	return 0;
}

 

MyReshape(int NewWidth, int NewHeight) :

윈도우의 크기를 300, 300으로 고정해 두지 않고 NewWidth와 NewHeight 중 길이가 작은것 (Min) 에 맞추어 사각형의 크기가 변화한다.

 

창을 늘렸을 때
창을 줄였을 때