Developing with OpenGL ES in Android Lesson (2): Defining Graphics

 

1. Preliminary basic knowledge reserve

The author plans to write three articles to analyze in detail the basics of OpenGL ES and the three key points of entry:

①What is OpenGL ES? What is the relationship with OpenGL? - Concept part

②The first step of using OpenGLES to draw 2D/3D graphics: define graphics; - application part

③ Use OpenGL ES to draw the graphics defined in the ② step: - the application part, where the difficulty lies

Through the analysis of these three articles, it is like laying the foundation stone for the high-rise building. The high-rise building starts from the ground, and then uses OpenGLES to do various effects. Various transformations are based on the understanding of these three steps of graphics programming.

In the previous article "Development with OpenGL ES in Android Lesson 1: Concept First" , the author analyzed some related concepts of OpenGL ES2.0 in detail, and simply implemented an OpenGL ES rendering Process, then the analysis of the article in this section today is based on the previous article, and continues to analyze the second key point of using OpenGL ES2.0 for graphics rendering - the definition of graphics .

(1) Why define graphics?

This question is a good question. OpenGL ES2.0 is a subset of OpenGL, and OpenGL is an API used to draw graphics, so OpenGL ES2.0 must also be used to draw graphics, but the drawn scene is placed in Android. . Whether it is a two-dimensional simple graphic or a complex three-dimensional image, its basic composition is a simple graphic. Like learning to draw a custom View, defining the shape of a graphic is the basis for implementing various complex graphics.

(2) What kind of graphs can we define?

In the world of OpenGL, we can only draw points, lines, and triangles , and complex graphics are composed of triangles.

For example, a rectangle is made up of two triangles.

(3) Steps to define graphics - core focus

①Define the floating-point buffer FloatBuffer of the coordinate data of the triangle vertex;

②Create an array triangleCoords[], which defines the coordinates of the three vertices of the triangle;

③ Define a constructor that implements three logics:

1) Initialize the byte buffer ByteBuffer of vertex coordinate data in the shape;

2) Obtain a basic type buffer from ByteBuffer, that is, a floating-point buffer FloatBuffer;

3) Put the coordinate array triangleCoords[] into FloatBuffer and define the reading order;

2. The above code, the specific implementation, take the drawing of a triangle as an example

First, we create a new triangle class ( public class Triangle {} ), and then follow the four steps mentioned above to take a look at the code:

The first step : define the floating-point buffer FloatBuffer of the coordinate data of the triangle vertices;

// Create a float buffer for vertex coordinates
private FloatBuffer vertexBuffer;

Vertex coordinates are generally specified by data of type float, so a floating-point buffer is specified here.

Step 2 : Create an array triangleCoords[], which defines the coordinates of the three vertices of the triangle;

// The number of vertex coordinates in the coordinate array
static final int COORDINATES_PRE_VERTEX = 3;
// In counterclockwise order, specify the coordinates and vertex coordinates respectively,
// Each vertex needs to specify three coordinates, which are the data in the direction of the X, Y, and Z coordinate axes;
static float triangleCoords[] = {  
        0.0f,  0.622008459f, 0.0f,  // top
        -0.5f, -0.311004243f, 0.0f, // bottom left
        0.5f, -0.311004243f, 0.0f   // bottom right
    };

Here, we need to define the coordinates of the three vertices respectively, and each coordinate needs to specify three parameters, corresponding to the data in the XYZ coordinate axis direction.

For more exciting content on OpenGL ES2.0 vertex coordinates,

It is recommended to refer to "Android OpenGl ES2.0 Programming_Related Concepts and Drawing Vertices"

Step 3 : Triple logic in the constructor:

1) Initialize the byte buffer ByteBuffer of vertex coordinate data in the shape;

// Initialize the byte buffer of vertex coordinate data in the shape
// Get the ByteBuffer instance through the allocateDirect() method of ByteBuffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(
        // The number of vertex coordinates * coordinate data type float, one is 4 bytes
        triangleCoords.length * 4
    );

2) Obtain a basic type buffer from ByteBuffer, that is, a floating-point buffer FloatBuffer;

// Since ByteBuffer is the only way to move data in and out of the channel, use
// Here use the "as" method to get a basic type buffer from the ByteBuffer byte buffer, that is, the floating-point buffer FloatBuffer
    vertexBuffer = byteBuffer.asFloatBuffer();

3) Put the coordinate array triangleCoords[] into FloatBuffer and define the reading order;

// Store the vertex coordinate information array triangleCoords[] to FloatBuffer
    vertexBuffer.put(triangleCoords);
// Set the vertex coordinate information to be read from the first position of the buffer
    vertexBuffer.position(0);

The complete code for this section is as follows:

public class Triangle {

    /**
     * A float buffer that defines the coordinate data of the triangle vertices
     */
    private FloatBuffer vertexBuffer;

    // The number of vertex coordinates in the coordinate array
    static final int COORDINATES_PRE_VERTEX = 3;
    static float triangleCoords[] = { // in counter-clockwise 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 the byte buffer of vertex coordinate data in the shape
        // Get the DirectByteBuffer instance through the allocateDirect method
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(
                // The number of vertex coordinates * coordinate data type float, one is 4 bytes
                triangleCoords.length * 4
        );

        // Set the buffer to read using the native byte order of the device hardware;
        byteBuffer.order(ByteOrder.nativeOrder());

        // ByteBuffer is the only way to move data in and out of the channel, here use the "as" method to get a primitive type buffer from the ByteBuffer
        vertexBuffer = byteBuffer.asFloatBuffer();
        // Store the vertex coordinate information array to FloatBuffer
        vertexBuffer.put(triangleCoords);
        // Set the vertex coordinate information to be read from the first position of the buffer
        vertexBuffer.position(0);
    }
}

Third, the above text, specifically analyze the ByteBuffer in the code

(1) What is ByteBuffer?

Buffer (Buffer), buffer (Buffer) is to reserve a specified size of storage space in memory for temporary storage of input/output (I/O) data, this part of reserved memory space is called buffer .

In Java NIO (Network Interface Object), the role of the buffer is also used to temporarily store data, which can be understood as a transfer station for data in I/O operations. The buffer directly serves the channel (Channel), writing data to the channel or reading data from the channel. Such operations can use the buffer data to transmit the data to achieve the purpose of efficient data processing. There are mainly eight buffer classes in NIO

Maybe readers have questions? So why are there two types of buffers in the above code - FloatBuffer and ByteBufer, and what is the relationship between them? - Readers should remember:

The buffer is of fixed length . Basically, it is just a list, and all its elements are of basic data types. For example, the coordinates of the graphics vertex in this example are floating-point data, so floating-point buffers are used to store floating-point data. type of data;

②The existence of the buffer is to serve the channel (Channel) , and the read and write methods of the channel only receive ByteBuffer, that is, only the buffer of this type of ByteBuffer can move data into and out of the channel, so all data types need to pass ByteBuffer. As a relay, use ByteBuffer to read and write other data types .

(2) Instance method of ByteBuffer

ByteBuffer has four instantiation methods, one of which is used in this example - allocateDirect().

①allocate(int capacity): allocate a byte array of capacity size from the heap space as the byte data memory of the buffer;

②allocateDirect(int capacity): The memory block is created by the operating system as a buffer, not in the JVM stack;

③wrap(byte[] array): The data of this buffer will be stored in the byte array;

④wrap(byte[] array, int offset, int length): On the basis of the previous method, the offset and length can be specified;

For more wonderful explanations of ByteBuffer, readers are recommended to refer to: "Detailed Explanation of Common Methods of ByteBuffer"


Summary: In this section, we mainly analyze how to define the vertex coordinates of the triangle, what needs to be done, and how to understand the key ByteBuffer. Careful readers may find that we only define the vertex coordinates of the triangle here, in other words, After the graphic is defined, it is not actually drawn. The draw() method does not appear in the code of the entire article, so there is no way to draw graphics.

Now that the graphics are defined in this section, we will start the most critical part - drawing graphics , high energy ahead!

PS: In this section, on the basis of the first section, another graphic class Triangle is defined, which will be the object of our long-term struggle in the future. Most of the key code will be implemented in this graphics class, the renderer class in the first section just provides some auxiliary methods or calls the methods defined in the graphics class. All in all, let the reader know: most of the critical code is implemented in the concrete graphics class, and as stated in the first article, this part is where the real pain lies.

>>>>Next>>>>: "Development with OpenGL ES in Android Lesson 3: Drawing Graphics"

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324935530&siteId=291194637