투영 및 카메라 보기 적용

OpenGL ES 환경에서 투영 및 카메라 보기를 사용하면 육안으로 실제 객체를 보는 것과 더 비슷한 방식으로 그린 객체를 표시할 수 있습니다. 이 실제 보기 시뮬레이션은 그린 객체의 좌표를 수학적으로 변환하여 실행됩니다.

  • 투영 - 이 변환은 그린 객체가 표시되는 GLSurfaceView의 너비와 높이를 기준으로 그린 객체의 좌표를 조정합니다. 이 계산이 없으면 뷰 창의 비율이 같지 않으면 OpenGL ES에서 그린 객체가 기울어집니다. 일반적으로 투영 변환은 OpenGL 뷰의 비율이 설정되거나 렌더기의 onSurfaceChanged() 메서드에서 변경될 때만 계산해야 합니다. OpenGL ES 투영 및 좌표 매핑에 관한 자세한 내용은 그린 객체의 좌표 매핑을 참고하세요.
  • 카메라 뷰 - 이 변환에서는 가상 카메라 위치를 기반으로 그린 객체의 좌표를 조정합니다. OpenGL ES는 실제 카메라 객체를 정의하는 것이 아니라 그린 객체의 표시를 변환하여 카메라를 시뮬레이션하는 유틸리티 메서드를 제공한다는 점에 유의해야 합니다. 카메라 뷰 변환은 GLSurfaceView를 설정할 때 한 번만 계산되거나 사용자 작업 또는 애플리케이션의 함수에 따라 동적으로 변경될 수 있습니다.

이 과정에서는 투영과 카메라 뷰를 만들어 GLSurfaceView에 그린 도형에 적용하는 방법을 설명합니다.

프로젝션 정의

투영 변환 데이터는 GLSurfaceView.Renderer 클래스의 onSurfaceChanged() 메서드에서 계산됩니다. 다음 코드 예에서는 GLSurfaceView의 높이와 너비를 가져와 Matrix.frustumM() 메서드로 투영 변환 Matrix을 채웁니다.

Kotlin

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private val vPMatrix = FloatArray(16)
private val projectionMatrix = FloatArray(16)
private val viewMatrix = FloatArray(16)

override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) {
    GLES20.glViewport(0, 0, width, height)

    val ratio: Float = width.toFloat() / height.toFloat()

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
}

Java

// vPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

    // this projection matrix is applied to object coordinates
    // in the onDrawFrame() method
    Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}

이 코드는 투영 행렬인 mProjectionMatrix를 채웁니다. 그러면 다음 섹션에 나오는 onDrawFrame() 메서드에서 이 행렬을 카메라 뷰 변환과 결합할 수 있습니다.

참고: 그리기 객체에 투영 변환을 적용하기만 하면 일반적으로 빈 화면이 표시됩니다. 일반적으로 화면에 무엇이든 표시하려면 카메라 뷰 변환도 적용해야 합니다.

카메라 보기 정의

렌더기에서 그리기 프로세스의 일부로 카메라 뷰 변환을 추가하여 그린 객체의 변환 프로세스를 완료합니다. 다음 코드 예에서 카메라 뷰 변환은 Matrix.setLookAtM() 메서드를 사용하여 계산된 다음 이전에 계산된 투영 행렬과 결합됩니다. 그런 다음 결합된 변환 행렬이 그려진 도형에 전달됩니다.

Kotlin

override fun onDrawFrame(unused: GL10) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0)

    // Draw shape
    triangle.draw(vPMatrix)

Java

@Override
public void onDrawFrame(GL10 unused) {
    ...
    // Set the camera position (View matrix)
    Matrix.setLookAtM(viewMatrix, 0, 0, 0, 3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    // Calculate the projection and view transformation
    Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

    // Draw shape
    triangle.draw(vPMatrix);
}

투영 및 카메라 변환 적용

미리보기 섹션에 표시된 결합된 투영과 카메라 보기 변환 행렬을 사용하려면 먼저 이전에 Triangle 클래스에서 정의한 꼭짓점 셰이더에 행렬 변수를 추가합니다.

Kotlin

class Triangle {

    private val vertexShaderCode =
            // This matrix member variable provides a hook to manipulate
            // the coordinates of the objects that use this vertex shader
            "uniform mat4 uMVPMatrix;" +
            "attribute vec4 vPosition;" +
            "void main() {" +
            // the matrix must be included as a modifier of gl_Position
            // Note that the uMVPMatrix factor *must be first* in order
            // for the matrix multiplication product to be correct.
            "  gl_Position = uMVPMatrix * vPosition;" +
            "}"

    // Use to access and set the view transformation
    private var vPMatrixHandle: Int = 0

    ...
}

Java

public class Triangle {

    private final String vertexShaderCode =
        // This matrix member variable provides a hook to manipulate
        // the coordinates of the objects that use this vertex shader
        "uniform mat4 uMVPMatrix;" +
        "attribute vec4 vPosition;" +
        "void main() {" +
        // the matrix must be included as a modifier of gl_Position
        // Note that the uMVPMatrix factor *must be first* in order
        // for the matrix multiplication product to be correct.
        "  gl_Position = uMVPMatrix * vPosition;" +
        "}";

    // Use to access and set the view transformation
    private int vPMatrixHandle;

    ...
}

그런 다음 그래픽 객체의 draw() 메서드를 수정하여 결합된 변환 행렬을 허용하고 도형에 적용합니다.

Kotlin

fun draw(mvpMatrix: FloatArray) { // pass in the calculated transformation matrix

    // get handle to shape's transformation matrix
    vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix")

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0)

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount)

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(positionHandle)
}

Java

public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix
    ...

    // get handle to shape's transformation matrix
    vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");

    // Pass the projection and view transformation to the shader
    GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0);

    // Draw the triangle
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

    // Disable vertex array
    GLES20.glDisableVertexAttribArray(positionHandle);
}

투영 및 카메라 뷰 변환을 올바르게 계산하고 적용하면 그래픽 객체가 올바른 비율로 그려지고 다음과 같이 표시됩니다.

그림 1. 투영 및 카메라 보기를 적용하여 그린 삼각형.

올바른 비율로 도형을 표시하는 애플리케이션이 있으므로 도형에 모션을 추가해 보겠습니다.