momodudu.zip

#2 OpenGL/C++ glm library를 사용하는 간단한 예제들 본문

Graphics/OpenGL

#2 OpenGL/C++ glm library를 사용하는 간단한 예제들

ally10 2019. 9. 8. 05:09

음.. 매트릭스 관련해서 공부를 하고 있는데, glm 관련 예제가 별로 없어서 기록 겸 포스팅.

쓰기 어려운 라이브러리는 아닌데, 그냥 공부겸 기록겸....

 

일단 개발 환경은 모두 세팅된 상태여야함. 나는 glfw/opengl/c++입니당. 일단 2D상태의 아래와 같은 사각형이 있다.

뒤집어진건 신경쓰지말자..^^ Texture coord만져보다가 뒤집었다.

 

 

const char* vertexShaderSource =
{
	"#version 330 core\n"

	"#define IN_VERTEX	0\n"
	"#define IN_COLOR	1\n"
	"#define IN_TEXTURE 2\n"

	"layout (location=IN_VERTEX) in highp vec3 position;\n"
	"layout (location=IN_COLOR)	 in lowp vec3 colors;\n"
	"layout (location=IN_TEXTURE) in mediump vec2 texCoord;\n"

	"out mediump vec2 outTex;\n"

	"uniform highp mat4 transformationMat;\n"

	"void main()\n"
	"{\n"
	"	gl_Position = transformationMat*vec4(position,1.0);\n"
	"   outTex = texCoord;\n"
	"}\n"
};

나는 위와 같이 아주 간단한 vertex shader를 사용했다.

다른건 신경쓰지 말고, 지금은 행렬에 관한 포스팅이니 uniform으로 선언된 matrix와

built-in output인 gl_Position에 관한 연산만 신경쓰면 된다.

uniform value로 쉐이더 바깥에서 매트릭스를 전달하고자 한다.

일단 위의 상태는 기본 단위행렬만 전달하고 있는 상태다.

 

1. Translate

평행이동 행렬. 동작에 관한 설명은 구글링하면 엄-청 많이 나온다.

여기서는 실제로 어떻게 쓸지에 관해서만 포스팅한다. 즉, uniform value로 전달되는 matrix를 어떻게 변형하는지.

	glm::mat4 myMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.2f, 0.2f, 0.0f));
	glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "transformationMat"), 1, GL_FALSE, glm::value_ptr(myMatrix));

먼저 glm::translate를 사용하려면 glm/gtc/matrix_transform.hpp를 인클루드 해야한다.

첫번째 인자는 단위행렬을 줬고, 두번째로는 얼만큼 translate 할지? 에 대한 인자이다.

 

위 그림에서 형광펜으로 칠해놓은게 두번째 인자라고 할 수 있겠다. 나는 [(-1,-1),(1,1)]의 좌표를 사용하고 있으므로

x,y = (0.2,0.2)만큼 이동하도록 해놨다.

 

제일 처음 그림과 비교해보면 0.2,0.2씩 이동한게 보인다!

 

 

2. Scale

이번엔 확대/축소 행렬.

	glm::mat4 myMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.0f));
	glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "transformationMat"), 1, GL_FALSE, glm::value_ptr(myMatrix));

이번에는 제일 처음 상태에서 x,y를 각각 반으로 줄였다.

 

크기가 반으로 줄었다.

 

 

3. Rotate

이제 돌려보자.

Rotate는 구글링해서 나오는 행렬 표식만 봐도 Translate나 Rotate보단 쬐끔 복잡하다.

하지만 glm만 있다면 아주 쉽게 가능!

 

	glm::mat4 myMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(45.0f), glm::vec3(1.0f, 1.0f, 0.0f));
	glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "transformationMat"), 1, GL_FALSE, glm::value_ptr(myMatrix));

 첫번째 인자는 단위행렬. 두번째 인자는 얼마나 돌릴건지? 에 대한 인자다. 라디안으로 알아서 변경해주니 degree로 입력하면 된다. 대신, float type으로만 넣어야 합니당.

 

세번째 인자는 기준이 되는 축을 설정한다고 보면 된다. 지금 예제에서는 x,y축을 기준으로 돌렸습니다..

45도를 돌렸을 경우

 

180도를 돌렸을경우
360도를 돌렸을 경우! 원래랑 똑같기때문에 의미는 없지만..

 

4. 누적행렬

그럼 이제 위에서 했던 것들을 합쳐보고자 한다. 다 알겠지만, 위 세가지 transformation은 순서가 반드시 지켜져야 한다.

TransformationM = TranslateM*RotateM*ScaleM 안그러면 엉망이 됩니다.. 

 

즉 ScaleM을 먼저 수행하고, Rotate를 수행후에 translate를 수행해야 된다. 공식으로 그냥 TRS로 외우면 된다.

glm으로 작성한 코드는 아래와 같다.

	glm::mat4 myMatrix = glm::translate(glm::rotate(glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.0f)), glm::radians(45.0f), glm::vec3(1.0f,1.0f,0.0f)),glm::vec3(0.5f,0.5f,0.0f));

가독성 엉망.... 알기 쉽게 풀어쓰자면 이렇다.

 

	glm::mat4 myMatrix = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f, 0.5f, 0.0f));
	myMatrix = glm::rotate(myMatrix, glm::radians(45.0f), glm::vec3(1.0f, 1.0f, 0.0f));
	myMatrix = glm::translate(myMatrix, glm::vec3(0.5f, 0.5f, 0.0f));

 

먼저 크기를 반으로 줄이고(scale), 그다음에 x/y축을 기준으로 45도만큼 돌리고(rotate), 마지막으로 (+0.5,+0.5)만큼 평행이동 시킨다.

 

그러면 아래와 같은 결과를 얻을 수 있다.

 

TRS 순서를 안지키면 어떻게 되는지, 조금씩 바꿔가면서 해보면 알기 쉬울듯 :)