OpenGLES3.0_Example/Chapter_2/app/src/main/cpp/Scene/ManyCubes.cpp at main · dlgmlals3/OpenGLES3.0_Example
Contribute to dlgmlals3/OpenGLES3.0_Example development by creating an account on GitHub.
github.com
RenderPlus()
좌표계 변환 >
ScreenCoord = Viewport × Projection × View × Model × Vertex
Transform (변환)
Transform은 객체의 위치, 크기, 회전을 변경하는 과정이다. 그래픽에서 기본적인 변환은 다음과 같다.
일반적인 3D 그래픽에서는 이동, 회전, 스케일 변환을 조합하여 모델링 변환을 수행함.
===========================================================
Translation, Scale, Rotation 함수를 알아본다.
void Transform::TransformSetMatrixMode( unsigned int mode )
{
TransformMemData.matrix_mode = mode;
}
void Transform::TransformTranslate( float x, float y, float z )
{
glm::vec3 v( x, y, z );
switch( TransformMemData.matrix_mode )
{
case MODEL_MATRIX:
{
*TransformGetModelMatrix() = glm::translate( *TransformGetModelMatrix(), v);
break;
}
case VIEW_MATRIX:
{
*TransformGetViewMatrix() = glm::translate( *TransformGetViewMatrix(), v);
break;
}
case PROJECTION_MATRIX:
{
*TransformGetProjectionMatrix() = glm::translate( *TransformGetProjectionMatrix(), v);
break;
}
case TEXTURE_MATRIX:
{
*TransformGetTextureMatrix() = glm::translate( *TransformGetTextureMatrix(), v);
break;
}
}
}
/*!
Rotate the current matrix pointed for the current mode.
\param[in] angle Specifies the angle of rotation, in degrees.
\param[in] x Specify the x coordinate of a vector.
\param[in] y Specify the y coordinate of a vector.
\param[in] z Specify the z coordinate of a vector.
*/
void Transform::TransformRotate( float angle, float x, float y, float z )
{
if( !angle ) return;
glm::vec3 v( x, y, z);
switch( TransformMemData.matrix_mode )
{
case MODEL_MATRIX:
{
*TransformGetModelMatrix() = glm::rotate( *TransformGetModelMatrix(), angle, v );
break;
}
case VIEW_MATRIX:
{
*TransformGetViewMatrix() = glm::rotate( *TransformGetViewMatrix(), angle, v );
break;
}
case PROJECTION_MATRIX:
{
*TransformGetProjectionMatrix() = glm::rotate( *TransformGetProjectionMatrix(), angle, v );
break;
}
case TEXTURE_MATRIX:
{
*TransformGetTextureMatrix() = glm::rotate( *TransformGetTextureMatrix(), angle, v );
break;
}
}
}
/*!
Scale the current matrix pointed for the current mode.
\param[in] x Specify scale factor along the x axis.
\param[in] y Specify scale factor along the y axis.
\param[in] z Specify scale factor along the z axis.
*/
void Transform::TransformScale( float x, float y, float z )
{
static glm::vec3 scale( 1.0f, 1.0f, 1.0f );
glm::vec3 v( x, y, z );
if( !memcmp( &v, &scale, sizeof( glm::vec3 ) ) ) return;
switch( TransformMemData.matrix_mode )
{
case MODEL_MATRIX:
{
*TransformGetModelMatrix() = glm::scale(*TransformGetModelMatrix(), v);
break;
}
case VIEW_MATRIX:
{
*TransformGetViewMatrix() = glm::scale(*TransformGetViewMatrix(), v);
break;
}
case PROJECTION_MATRIX:
{
*TransformGetProjectionMatrix() = glm::scale(*TransformGetProjectionMatrix(), v);
break;
}
case TEXTURE_MATRIX:
{
*TransformGetTextureMatrix() = glm::scale(*TransformGetTextureMatrix(), v);
break;
}
}
}
해당 코드에서 하나의 씬을 렌더링 과정을 살펴보면
Translation을 하고 현재 공간에 매트릭스를 스택에 쌓아 놓는다.
스택에 쌓는 이유는 매트릭스를 변형하고 다시 복원을 해야될때 사용이 된다.
보통 셰이더에서 MVP 변수 하나를 사용하기 때문에,
여러개의 행렬 변수를 사용하지 않고, 각 공간마다 하나의 MVP 행렬을 관리한다.
TransformObj->TransformPushMatrix();
TransformObj->TransformPopMatrix();
RenderCubeOfCubes 함수에서 렌더링되는 것을 하나의 씬으로 생각하자.
실습 T 자 모양을 만들어본다.
과제 ) ㄴ 자 모양을 만들어보자.
=============================================================
Projection (투영)
- FOV: 60도
- Aspect Ratio: 16:9
- Near / Far Plane: 0.1 ~ 100
📌 FOV는 보통 45~90도 사이로 설정
📌 Near 값을 너무 작게 설정하면 Z-fighting 발생 가능
==========================================================================================
위에서 적용한 단계는 RTS를 곱하여 월드스페이스로 변환을 한 단계이다.
월드 -> 뷰 -> 클립 변환을 할 차례이다.
현재 어느공간에 알기 위한 함수는 아래와 같다
위에서 T를 만들때는 모델 스페이스로 설정되어 있을 것이다.
Transform::PrintMatrixMode
enum
{
MODEL_MATRIX = 0,
VIEW_MATRIX = 1,
PROJECTION_MATRIX = 2,
TEXTURE_MATRIX = 3
};
TransformSetMatrixMode(PROJECTION_MATRIX) 설정하면
이후로 Transform을 변경하면 투영 행렬이 변경이 된다.
아래 코드에서 Model, View, Projection 행렬을 설정 하는 것을 볼 수있다.
void Renderer::setUpProjection()
{
ProgramManager* ProgramManagerObj = &RenderMemData.ProgramManagerObj;
Transform* TransformObj = &RenderMemData.TransformObj;
float span = 10.0;
float depth = 50.0;
bool considerAspectRatio = true;
RenderMemData.isPerspective = true;
TransformObj->TransformInit();
TransformObj->TransformSetMatrixMode( PROJECTION_MATRIX );
TransformObj->TransformLoadIdentity();
if ( considerAspectRatio ){
GLfloat aspectRatio = (GLfloat)RenderMemData.screenWidth / (GLfloat)RenderMemData.screenHeight;
if ( RenderMemData.isPerspective ){
TransformObj->TransformSetPerspective(60.0f, aspectRatio, 0.01, 1000, 0);
} else {
if ( RenderMemData.screenWidth <= RenderMemData.screenHeight ){
TransformObj->TransformOrtho( -span, span, -span / aspectRatio, span / aspectRatio, -span, depth);
}
else{
TransformObj->TransformOrtho( -span * aspectRatio, span * aspectRatio, -span, span, -span, depth);
}
}
}
else{
if ( RenderMemData.isPerspective ){
TransformObj->TransformSetPerspective(60.0f, 1, 1.0, 1000, 0);
}
else{
TransformObj->TransformOrtho( -span, span, -span, span, -span, depth );
}
}
TransformObj->TransformSetMatrixMode( VIEW_MATRIX );
TransformObj->TransformLoadIdentity();
TransformObj->TransformTranslate(3.0, 0.0, -depth); /// !!
TransformObj->TransformSetMatrixMode( MODEL_MATRIX );
TransformObj->TransformLoadIdentity();
}
RenderMemData.isPerspective를 true하면 원근 투영, false이면 직교투영이다.
모델 스페이스에서 회전도 다음과 같이 해보자.
void ManyCubes::Render()
{
glEnable( GL_DEPTH_TEST );
glUseProgram( program->ProgramID );
TransformObj->PrintMatrixMode();
TransformObj->TransformRotate(k++, 1, 1, 1);
RenderPlus();
}
원근 투영과 직교 투영의 가장 큰 차이를 보려면 z축이 다른 물체를 나란히 놓으면 확인 할 수 있다.
직교 투영의 경우 동일한 크기의 물체의 경우 멀리 있거나, 가까이 있거나 동일하게 보이기 때문에
z축이 다른 물체들이 나란히 있으면 물체를 인식하기 어렵다.
직교 투영된 물체의 크기를 크게 하려면 카메라 행렬 z값을 변환해도 크게되지 않으니
직교 투영 범위를 좁게 만들자. (span 값)
'Opengles 3.0 with Android' 카테고리의 다른 글
Chapter 2.1 Shader Build (0) | 2025.02.22 |
---|---|
Chapter 2.4 Culling (0) | 2025.02.21 |
Chapter 2.6 Touch Event ( Skip ) (1) | 2025.02.21 |
Chapter 2.2 VBO, EBO, VAO (0) | 2025.02.21 |
Chapter 1.0 EGL Context ( Skip ) (0) | 2025.02.21 |