The sphere world case is based on the previous case: texture and mirror display are added on the basis of the rotation of the large ball and the revolution of the small ball. It is still more interesting to play, and the effect is shown in the picture:

Case realization flowchart:



Function description

  • Main: Program entry, initializes Windows, menus, and render environments, and registers callback functions
  • SetupRC: Initializes background colors, shaders, and generates texture data
  • LoadTGATexture: Loads the TGA file as a 2D texture
  • ChangeSize: Change the viewport and the viewport, call it when resizing or initializing the window
  • RenderScene: Clears the cache, draws the sphere, and sets the texture data
  • DrawSomething: encapsulates the drawing of big ball, small ball and ball rotation
  • SpecialKeys: Move the camera reference frame based on the up and down keys to respond to the arrow keys
  • ShutDownRC: Closes the rendering environment and deletes texturesglDeleteTextures
  • Principal function analysis

    SetupRC function

    This function is mainly the initialization of data, including vertex, texture, etc. The function flow chart is as follows



    LoadTGATexture function

    The main process is to read the TGA file from memory and load it as 2D texture data. The main process is as follows:



    DrawSomething function



    RenderScene function



    Case code:

    The imported header file

    #include "GLTools.h"
    #include "GLShaderManager.h"
    #include "GLFrustum.h"
    #include "GLBatch.h"
    #include "GLMatrixStack.h"
    #include "GLGeometryTransform.h"
    #include "StopWatch.h"
    
    #include <math.h>
    #include <stdio.h>
    
    #ifdef __APPLE__
    #include <glut/glut.h>
    #else
    #define FREEGLUT_STATIC
    #include <GL/glut.h>
    #endif
    Copy the code

    Declared global variables

    //**4, add additional random balls#define NUM_SPHERES 50GLFrame spheres[NUM_SPHERES]; GLShaderManager shaderManager; // GLMatrixStack modelViewMatrix; // model view matrix GLMatrixStack projectionMatrix; // GLFrustum viewFrustum; // GLGeometryTransform transformPipeline; // GLTriangleBatch torusBatch; // floorBatch batch; ** GLTriangleBatch sphereBatch; ** GLTriangleBatch sphereBatch; //**3, cameraFrame (global camera instance) GLFrame cameraFrame; GLuint uiTextures[3];Copy the code

    Realize the function

    bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) { GLbyte *pBits; int nWidth, nHeight, nComponents; GLenum eFormat; PBits = gltReadTGABits(szFileName, &nWidth, &nheight, &nComponents, &eformat);if(pBits == NULL)
            return false; Parameteri: wrapMode, wrapMode glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); // Parameter 1: texture dimension // Parameter 2: linear filter // parameter 3: wrapMode, surround mode glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); // Parameter 1: Texture dimensions // Parameter 2: MIP texture layers // Parameter 3: texture unit stored color components (obtained from reading pixel images) - change internal parameter nComponents to general compressed texture format GL_COMPRESSED_RGB // Parameter 4: Load texture width // Parameter 5: load texture height // Parameter 6: load texture depth // parameter 7: data type of pixel data (GL_UNSIGNED_BYTE, each color component is an 8-bit unsigned integer) // Parameter 8: GlTexImage2D (GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits); PBits free(pBits); //GL_NEAREST_MIPMAP_NEAREST has very good performance and very weak flicker. //GL_LINEAR_MIPMAP_NEAREST is often used to accelerate games. It uses high quality linear filters //GL_LINEAR_MIPMAP_LINEAR and GL_NEAREST_MIPMAP_LINEAR to perform some additional interpolation between the Mip layers to eliminate filter traces between them. //GL_LINEAR_MIPMAP_LINEAR TRI-linear Mip map. The gold standard of texture filtering, with the highest accuracy.if(minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST) //4. // GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D glGenerateMipmap(GL_TEXTURE_2D);return true;
    }
    
    
    
    void SetupRC() {//1. Set clear color to color buffer glClearColor(0.0f, 0.0f, 0.0f, 1.0f); / / 2. Initialize shader manager shaderManager. InitializeStockShaders (); //3. Enable depth test/back cull glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); Makesphere (torusBatch, 0.4f, 40, 80); makesphere (torusBatch, 0.4f, 40, 80); GltMakeSphere (sphereBatch, 0.1F, 26, 13); //6. Set floor vertex data & floor texture GLfloatTexSize = 10.0 f; FloorBatch. The Begin (GL_TRIANGLE_FAN, 4, 1); FloorBatch. MultiTexCoord2f (0, 0.0 f, 0.0 f); FloorBatch. Vertex3f (- 20. F to 0.41 f, 20.0 f); FloorBatch. MultiTexCoord2f (0, texSize, 0.0 f); FloorBatch. Vertex3f (20.0 f to 0.41 f, 20 f); floorBatch.MultiTexCoord2f(0, texSize, texSize); FloorBatch. Vertex3f (20.0 f to 0.41 f, 20.0 f); FloorBatch. MultiTexCoord2f (0, 0.0 f, texSize); FloorBatch. Vertex3f (20.0 f, 0.41 f, 20.0 f); floorBatch.End(); //7. Random ball vertex coordinates datafor(int i = 0; i < NUM_SPHERES; I++) {// the Y-axis is unchanged, X,Z produces a random value GLfloat x = ((GLfloat)((rand() % 400) -200) * 0.1f); GLfloat z = ((GLfloat)((rand() % 400) -200) * 0.1f); // For each vertex in the Spheres array, set the vertex data Spheres [I].SetOrigin(x, 0.0f, z); // For each vertex in the spheres array, set the vertex data Spheres [I]. } //8. Name the texture object glGenTextures(3, uiTextures); //9. Load the TGA file as a 2D texture. GlBindTexture (GL_TEXTURE_2D, uiTextures[0]); GL_TEXTURE_2D; GL_TEXTURE_2D; LoadTGATexture("marble.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT);
        
        
        glBindTexture(GL_TEXTURE_2D, uiTextures[1]);
        LoadTGATexture("marslike.tga", GL_LINEAR_MIPMAP_LINEAR,
                       GL_LINEAR, GL_CLAMP_TO_EDGE);
        
        
        glBindTexture(GL_TEXTURE_2D, uiTextures[2]);
        LoadTGATexture("moonlike.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE); } // Delete texture void ShutdownRC(void) {glDeleteTextures(3, uiTextures); Void ChangeSize(int nWidth, int nHeight) {//1. Set the viewport glViewport(0, 0, nWidth, nHeight); / / 2. Set the projection mode viewFrustum. SetPerspective (35.0 f,float(nWidth)/float(nHeight), 1.0 f, 100.0 f); / / 3. The projection matrix is loaded into the stack of projection matrix and the projectionMatrix. LoadMatrix (viewFrustum. GetProjectionMatrix ()); modelViewMatrix.LoadIdentity(); / / 4. Set the model view matrix and projection matrix stack object to the pipeline transformPipeline. SetMatrixStacks (modelViewMatrix projectionMatrix); } void drawSomething(GLfloatYRot) {//1. Define the light position & diffuse color static GLfloatVWhite [] = {1.0f, 1.0f, 1.0f, 1.0f}; static GLfloatVLightPos [] = {0.0f, 3.0f, 0.0f, 1.0f}; GlBindTexture (GL_TEXTURE_2D, uiTextures[2]);for(int i = 0; i < NUM_SPHERES; i++) { modelViewMatrix.PushMatrix(); modelViewMatrix.MultMatrix(spheres[i]); shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, modelViewMatrix.GetMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vWhite, 0); sphereBatch.Draw(); modelViewMatrix.PopMatrix(); } / / 3. Draw the ball ball modelViewMatrix. Translate (0.0 f to 0.2 f, 2.5 f); modelViewMatrix.PushMatrix(); ModelViewMatrix. Rotate (yRot, 0.0 f, f 1.0, 0.0 f); glBindTexture(GL_TEXTURE_2D, uiTextures[1]); shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, modelViewMatrix.GetMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vWhite, 0); torusBatch.Draw(); modelViewMatrix.PopMatrix(); / / 4. Draw the revolution of balls (revolution) modelViewMatrix. PushMatrix (); ModelViewMatrix.Rotate(yRot * -1.0f, 0.0f, 1.0f, 0.0f); ModelViewMatrix. Translate (0.8 f, f 0.0, 0.0 f); glBindTexture(GL_TEXTURE_2D, uiTextures[2]); shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, modelViewMatrix.GetMatrix(), transformPipeline.GetProjectionMatrix(), vLightPos, vWhite, 0); sphereBatch.Draw(); modelViewMatrix.PopMatrix(); } // call to draw the scene void RenderScene(void) {//1. Floor color value static GLfloatVFloorColor [] = {1.0f, 1.0f, 0.0f, 0.75f}; //2. Time-based animation static CStopWatch rotTimer;floatYRot = rotTimer. GetElapsedSeconds () * 60.0 f; / / 3. Clear the color buffer and depth buffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); / / 4. Push the stack (stack) modelViewMatrix. PushMatrix (); //5. Set the observer matrix to M3DMatrix44f mCamera; cameraFrame.GetCameraMatrix(mCamera); modelViewMatrix.MultMatrix(mCamera); / / 6. Pressure stack (mirror) modelViewMatrix. PushMatrix (); / / 7. - add reflective effect - / / flip Y modelViewMatrix Scale (1.0 1.0 f to 1.0 f, f); / / mirror worlds around Y axis translation certain spacing modelViewMatrix. Translate (0.0 f to 0.8 f to 0.0 f); //8. Specify clockwise glFrontFace(GL_CW); //9. DrawSomething (yRot); //10. Revert to glFrontFace(GL_CCW); / / 11. Draw a mirror, restore matrices modelViewMatrix. PopMatrix (); //12. Enable glEnable(GL_BLEND); //13. Specify the glBlendFunc color blend equation glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); GlBindTexture (GL_TEXTURE_2D, uiTextures[0]); /*15. Texture adjustment shader (multiply a base color by a texture from the texture unit nTextureUnit) parameter 1: GLT_SHADER_TEXTURE_MODULATE parameter 2: model view projection matrix parameter 3: Color parameter 4: Texture unit (0 layer texture unit). * / shaderManager UseStockShader (GLT_SHADER_TEXTURE_MODULATE, transformPipeline.GetModelViewProjectionMatrix(), vFloorColor, 0); //shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0); // Start drawing floorbatch.draw (); // unblend glDisable(GL_BLEND); DrawSomething (yRot); / / 17. Painted, restore matrices modelViewMatrix. PopMatrix (); GlutSwapBuffers (); //19. Submit to re-render glutPostRedisplay(); Void SpeacialKeys(int key,int x,int y) {//**3.floatLinear = 0.1 f;float angular = float(m3dDegToRad (5.0 f));if(key == GLUT_KEY_UP) {// camerafame. }if (key == GLUT_KEY_DOWN) {
            cameraFrame.MoveForward(-linear);
        }
        
        if(key == GLUT_KEY_LEFT) {//RotateWorld rotates camerafame.RotateWorld(Angular, 0.0f, 1.0f, 0.0f); }if(key == GLUT_KEY_RIGHT) {camerafame.RotateWorld(-Angular, 0.0f, 1.0f, 0.0f); } } int main(int argc, char* argv[]) { gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); GlutInitWindowSize (800600); glutCreateWindow("OpenGL SphereWorld");
        
        glutReshapeFunc(ChangeSize);
        glutDisplayFunc(RenderScene);
        glutSpecialFunc(SpeacialKeys);
        
        GLenum err = glewInit();
        if(GLEW_OK ! = err) { fprintf(stderr,"GLEW Error: %s\n", glewGetErrorString(err));
            return 1;
        }
        
        SetupRC();
        glutMainLoop();
        ShutdownRC();
        return 0;
    }
    Copy the code

    Demo address attached:

    Github complete Demo 08-OpenGL- Sphere world