Xác định hình dạng

Việc có thể xác định hình dạng cần vẽ trong bối cảnh chế độ xem OpenGL ES là bước đầu tiên trong tạo đồ hoạ cao cấp cho ứng dụng của bạn. Vẽ bằng OpenGL ES có thể hơi phức tạp nếu không biết một số thông tin cơ bản về cách OpenGL ES muốn bạn xác định đối tượng đồ hoạ.

Bài học này giải thích về hệ toạ độ OpenGL ES liên quan đến màn hình thiết bị Android, kiến thức cơ bản về việc xác định hình dạng, mặt của hình dạng cũng như xác định tam giác và hình vuông.

Định nghĩa tam giác

OpenGL ES cho phép bạn xác định các đối tượng được vẽ bằng cách sử dụng toạ độ trong không gian ba chiều. Vì vậy, trước khi vẽ một hình tam giác, bạn phải xác định toạ độ của nó. Trong OpenGL, cách làm thông thường hàm này xác định một mảng đỉnh gồm các số có dấu phẩy động cho toạ độ. Tối đa hiệu quả, bạn sẽ viết các toạ độ này vào ByteBuffer, được chuyển vào Quy trình đồ hoạ OpenGL ES để xử lý.

Kotlin

// number of coordinates per vertex in this array
const val COORDS_PER_VERTEX = 3
var triangleCoords = floatArrayOf(     // in counterclockwise order:
        0.0f, 0.622008459f, 0.0f,      // top
        -0.5f, -0.311004243f, 0.0f,    // bottom left
        0.5f, -0.311004243f, 0.0f      // bottom right
)

class Triangle {

    // Set color with red, green, blue and alpha (opacity) values
    val color = floatArrayOf(0.63671875f, 0.76953125f, 0.22265625f, 1.0f)

    private var vertexBuffer: FloatBuffer =
            // (number of coordinate values * 4 bytes per float)
            ByteBuffer.allocateDirect(triangleCoords.size * 4).run {
                // use the device hardware's native byte order
                order(ByteOrder.nativeOrder())

                // create a floating point buffer from the ByteBuffer
                asFloatBuffer().apply {
                    // add the coordinates to the FloatBuffer
                    put(triangleCoords)
                    // set the buffer to read the first coordinate
                    position(0)
                }
            }
}

Java

public class Triangle {

    private FloatBuffer vertexBuffer;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float triangleCoords[] = {   // in counterclockwise order:
             0.0f,  0.622008459f, 0.0f, // top
            -0.5f, -0.311004243f, 0.0f, // bottom left
             0.5f, -0.311004243f, 0.0f  // bottom right
    };

    // Set color with red, green, blue and alpha (opacity) values
    float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };

    public Triangle() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
                // (number of coordinate values * 4 bytes per float)
                triangleCoords.length * 4);
        // use the device hardware's native byte order
        bb.order(ByteOrder.nativeOrder());

        // create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer();
        // add the coordinates to the FloatBuffer
        vertexBuffer.put(triangleCoords);
        // set the buffer to read the first coordinate
        vertexBuffer.position(0);
    }
}

Theo mặc định, OpenGL ES giả định một hệ toạ độ trong đó [0,0,0] (X,Y,Z) xác định tâm của khung GLSurfaceView, [1,1,0] là góc trên cùng bên phải của khung hình và [-1,-1,0] là góc dưới cùng bên trái của khung hình. Để biết hình minh hoạ hệ toạ độ này, hãy xem Nhà phát triển OpenGL ES hướng dẫn.

Lưu ý rằng toạ độ của hình dạng này được xác định theo thứ tự ngược chiều kim đồng hồ. Bản vẽ rất quan trọng vì nó xác định mặt nào là mặt trước của hình dạng, mà bạn thường muốn vẽ và mặt sau (bạn có thể chọn không vẽ bằng cách sử dụng bộ chọn OpenGL ES khuôn mặt. Để biết thêm thông tin về các khuôn mặt và danh sách chọn khuôn mặt, hãy xem Hướng dẫn cho nhà phát triển OpenGL ES.

Xác định hình vuông

Xác định tam giác khá dễ dàng trong OpenGL, nhưng nếu bạn muốn nhận thêm một chút phức tạp không? Bạn có muốn chọn hình vuông không? Có một số cách để thực hiện điều này, nhưng cách thức thông thường để vẽ hình dạng trong OpenGL ES sử dụng hai hình tam giác được vẽ cùng nhau:

Hình 1. Vẽ hình vuông bằng hai hình tam giác.

Xin nhắc lại, bạn nên xác định các đỉnh theo thứ tự ngược chiều kim đồng hồ cho cả hai tam giác biểu thị hình dạng này và đặt các giá trị vào ByteBuffer. Để tránh xác định hai toạ độ mà mỗi tam giác dùng chung hai lần, hãy sử dụng danh sách vẽ để cho Quy trình đồ hoạ của OpenGL ES cách vẽ các đỉnh này. Đây là mã cho hình dạng này:

Kotlin

// number of coordinates per vertex in this array
const val COORDS_PER_VERTEX = 3
var squareCoords = floatArrayOf(
        -0.5f,  0.5f, 0.0f,      // top left
        -0.5f, -0.5f, 0.0f,      // bottom left
         0.5f, -0.5f, 0.0f,      // bottom right
         0.5f,  0.5f, 0.0f       // top right
)

class Square2 {

    private val drawOrder = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw vertices

    // initialize vertex byte buffer for shape coordinates
    private val vertexBuffer: FloatBuffer =
            // (# of coordinate values * 4 bytes per float)
            ByteBuffer.allocateDirect(squareCoords.size * 4).run {
                order(ByteOrder.nativeOrder())
                asFloatBuffer().apply {
                    put(squareCoords)
                    position(0)
                }
            }

    // initialize byte buffer for the draw list
    private val drawListBuffer: ShortBuffer =
            // (# of coordinate values * 2 bytes per short)
            ByteBuffer.allocateDirect(drawOrder.size * 2).run {
                order(ByteOrder.nativeOrder())
                asShortBuffer().apply {
                    put(drawOrder)
                    position(0)
                }
            }
}

Java

public class Square {

    private FloatBuffer vertexBuffer;
    private ShortBuffer drawListBuffer;

    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 3;
    static float squareCoords[] = {
            -0.5f,  0.5f, 0.0f,   // top left
            -0.5f, -0.5f, 0.0f,   // bottom left
             0.5f, -0.5f, 0.0f,   // bottom right
             0.5f,  0.5f, 0.0f }; // top right

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

    public Square() {
        // initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 4 bytes per float)
                squareCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareCoords);
        vertexBuffer.position(0);

        // initialize byte buffer for the draw list
        ByteBuffer dlb = ByteBuffer.allocateDirect(
        // (# of coordinate values * 2 bytes per short)
                drawOrder.length * 2);
        dlb.order(ByteOrder.nativeOrder());
        drawListBuffer = dlb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);
    }
}

Ví dụ này cung cấp cho bạn thông tin sơ bộ về những việc cần làm để tạo hình dạng phức tạp hơn bằng OpenGL. Trong nói chung, bạn sẽ sử dụng các bộ sưu tập tam giác để vẽ các đối tượng. Trong bài học tiếp theo, bạn sẽ học cách vẽ các hình dạng này trên màn hình.