First, the drawing of multiple primitives

Most of the previous talk is to draw a primitive, here draw multiple primitives. The final effect is as follows:

This interface contains:

  1. The largest red sphere spinning
  2. A small blue ball revolving around a larger ball
  3. Fifty little blue spheres on the floor
  4. Green floor

1.1. Draw green floor

If we look at this floor metagraph, we see that to draw it, all we need to change is the position of x and z, and the position of y stays the same. So you can iterate through a set of vertex data with the same y value:

Floorbatch.begin (GL_LINES, 324);for(GLfloatX = 20.0; X < = 20.0 f; X += 0.5) {floorBatch.vertex3f (x, -0.55f, 20.0f); FloorBatch. Vertex3f (x, - 0.55 f, 20.0 f); FloorBatch. Vertex3f (20.0 f to 0.55 f, x); FloorBatch. Vertex3f (20.0 f, 0.55 f, x); } floorBatch.End();Copy the code

After setting the vertex data for the batch class, you just need to turn on draw in the render to finish drawing:

// Pass to the storage shader, GLT_SHADER_IDENTITY shader, This shader is only using the specified color on the screen in a cartesian coordinates by default the first rendering geometry shaderManager. UseStockShader (GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor); // Draw the floorbatch.draw ();Copy the code

1.2. Draw a big red ball

As mentioned earlier, the system comes with some primitives, and spheres are one of them. Then we can draw the sphere directly through the API.

GltMakeSphere (torusBatch, 0.4f, 40, 80);Copy the code

Let’s go to render:

  1. First, a timer is used to constantly change the Angle of rotation.
  2. To make the rotation look real I’m going to set up a point light source here.
  3. I’m going to shift it inward to make it easier to see
  4. Change objects before pushing
  5. Rotate the pixel Angle
  6. Set shader – Point light shader
  7. draw
  8. Out of the stack
// static CStopWatch rotTimer; // Rotate each drawing by an AnglefloatYRot = rotTimer. GetElapsedSeconds () * 60.0 f; M3DMatrix44f vLightPos = {0,10,5,1}; / / put the red ball to translation (convenient observation) modelViewMatrix. Translate (0, 0, 3); . / / rotate forward stack modelViewMatrix PushMatrix (); ModelViewMatrix.Rotate(yRot, 0, 1, 0); ShaderManager. UseStockShader (GLT_SHADER_POINT_LIGHT_DIFF, / / point source shader transformPipeline GetModelViewMatrix (), / / model view matrix TransformPipeline. GetProjectionMatrix (), / / projection matrix vLightPos, / / the source vTorusColor); // Batch-color torusbatch.draw (); / / draw modelViewMatrix PopMatrix (); // Rotate out of stackCopy the code

1.3. Draw 50 blue balls

To generate 50 blue balls in batch, we need to use an array to store the vertex data of the 50 balls:

// Set the vertex data to gltMakeSphere(sphereBatch, 0.1F, 13, 26);for (int i = 0; i < NUM_SPHERES; i++) {
    GLfloatX = (rand() % 200) -200) * 0.1f; // random x coordinates GLfloatZ = ((rand() % 200) -200) * 0.1f; // Random z-coordinate spheres[I].SetOrigin(x, 0, z); // Store the vertex data of a small ball}Copy the code

Go to render and draw the 50 balls:

// Draw 50 ballsfor(int i = 0; i < NUM_SPHERES; i++) { modelViewMatrix.PushMatrix(); / / ball into the stack modelViewMatrix. MultMatrix (the spheres [I]); / / set the vertex shaderManager. UseStockShader (GLT_SHADER_POINT_LIGHT_DIFF, / / point source shader transformPipeline. GetModelViewMatrix (), / / model view matrix TransformPipeline. GetProjectionMatrix (), / / projection matrix vLightPos, / / the source vSphereColor); // The primitive color sphereBatch.draw (); / / draw modelViewMatrix PopMatrix (); // ball out of stack}Copy the code

1.4. Draw the revolution ball

The ball goes around, which is:

  1. The x coordinate is always changing, it’s going around the y axis, and it’s just spinning.
  2. You can directly use the batch class of the little blue ball above, just reset the vertex data.
  3. Shift the ball, cause revolution
modelViewMatrix.PushMatrix(); Rotate(yRot * -2, 0, 1, 0); Rotate(yRot * -2, 0, 1, 0); / / around y axis rotation Angle modelViewMatrix. Translate (0.8 f, 0, 0); / / translation a little distance rotation, resulting in orbit effect shaderManager. UseStockShader (GLT_SHADER_POINT_LIGHT_DIFF, / / point source shader TransformPipeline. GetModelViewMatrix (), / / model view matrix transformPipeline. GetProjectionMatrix (), / / projection matrix vLightPos, / / light source position vSphereColor); // The primitive color sphereBatch.draw (); / / draw modelViewMatrix PopMatrix (); // The ball exits the stackCopy the code

1.5. Matters needing attention after completion of drawing

After drawing it, we need to Push it out of the stack, matching a Pop for each Push.

GlutPostRedisplay () : glutPostRedisplay()

Second, the texture

After drawing the above primions, it runs, but it still looks very monotonous. Because they are drawn directly with dots, lines, etc., and filled directly with color. So it looks pretty monotonous.

So we can attach a picture to the surface of the primitives to improve the aesthetics.

Texture generally refers to the pattern or line on the object, which is the line lines presented on the object.

In OpenGL, texture usually refers to a layer of images attached to a primitive surface. Usually tag files are used.

On other platforms, when we use PNG or JPG, we need to decode it and get the bitmap data of the image.

We usually use PNG, JPG and other images, are compressed images, is the original image data for a layer of processing.

Image storage space = image height x image width x number of bytes per pixel

2.1. Recognize functions

2.1.1 Storage mode

Change pixel storage:

voidglPixelStorei(GLenumpname,GLintparam);

Restore pixel storage mode:

voidglPixelStoref(GLenumpname,GLfloatparam);

These two functions are very underused in development, so here are some examples:

// Parameter 1: GL_UNPACK_ALIGNMENT Specifies how OpenGL unpacks image data from the data cache. GL_UNPACK_ALIGNMENT Specifies the alignment request at the start of each pixel line in memory. The value can be 1 (byte alignment), 2 (even-byte alignment), 4 (Word alignment), or 8 (lines starting from the double-byte alignment) glPixelStorei(GL_UNPACK_ALIGNMENT,1).Copy the code

2.1.2. Read pixel map

We can read the pixel image directly from the color cache:

// Parameter 1: x, the window coordinates in the lower left corner of the rectangle // Parameter 2: y, the window coordinates in the lower left corner of the rectangle // Parameter 3: width, the width of the rectangle, in pixels // Parameter 4: height, the height of the rectangle, in pixels // Parameter 5: Format indicates the pixel format of OpenGL, as shown in Table 6-1 // Parameter 6:typeOpenGL specifies the data type in the cache to store color components. The data type of the pixel data is shown in the table below. Pixels, a pointer to the graphics data voidglReadPixels (GLintx, GLinty GLSizei width, GLSizei height, GLenumformat, GLenumtype, const void* pixels); glReadBuffer(mode); // Specify the cache to read glWriteBuffer(mode); // Specifies the cache to write toCopy the code

2.1.3. Load textures

There are three functions for loading 1D, 2D and 3D textures:

voidglTexImage1D(GLenumtarget,GLintlevel,GLint internalformat,GLsizeiwidth,GLintborder,GLenum format,GLenumtype,void* data); voidglTexImage2D(GLenumtarget,GLintlevel,GLint internalformat,GLsizeiwidth,GLsizeiheight,GLint border,GLenumformat,GLenumtype,void*data); voidglTexImage3D(GLenumtarget,GLintlevel,GLint internalformat,GLSizeiwidth,GLsizeiheight,GLsizei depth,GLintborder,GLenumformat,GLenumtype,void*data); *target: 'GL_TEXTURE_1D', 'GL_TEXTURE_2D', 'GL_TEXTURE_3D'. *Level: Specifies the mIP map Level to load. We usually set this parameter to 0. * InternalFormat: How many color components to store in each texture unit. * Width, height, depth: indicates the width, height, and depth of the loaded texture. = = attention! These values must be raised to an integer power of 2. (This is due to a requirement left over from older versions of OpenGL. Now, of course, it's possible to support an integer power other than 2. But developers are still used to setting these parameters to the power of 2.) * Border parameter: allows specifying a border width for the texture map. * format,typeData parameter: the same parameter as in the glDrawPixels functionCopy the code

2.1.4 Update textures

voidglTexSubImage1D(GLenumtarget,GLintlevel,GLintxOffset,GLsizeiwidth,GLenum format,GLenumtype,constGLvoid*data);

voidglTexSubImage2D(GLenumtarget,GLintlevel,GLintxOffset,GLintyOffset,GLsizei width,GLsizeiheight,GLenumformat,GLenumtype,constGLvoid*data);

voidglTexSubImage3D(GLenumtarget,GLintlevel,GLintxOffset,GLintyOffset,GLint zOffset,GLsizeiwidth,GLsizeiheight,GLsizeidepth,Glenumtype,constGLvoid*data);
Copy the code

2.1.5. Insert and replace textures

voidglCopyTexSubImage1D(GLenumtarget,GLintlevel,GLintxoffset,GLintx,GLinty,GLsizei width);

voidglCopyTexSubImage2D(GLenumtarget,GLintlevel,GLintxoffset,GLintyOffset,GLintx,GLint y,GLsizeiwidth,GLsizeiheight);

voidglCopyTexSubImage3D(GLenumtarget,GLintlevel,GLintxoffset,GLintyOffset,GLint zOffset,GLint x,GLinty,GLsizeiwidth,GLsizeiheight);
Copy the code

2.1.6. Load data to form new textures

voidglCopyTexImage1D(GLenumtarget,GLintlevel,GLenum internalformt,GLintx,GLinty,GLsizeiwidth,GLintborder); voidglCopyTexImage2D(GLenumtarget,GLintlevel,GLenum internalformt,GLintx,GLinty,GLsizeiwidth,GLsizei height,GLintborder); //x,y specifies the location in the color cache to start reading the texture data; // The data in the cache is set by the source cache using glReadBuffer. // Note: glCopyTextImage3D does not exist because we cannot get volume data from the 2D color cacheCopy the code

2.1.7. Use texture objects

// Use the function to allocate texture objects // specify the number of texture objects and Pointers (Pointers to an unsigned integer array filled with texture object identifiers). voidglGenTextures(GLsizei n,GLuint* textTures); // Bind texture state // parameter target:GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D target,GLunit texture); // Remove the binding texture object // Texture object and texture object pointer (the pointer points to an unsigned integer array filled with texture object identifiers). voidglDeleteTextures(GLsizein,GLuint*textures); The function returns GL_TRUE if the texture is a texture object that already has space allocated, GL_FALSE otherwise. GLbooleanglIsTexture(GLuint texture);Copy the code

2.1.8. Set texture parameters

glTexParameterf(GLenumtarget,GLenumpname,GLFloatparam); glTexParameteri(GLenumtarget,GLenumpname,GLintparam); glTexParameterfv(GLenumtarget,GLenumpname,GLFloat*param); glTexParameteriv(GLenumtarget,GLenumpname,GLint*param); Parameter 1:target, which specifies which texture mode these parameters will be applied to, such as GL_TEXTURE_1D, GL_TEXTURE_2D, and GL_TEXTURE_3D. Parameter 2:pname specifies which texture parameter to set. Parameter 3:param specifies the value of a specific texture parameterCopy the code

There are two kinds of param:

Proximity filtering: The object is to take the value of the color closest to the pixel position

Linear filter: to take the pixel position near the color value of the mixed value as the target

// for example, glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);Copy the code

2.1.9 Surround mode

In OpenGL, there are 4 ways to surround:

Around the way describe
GL_REPEAT Default behavior for texture, repeat texture image
GL_MIRRORED_REPEAT Same as GL_REPEAT, but the image is mirrored each time it is repeated
GL_CLAMP_TO_EDGE The texture coordinates are constrained between 0 and 1, and the excess portion repeats the edges of the texture coordinates, creating a stretch effect
GL_CLAMP_TO_BORDER The coordinate beyond is the user-specified edge color

The effects are as follows:

The surround Settings are as follows:

Parameter 1: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D Parameter 2: GL_TEXTURE_WRAP_S, GL_TEXTURE_T, GL_TEXTURE_R for s, T,r coordinates Parameter 3: GL_REPEAT, GL_CLAMP, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER GL_REPEAT:OpenGL repeats the texture in the direction with texture coordinates greater than 1.0; GL_CLAMP: The required texture cells are taken from the texture boundary or TEXTURE_BORDER_COLOR. GL_CLAMP_TO_EDGE surround mode forces texture coordinates out of range to be sampled along the last row or column of a valid texture cell. GL_CLAMP_TO_BORDER: only border texture units are used when texture coordinates are outside the 0.0 to 1.0 range. Boundary texture units are loaded with the base texture image as additional rows and columns around the base image. glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_S,GL_CLAMP_TO_EDGE); glTextParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_T,GL_CLAMP_TO_EDGE);Copy the code

2.2 texture coordinates

By default, the lower left corner is (0,0) and the upper right corner is (1,1).

When we load the image onto the primitives, the image data is mapped to the primitives according to texture coordinates