An overview of the

This is a new series, learn OpengGl Es, actually is “OpenGl Es Application Development Practice Guide Android volume” study notes, interested can directly read this book, of course, this will record their own understanding, the following only as notes, in case you forget later

The first nine chapters of the book will then be analyzed in turn

Android OpenGl Es learning (a) : create an OpenGl Es program

Android OpenGl Es learning (2) : define vertices and shaders

Android OpenGl Es learning (3) : build shaders

Android OpenGl Es learning (4) : add color

Android OpenGl Es learning (5) : adjust the aspect ratio

Android OpenGl Es Learning (vi) : Enter 3d

Android OpenGl Es learning (7) : Using textures

Android OpenGl Es Learning (8) : Build simple objects

Add touch feedback to Android OpenGl Es

The end result is a simple game of hockey, something like this

Define the vertices

So here we see the final result, but first let’s make it simple, one rectangle, one line, two points

We see that a rectangle is actually made up of four vertices, and then we connect the four vertices into a line

Points, lines, triangles

So in OpenGl you can only draw points, sublines, triangles, so you can’t draw a rectangle directly, you have to break up a rectangle into triangles, and then form a rectangle again

As shown in the figure, a rectangle is divided into two triangles

Define vertices in your code

In your code these vertices are represented as floating-point arrays. Because they are two-dimensional coordinates, each vertex is recorded with two floating-point arrays, one marking the X-axis position and one marking the Y-axis position. This array is often called an attribute array

  float[] tableVertices = {
                // First triangle
                0f.0f.9f.14f.0.14f.// Second triangle
                0f.0f.9f.0f.9f.14f};Copy the code

This array represents two triangles, each in counterclockwise order, with four vertices, each of which shares two vertices

Add lines and points

   float[] tableVertices = {
            // First triangle
            0f.0f.9f.14f.0.14f.// Second triangle
            0f.0f.9f.0f.9f.14f./ / line
            0f.7f.9f.7f./ / points
            4.5 f.2f.4.5 f.12f
    };
Copy the code

Make the data available to OpengL

We have defined vertices above, but our Java code runs on a virtual machine, while OpengL runs on local hardware. So how do we make Java data available to OpengL?

  • The first one is JNI, if you need to know about it, check out my previous blog
  • The second is to change the way memory is allocated. Java has a special set of classes that allocate local chunks of memory and copy Java data into local memory

Let’s look at the code

private final int BYTES_PER_FLOAT = 4;
				
FloatBuffer verticeData = ByteBuffer.allocateDirect(tableVertices.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(tableVertices);
        verticeData.position(0);
Copy the code

Each floating-point number has 32 bits of precision and each byte has 8 bits of precision, so each floating-point number takes up 4 bytes

methods describe
ByteBuffer.allocateDirect Allocates a block of local memory, the size of which is passed in from outside
order(ByteOrder.nativeOrder()) Tells the buffer to organize content in local byte order
asFloatBuffer() We want to operate on Float, and calling this method returns FloatBuffer
put() Fill in the data
position() Moves the data subscript to the specified position

Opengl pipeline

Now that OpengL has the data, before they can draw the rectangle to the screen, they also need to pass it through opengL’s pipelines. This step requires the use of shaders. These shaders tell the GRAPHICS processing unit (CPU) how to draw the data

  • Vertex shader: Generates the final position of each vertex. It executes the position once for each vertex. Once the position is determined, OpengL can assemble these vertices into points, lines, and triangles
  • Fragment shader: Generates the final color for each fragment that consists of points, lines, and triangles. It performs this once for each fragment. A fragment is a small, rectangular area of a single color, similar to a pixel on a computer screen

Once the final colors are generated, OpengL writes them to a block of memory called a frame buffer, which Android then displays on the screen

Rasterization technique

Mobile devices display is composed of hundreds of millions of independent panel parts, they are called pixels, each of these pixels have the ability to display one of the millions of colors, each pixel is actually made up of three separate subcomponents, they emit red, blue, green light, because each pixel is very small, people’s eyes, would have been red, green and blue mix tube, It creates a huge amount of color, and you only need as many pixels to show what you want

Opengl through rasterization process, each of the points, lines, triangles, decomposed into lots of small fragments, pixel mapping to a mobile device, so as to generate the image, these small fragments is similar to that of the pixels on the screen, each containing a single pure color, to show the color, each fragment has four components, red, blue, green, to represent the color, The Alpha component is used to indicate transparency

GLSL

Opengl Shader Language(GLSL) is an opengL Shader Language used to create vertex shaders. If you want to learn more about this Language, please refer to the OpengL Shader GLSL Manual

Basic data types

type instructions
void An empty type that does not return any value
bool Boolean type true, false
int A signed integer
float A signed floating point number
vec2, vec3, vec4 N-dimensional floating point vector, including 2, 3, and 4 elements of the floating point vector
bvec2, bvec3, bvec4 N-dimensional Boolean vectors, Boolean vectors with 2, 3, and 4 elements
ivec2, ivec3, ivec4 N-dimensional orthopaedics vector, orthopaedics vector with 2, 3, and 4 elements
mat2, mat3, mat4 2✖️2, 3✖️ 3,4 ✖️4, floating point matrix
sampler2D 2 d texture
samplerCube Cube texture

Basic structures and arrays

type describe
structure Struct type-name{} is similar to a c language structure
An array of Float Foo [3] GLSL only supports 1-dimensional arrays, which can be members of a structure

Variable qualifier

The modifier describe
none (omitted by default) Local variables are readable and writable, and function inputs are such variables
const Declare the arguments of a variable or function as read-only types
attribute There can only be vertex shaders, which are typically used to hold vertex or normal data and can be read from a buffer
uniform Shader cannot change uniform variables at runtime. The first version is used to place transformation matrices, materials, and lighting parameters passed to the shader by the program
varying Responsible for data transfer between Vertex and fragment

Parameter qualifier

Function parameters are passed by default as copies, that is, value passes. Any variable passed to a function is copied and passed internally. We can also add qualifiers to achieve the effect of passing by reference

type describe
The default The in qualifier is used by default
in What is passed to a function is a copy of the parameter. Modifying the parameter value inside the function does not affect the parameter variable itself
out The value of a parameter is not passed to the function, but if you change the value inside the function, the value of the parameter will change after the function ends
inout The arguments passed to the function are references, and when the value is changed internally, the arguments change

function

GLSL allows functions to be declared on the outermost side of a program. Functions cannot be nested, cannot be called recursively, and must declare a return value type (void if there is no return value), otherwise like C functions

vec4 getPosition(a){ 
    vec4 v4 = vec4(0..0..0..1.);
    return v4;
}
 
void doubleSize(inout float size){
    size= size*2.0  ;
}
void main(a) {
    float psize= 10.0;
    doubleSize(psize);
    gl_Position = getPosition();
    gl_PointSize = psize;
}
Copy the code

Type conversion

GLSL can use constructors for display type conversions

bool t= true;
bool f = false;
 
int a = int(t); //true converts to 1 or 1.0
int a1 = int(f);//false converts to 0 or 0.0
 
float b = float(t);
float b1 = float(f);
 
bool c = bool(0);//0 or 0.0 is converted to false
bool c1 = bool(1);// Non-0 converts to true
 
bool d = bool(0.0);
bool d1 = bool(1.0);
Copy the code

Precision limit

GLSL, when rasterizing, does a lot of floating point operations that the device may not be able to handle, so GLSL offers three floating-point precision options that can be selected for different devices

Add highP mediump lowp before variable to declare precision

lowp float color;
varying mediump vec2 Coord;
lowp ivec2 foo(lowp mat3);
highp mat4 m;
Copy the code

In addition to the precision qualifier, we can also specify the precision to be used by default. If a variable does not use a precision qualifier, the default precision is used. The default precision qualifier is placed at the beginning of the shader code, as in:

precision highp float;// Defaults to high-precision float
precision mediump int;// Default medium precision int
Copy the code

Invariant keyword:

This can cause some problems, especially when vertex shader is passing values to fragment shader. In addition to this, we can use #pragma STDGL invariant(all) to ensure that all outputs are uniform, which limits the compiler’s optimization and reduces performance

#pragma STDGL invariant(all) // All output variables are invariant
invariant varying texCoord; // VARYING is declared as invariant when passing data
Copy the code

Built-in special variables

GLSL uses some special built-in variables to communicate with the hardware, which can be roughly divided into two types. One type is input, which is responsible for sending data to the hardware, and the other type is output, which is responsible for sending data back to the program for convenient programming needs

In the vertex shader

The built-in variable for output

variable describe
highp vec4 gl_Position; Gl_Position places vertex coordinate information
mediump float gl_PointSize; Gl_PointSize Specifies the size of the drawing point

In the fragment shader

A built-in variable of type input

variable describe
mediump vec4 gl_FragCoord; The relative positions of the elements in the framebuffer
bool gl_FrontFacing; Flags whether the current icon is part of the front icon
mediump vec2 gl_PointCoord; The interpolated texture coordinates range from 0.0 to 1.0

Built-in variable of type output

variable describe
mediump vec4 gl_FragColor; The relative positions of the elements in the framebuffer
mediump vec4 gl_FragData[n] Sets the color of the current slice, using the glDrawBuffers data array

Built-in function

Refer to the link above and I won’t continue writing here

Create a vertex shader

First we create a raw folder in res, then create a new file vertex_shader.glsl, and write the code in GLSL

 attribute vec4 a_Position;

  void main() {
      gl_Position =  a_Position;
      gl_PointSize=10.0;
   }
Copy the code

For each vertex we define, the vertex shader is called once, and when it is called, it accepts the position of the current vertex in the gl_Position property

The main function is the entrance to the shader, and all it needs to do is assign the position defined earlier to the specified output variable gl_Position, and this shader assigns a value to gl_Position, and OpengL takes the value stored in gl_Position as the final position of the vertex, and assembles those vertices into points, lines, triangle

Create the fragment shader

Let’s create a new file fragment_shader.glsl

 precision mediump float;
 uniform vec4 u_Color;
   void main() {
        gl_FragColor = u_Color;
    }
Copy the code

The first line sets the precision

Uniform Unlike the property that sets one for every vertex, a UNIFORM uniform will make every vertex use the same value unless we change them

The main function is the entrance to the shader, and then assigns the uniform definition of color to the special output variable gl_FragColor