도형 그리기

OpenGL로 그릴 도형을 정의한 후 도형을 그릴 가능성이 높습니다. 도형 그리기 OpenGL ES 2.0을 사용하면 생각보다 약간 더 많은 코드가 필요합니다. API가 그래픽 렌더링 파이프라인을 상당히 제어할 수 있습니다

이 과정에서는 OpenGL을 사용하여 이전 과정에서 정의한 도형을 그리는 방법을 설명합니다. ES 2.0 API를 사용할 수 있습니다.

도형 초기화

그리기 전에 그릴 도형을 초기화하고 로드해야 합니다. 다만 과정 중에 프로그램에서 사용하는 도형의 구조 (원래 좌표)가 초기화하려면 onSurfaceCreated() 메서드 사용 메모리와 처리 효율성을 위한 렌더러입니다

Kotlin

class MyGLRenderer : GLSurfaceView.Renderer {
    ...
    private lateinit var mTriangle: Triangle
    private lateinit var mSquare: Square

    override fun onSurfaceCreated(unused: GL10, config: EGLConfig) {
        ...
        // initialize a triangle
        mTriangle = Triangle()
        // initialize a square
        mSquare = Square()
    }
    ...
}

자바

public class MyGLRenderer implements GLSurfaceView.Renderer {

    ...
    private Triangle mTriangle;
    private Square   mSquare;

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        // initialize a triangle
        mTriangle = new Triangle();
        // initialize a square
        mSquare = new Square();
    }
    ...
}

도형 그리기

OpenGL ES 2.0을 사용하여 정의된 도형을 그리려면 많은 양의 코드가 필요합니다. 그래픽 렌더링 파이프라인에 많은 세부 정보를 제공해야 합니다. 특히 있습니다.

  • 꼭짓점 셰이더 - 도형의 꼭짓점을 렌더링하는 OpenGL ES 그래픽 코드입니다.
  • 조각 셰이더 - 도형의 면을 색상 또는 음질로 렌더링하는 OpenGL ES 코드입니다. 합니다.
  • 프로그램 - 그리기에 사용할 셰이더가 포함된 OpenGL ES 객체입니다. 하나 이상의 셰이프

도형을 그리려면 하나 이상의 꼭짓점 셰이더가 있어야 하고 도형의 색상을 지정하려면 하나의 조각 셰이더가 있어야 합니다. 이러한 셰이더는 컴파일한 다음 OpenGL ES 프로그램에 추가해야 하며, 이후 OpenGL ES 프로그램을 사용하여 지정합니다. 다음은 Triangle 클래스:

Kotlin

class Triangle {

    private val vertexShaderCode =
            "attribute vec4 vPosition;" +
            "void main() {" +
            "  gl_Position = vPosition;" +
            "}"

    private val fragmentShaderCode =
            "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}"

    ...
}

자바

public class Triangle {

    private final String vertexShaderCode =
        "attribute vec4 vPosition;" +
        "void main() {" +
        "  gl_Position = vPosition;" +
        "}";

    private final String fragmentShaderCode =
        "precision mediump float;" +
        "uniform vec4 vColor;" +
        "void main() {" +
        "  gl_FragColor = vColor;" +
        "}";

    ...
}

셰이더에는 GLSL (OpenGL Shading Language) 코드가 포함되어 있으며 이 코드는 살펴보겠습니다 이 코드를 컴파일하려면 다음과 같이 렌더기 클래스에 유틸리티 메소드를 만들어야 합니다.

Kotlin

fun loadShader(type: Int, shaderCode: String): Int {

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
    return GLES20.glCreateShader(type).also { shader ->

        // add the source code to the shader and compile it
        GLES20.glShaderSource(shader, shaderCode)
        GLES20.glCompileShader(shader)
    }
}

자바

public static int loadShader(int type, String shaderCode){

    // create a vertex shader type (GLES20.GL_VERTEX_SHADER)
    // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
    int shader = GLES20.glCreateShader(type);

    // add the source code to the shader and compile it
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    return shader;
}

도형을 그리려면 셰이더 코드를 컴파일하고 OpenGL ES 프로그램에 추가해야 합니다. 객체를 만들고 프로그램을 연결합니다. 그린 객체의 생성자에서 이 작업을 수행하므로 합니다.

참고: OpenGL ES 셰이더를 컴파일하고 프로그램을 연결하는 작업은 비용이 많이 듭니다. CPU 주기 및 처리 시간 측면에서 볼 때 이 작업은 두 번 이상 하지 않는 것이 좋습니다. 만약 그렇다면 셰이더의 내용을 모르는 경우 셰이더에서만 한 번 생성된 다음 나중에 사용할 수 있도록 캐시됩니다.

Kotlin

class Triangle {
    ...

    private var mProgram: Int

    init {
        ...

        val vertexShader: Int = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        val fragmentShader: Int = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram().also {

            // add the vertex shader to program
            GLES20.glAttachShader(it, vertexShader)

            // add the fragment shader to program
            GLES20.glAttachShader(it, fragmentShader)

            // creates OpenGL ES program executables
            GLES20.glLinkProgram(it)
        }
    }
}

자바

public class Triangle() {
    ...

    private final int mProgram;

    public Triangle() {
        ...

        int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
                                        vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
                                        fragmentShaderCode);

        // create empty OpenGL ES Program
        mProgram = GLES20.glCreateProgram();

        // add the vertex shader to program
        GLES20.glAttachShader(mProgram, vertexShader);

        // add the fragment shader to program
        GLES20.glAttachShader(mProgram, fragmentShader);

        // creates OpenGL ES program executables
        GLES20.glLinkProgram(mProgram);
    }
}

이제 도형을 그리는 실제 호출을 추가할 준비가 되었습니다. 도형 그리기 OpenGL ES에서는 여러 매개변수를 지정하여 렌더링 파이프라인에 원하는 것을 알려야 합니다. 어떻게 그리는지 배우게 됩니다. 그리기 옵션은 모양에 따라 다를 수 있으므로 그리기 옵션을 설정하는 것이 좋습니다. 도형 클래스에는 고유한 그리기 로직이 포함되어 있습니다.

도형을 그리는 draw() 메서드를 작성합니다. 이 코드는 위치를 설정하고 색상 값을 도형의 꼭짓점 셰이더와 프래그먼트 셰이더에 적용한 다음 그리기를 실행합니다. 함수를 사용하세요.

Kotlin

private var positionHandle: Int = 0
private var mColorHandle: Int = 0

private val vertexCount: Int = triangleCoords.size / COORDS_PER_VERTEX
private val vertexStride: Int = COORDS_PER_VERTEX * 4 // 4 bytes per vertex

fun draw() {
    // Add program to OpenGL ES environment
    GLES20.glUseProgram(mProgram)

    // get handle to vertex shader's vPosition member
    positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition").also {

        // Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray(it)

        // Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer(
                it,
                COORDS_PER_VERTEX,
                GLES20.GL_FLOAT,
                false,
                vertexStride,
                vertexBuffer
        )

        // get handle to fragment shader's vColor member
        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor").also { colorHandle ->

            // Set color for drawing the triangle
            GLES20.glUniform4fv(colorHandle, 1, color, 0)
        }

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

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

자바

private int positionHandle;
private int colorHandle;

private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

public void draw() {
    // Add program to OpenGL ES environment
    GLES20.glUseProgram(mProgram);

    // get handle to vertex shader's vPosition member
    positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

    // Enable a handle to the triangle vertices
    GLES20.glEnableVertexAttribArray(positionHandle);

    // Prepare the triangle coordinate data
    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
                                 GLES20.GL_FLOAT, false,
                                 vertexStride, vertexBuffer);

    // get handle to fragment shader's vColor member
    colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

    // Set color for drawing the triangle
    GLES20.glUniform4fv(colorHandle, 1, color, 0);

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

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

이 모든 코드를 완성한 후에는 이 객체를 그리려면 draw() 메서드를 호출하여 onDrawFrame() 메서드를 호출합니다.

Kotlin

override fun onDrawFrame(unused: GL10) {
    ...

    mTriangle.draw()
}

자바

public void onDrawFrame(GL10 unused) {
    ...

    mTriangle.draw();
}

애플리케이션을 실행하면 다음과 같이 표시되어야 합니다.

그림 1. 투영 또는 카메라 보기 없이 그려진 삼각형.

이 코드 예에는 몇 가지 문제점이 있습니다. 우선, 고객에게 좋은 인상을 주지 친구. 두 번째로 삼각형이 약간 찌그러져 있으며 화면을 바꾸면 모양이 바뀝니다. 기기의 방향입니다. 도형이 기울어진 이유는 객체의 꼭짓점이 배치되는 화면 영역의 비율에 맞게 GLSurfaceView가 표시됩니다. 프로젝션과 카메라를 사용하면 이 문제를 해결할 수 있습니다. 다음 강의에서 살펴보겠습니다.

마지막으로 삼각형은 정지되어 있으므로 약간 지루한 느낌을 줍니다. 모션 추가 강의, 도형을 만드는 방법 OpenGL ES 그래픽 파이프라인을 좀 더 흥미롭게 사용할 수 있습니다.