My OpenGL thematic learning directory, hope to learn with you exchange progress!
- OpenGL Learning (I) – Terminology understanding
- OpenGL learning (2) — Xcode build OpenGL environment
- OpenGL learning (three) – OpenGL base rendering
- OpenGL learning (4) – front & back culling and depth testing
- OpenGL Learning (5) – Cropping and Blending
- OpenGL Learning (6) – Base textures
- OpenGL Learning (7) — Summary of basic change Comprehensive Exercise practice
- OpenGL ES Learning (8)
- OpenGL learning (nine) — OpenGL ES preliminary exploration (next) GLKit
- OpenGL learning (10) – GLSL syntax introduction
- OpenGL learning (11) – using GLSL to load pictures
- OpenGL learning (12) — OpenGL ES texture flipping strategy comparison
One, foreword
The following I summarized some recent learning OpenGL commonly used in some functions, add more comments, not only to their own learning a consolidated summary, but also to prevent the future forgotten can quickly view the record, at the same time, I hope to help more friends in learning OpenGL.
Xcode has not yet built an OpenGL environment for friends can refer to my article to build OpenGL learning (2) — Xcode built OpenGL environment. There are also some basic OpenGL articles that I summarized earlier, which can be viewed in the table of contents at the top of the article.
Second, code + comments summary
1. Imported header files:
#include "GLTools.h" // OpenGL toolkit
#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLGeometryTransform.h"
#include "StopWatch.h"
#include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
Copy the code
2, some common global variable declaration:
GLShaderManager shaderManager;// Fix the pipeline manager
GLMatrixStack modelViewMatrix;// Model view matrix stack
GLMatrixStack projectionMatrix;// Projection view matrix stack
GLFrame cameraFrame;// Observer position
GLFrame objectFrame;// World coordinates
GLFrustum viewFrustum;// Projection mode, technical name: viewframe. To construct the projection matrix.
GLBatch triangleBatch;// A simple batch container is a simple container class for GLTools.
GLTriangleBatch CC_Triangle;// Triangle batch class
GLTriangleBatch sphereBatch;/ / the ball
GLTriangleBatch torusBatch;/ / ring
GLTriangleBatch cylinderBatch;/ / cylindrical
GLTriangleBatch coneBatch;/ / cone
GLTriangleBatch diskBatch;/ / disk
GLGeometryTransform transformPipeline; // Transform pipe is used to manage projection and model matrix
GLfloat vGreen[] = {0.0 f.1.0 f.0.0 f.1.0 f };// Define a color value, green
Copy the code
3, main function: program entry Settings
int main(int argc,char *argv[]) {
// Set the current working directory for MAC OS X
/* 'GLTools' function' glSetWorkingDrectory 'sets the current working directory. In fact, this is not necessary in Windows because the working directory is the same directory as the program executable by default. But on Mac OS X, this program changes the current working folder to the '/Resource' folder in the application bundle. The 'GLUT' priority setting does this automatically, but the method is more secure. * /
gltSetWorkingDirectory(argv[0]);
// Initialize GLUT library. This function simply passes command arguments and initializes GLUT library
glutInit(&argc, argv);
/* Initialize the double buffer window, where GLUT_DOUBLE, GLUT_RGBA, GLUT_DEPTH, GLUT_STENCIL indicate the double buffer window, RGBA color mode, depth test, and template buffer, respectively. Double-cached Windows, where a drawing command is actually executed off-screen from the cache and then quickly converted to a window view, are often used to generate animation effects; --GLUT_DEPTH ': flag allocates a depth cache as part of the display, so we can perform a depth test; GLUT_STENCIL: Make sure we also have a template cache available. Depth and template testing will be covered in more detail */
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//GLUT window size, window title
glutInitWindowSize(800.600);
glutCreateWindow("Triangle");
/* GLUT internally runs a local message loop that intercepts the appropriate message. Then call the callback function that we registered at different times. We registered two callback functions: 1) a callback for window resizing and 2) a callback that contains OpenGL rendering */
// Register the remodeling function
glutReshapeFunc(changeSize);
// Register the display function
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpeacialKeys);
/* Initialize a GLEW library to ensure that the OpenGL API is fully available to the program. Before attempting to do any rendering, check to make sure there are no problems with driver initialization */
GLenum status = glewInit();
if(GLEW_OK ! = status) {printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
// Set up our render environment
setupRC();
glutMainLoop();
return 0;
}
Copy the code
ChangeSize (int w, int h);
Resize function, a callback function set for window resizing to receive new width & height when the window resizes. The glutReshapeFunc function is registered in the main function: glutReshapeFunc(changeSize); // Register the remodeling function
/* Receives new width & height when the window size changes. * /
void changeSize(int w,int h) {
/* 1. Set the window coordinate x,y parameter represents the coordinate of the lower left corner of the view in the window, width and height are represented by pixels, usually x and y are 0 */
// Prevent h from going to 0
if(h == 0){
h = 1;
}
glViewport(0.0, w, h);
/ / 2,
// If you are drawing a solid shape, you also need to set perspective projection
// Perspective projection
// Parameter 1: Field of view Angle from vertex direction (Angle value)
// Parameter 2: aspect ratio of width and height
// Parameter 3: fNear
// Parameter 4: fFar
viewFrustum.SetPerspective(35.0 f.float(w) / float(h), 1.0 f.500.0 f);
/ / 3.
// We just set it up but it doesn't work, we need to convert it to a matrix and take the result back.
// load a matrix into the projectionMatrix stack projectionMatrix, and get the projectionMatrix GetProjectionMatrix() from our viewbody viewFrustum
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
/ / 4.
// The model view matrix is used for rotation, translation, etc. There is no change here, so just load a element matrix.
// Add a cell matrix to the modelViewMatrix stack
modelViewMatrix.LoadIdentity();
}
Copy the code
5, KeyPressFunc click the space function:
Each time you click on a space, switch the title of the window and re-render the graphics
// Click space to toggle rendering graphics
void KeyPressFunc(unsigned char key, int x, int y) {
if(key == 32) {
nStep++;
if(nStep > 4)
nStep = 0;
}
switch(nStep) {
case 0:
glutSetWindowTitle("Sphere");
break;
case 1:
glutSetWindowTitle("Torus");
break;
case 2:
glutSetWindowTitle("Cylinder");
break;
case 3:
glutSetWindowTitle("Cone");
break;
case 4:
glutSetWindowTitle("Disk");
break;
}
glutPostRedisplay();
}
Copy the code
SpecialKeys function
Click up, down, left, and right on the keyboard to change the world coordinate system (not the object itself)
// Move the world coordinate system up, down, left, and right
void SpecialKeys(int key, int x, int y) {
if(key == GLUT_KEY_UP)
// Move the world coordinate system instead of moving objects.
// Move the world coordinate system to -5.0 in the X direction
objectFrame.RotateWorld(m3dDegToRad(5.0 f), 1.0 f.0.0 f.0.0 f);
if (key == GLUT_KEY_DOWN)
objectFrame.RotateWorld(m3dDegToRad(5.0 f), 1.0 f.0.0 f.0.0 f);
if (key == GLUT_KEY_LEFT)
objectFrame.RotateWorld(m3dDegToRad(5.0 f), 0.0 f.1.0 f.0.0 f);
if (key == GLUT_KEY_RIGHT)
objectFrame.RotateWorld(m3dDegToRad(5.0 f), 0.0 f.1.0 f.0.0 f);
glutPostRedisplay();
}
Copy the code
SetupRC()
Do the necessary initialization to set up our render environment, called in the main function. This is usually used to describe what the shape we want to render looks like. The real time to draw is not here, but in the RenderScene() function, which WE’ll talk about later.
// Place the necessary initialization in the context
void SetupRC(a) {
// 1. Set the background color
glClearColor(0.7 f.0.7 f.0.7 f.1.0 f );
// 2. Initialize the fixed shader manager
shaderManager.InitializeStockShaders();
// 3. Enable depth testing when drawing stereo graphics
glEnable(GL_DEPTH_TEST);
// Manage matrix stack with GLGeometryTransform
// Manage the model view matrix stack and projection matrix stack using transformPipeline.
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
// 5. For obvious effect, move the observer position Z 15 units to the screen
// Parameter: indicates the distance from the screen. Negative numbers are moving behind the screen; Positive, move to the front of the screen
cameraFrame.MoveForward(15.0 f);
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- GLTriangleBatch type -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
// Use the triangle batch class of type "GLTriangleBatch" to construct the graphics object. The GLTriangleBatch type encapsulates many commonly used stereo graphics.
/ / 1, the ball
/* gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks); Parameter 1: sphereBatch, triangle batch class object parameter 2: fRadius, sphere radius parameter 3: iSlices, the number of triangle strips stacked from the bottom of the sphere to the top; It is suggested that the number of fragments of a sphere with good symmetry is twice the number of stacked fragments, that is, iStacks = 2 * iSlices. Parameter 4 is twice the number of parameter 3. The spheres are drawn around the z-axis so that + Z is the vertex of the sphere and -z is the bottom of the sphere. * /
gltMakeSphere(sphereBatch, 3.0.10.20);
// 2, torus
/* gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor); Parameter 1: torusBatch, triangle batch class object parameter 2: majorRadius, the radius from the center of the doughnut to the outer edge parameter 3: minorRadius, the radius from the center of the doughnut to the inner edge parameter 4: numMajor, the number of triangles along the main radius parameter 5: NumMinor, the number of triangles along the inner smaller radius */
gltMakeTorus(torusBatch, 3.0 f.0.75 f.15.15);
// 3
/* void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks); Parameter 1: cylinderBatch, triangle batch class object parameter 2: baseRadius, baseRadius parameter 3: topRadius, head radius parameter 4: fLength, circular length parameter 5: numSlices, number of triangle pairs around the z-axis parameter 6: NumStacks, the number of triangles that stack the bottom of a cylinder into the top ring */
gltMakeCylinder(cylinderBatch, 2.0 f.2.0 f.3.0 f.15.2);
/ / 4, cone
/* void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks); Parameter 1: cylinderBatch, triangle batch class object parameter 2: baseRadius, baseRadius parameter 3: topRadius, head radius parameter 4: fLength, circular length parameter 5: numSlices, number of triangle pairs around the z-axis parameter 6: NumStacks, the number of triangles that stack the bottom of a cylinder into the top ring */
// A cylinder extends from 0 to the positive direction of the Z axis.
// The radius of one end is 0, and the radius of the other end can be specified.
gltMakeCylinder(coneBatch, 2.0 f.0.0 f.3.0 f.13.2);
// 5
/* void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks); Parameter 1:diskBatch, triangle batch object parameter 2:innerRadius, innerRadius parameter 3:outerRadius, outerRadius parameter 4:nSlices, number of triangle pairs around the Z axis of the disk 5:nStacks, number of triangles from the outer network to the inner circle of the disk */
gltMakeDisk(diskBatch, 1.5 f.3.0 f.13.3);
/ / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- GLBatch type -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
// When using GLTriangleBatch code above, comment out the following code before running. The two pieces of code were originally separate, but were written together for convenience.
// Above is the triangle batch class of type "GLTriangleBatch", below we use the most basic triangle batch class of type "GLBatch" to draw the pyramid.
// First create the triangle batch class and tell it how many vertices we need,
The function BeginMesh(GLuint nMaxVerts)// specifies how many vertices there are
CC_Triangle.BeginMesh(300);// Specify 300 vertices
// 2. Create a vertex
M3DVector3f m[] = {
0.5.0.0.0.0.0.5.0.0.0.0.0.0.0.5.0.0
};
// 3. Copy the vertices to add them
// Parameter 1: indicates the vertex coordinate value
// parameter 2: indicates the normal coordinate value, NULL if no
// Parameter 3: indicates the texture coordinate value, NULL if no
CC_Triangle.AddTriangle(m, NULL.NULL);
//CC_Triangle.CopyVertexData3f
CC_Triangle.End();
CC_Triangle.Draw();
// --------------------------------------------------------------
}
Copy the code
RenderScene() :
The function RenderScene() is called when the glutPostRedisplay() method is called for any change. GlutDisplayFunc (RenderScene) is registered in the main function.
Let me explain the code in detail:
- (1) PushMatrix();
modelViewMatrix.PushMatrix(); If the parentheses of PushMatix() are empty, the matrix at the top of the stack is copied and pushed to the top. If it is not empty, such as the element matrix in parentheses, then it means pushing a element matrix to the top of the stack.
- (2) Matrix multiplication MultMatrix(mObjectFrame)
The matrix in the modelViewMatrix stack is multiplied by the mOjbectFrame matrix and stored in the modelViewMatrix matrix stack. modelViewMatrix.MultMatrix(mObjectFrame); Copy the top matrix of the modelview matrix stack, multiply it by the new matrix, and assign the result to the top matrix.
- (3) PopMatrix();
modelViewMatrix.PopMatrix(); Take the top matrix off the stack and restore it to the original matrix stack so that it does not affect subsequent operations.
Here is a flow chart of “Matrix loading, multiplying, and unloading” summarized by myself:
- (4) cameraFrame. GetCameraMatrix (mCamera) :
cameraFrame.GetCameraMatrix(mCamera); This syntax is a little different from OC, which means that the matrix is taken from the observer frame cameraFrame and assigned to mCamera. Objectframe.getmatrix (mObjectFrame); . CameraFrame and mCamera are structures of type GLFrame.
Let’s look at the RenderScene() code:
// Call scene
void RenderScene(void) {
//1. Clear a specific cache or group of caches
/* A buffer is a block of storage space containing image information. The red, green, blue, and alpha components are often referenced together as color caches or pixel caches. More than one buffer in OpenGL (color cache, depth cache, and template cache) clears the cache to preset values: GL_COLOR_BUFFER_BIT: indicates the currently active buffer for color writing GL_DEPTH_BUFFER_BIT: indicates the depth buffer GL_STENCIL_BUFFER_BIT: indicates the template buffer */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Model view matrix stack stack
modelViewMatrix.PushMatrix();
// Get the camera matrix
M3DMatrix44f mCamera;
// Get the matrix from camereaFrame to mCamera
cameraFrame.GetCameraMatrix(mCamera);
// The matrix of the modelview stack is multiplied by the mCamera matrix and stored in the modelViewMatrix matrix stack
modelViewMatrix.MultMatrix(mCamera);
// Create the matrix mObjectFrame
M3DMatrix44f mObjectFrame;
// Get the matrix from ObjectFrame into mOjectFrame
objectFrame.GetMatrix(mObjectFrame);
// Multiply the matrix in the modelViewMatrix stack by the mOjbectFrame matrix and store it in the modelViewMatrix stack
modelViewMatrix.MultMatrix(mObjectFrame);
// Use a flat shader
// Parameter 1: type
// Parameter 2: Obtain the model view matrix via transformPipeline
// Parameter 3: color
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
// Determine which graph you are currently drawing
// Note that the address passed here is &sphereBatch
switch(nStep) {
case 0:
DrawWireFramedBatch(&sphereBatch);/ / the ball
break;
case 1:
DrawWireFramedBatch(&torusBatch);/ / torus
break;
case 2:
DrawWireFramedBatch(&cylinderBatch);/ / cylindrical
break;
case 3:
DrawWireFramedBatch(&coneBatch);/ / cone
break;
case 4:
DrawWireFramedBatch(&diskBatch);/ / disk
break;
}
// When I'm done drawing, I need to pop out the matrix at the top of the stack
modelViewMatrix.PopMatrix();
// Flush drawing commands
glutSwapBuffers();
}
Copy the code
DrawWireFramedBatch ();
void DrawWireFramedBatch(GLTriangleBatch* pBatch) {
// Flat shader, draw triangle
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
// The parameters to be passed correspond to different graphs Batch
pBatch->Draw();
// Draw the black outline
glPolygonOffset(1.0 f.1.0 f);
// Enable line segment smoothing
glEnable(GL_LINE_SMOOTH);
// Enable the blending function
glEnable(GL_BLEND);
// Color mix
// The source color is multiplied by its alpha value, and the target color is multiplied by 1.0 minus the alpha value of the source color, so that the larger the alpha value of the source color is, the larger the proportion of the source color is, and the smaller the proportion of the target color is. In this case, we can simply interpret the alpha value of the source color as "opacity". This is the most common way to mix.
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Use the program point size mode to set the point size
glEnable(GL_POLYGON_OFFSET_LINE);
// Set the back of the polygon to wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// Line width
glLineWidth(2.5 f);
// Flat shader draws lines
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw();
// Restore polygon mode and depth test
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0 f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
Copy the code
The above summary refers to and partly extracts the following articles, thanks very much to the following authors for sharing! :
1. OpenGL Super Dictionary 5th Edition
2. OpenGL Programming Guide (Eighth Edition)
Reprint please note the original source, shall not be used for commercial communication – any more