OpenGL 基础知识

1. 主函数

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);

    //初始化OPENGL显示方式 双缓冲、RGBA颜色模式
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA);
    //设定OPENGL窗口位置和大小
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    //打开窗口
    glutCreateWindow ("OpenGL");

    //调用初始化函数
    myinit();

    //设定窗口大小变化的回调函数,需要设定视区glViewport(0, 0, w, h);、透视方式glMatrixMode(GL_PROJECTION)与透视参数gluPerspective(60.0, 1.0*(GLfloat)w/(GLfloat)h, 1.0, 30.0)(角度,视景体的宽高比,沿z轴方向的两裁面之间的距离的近处,远处)


    glutReshapeFunc(myReshape);

    //设定键盘控制的回调函数
    //processSpecialKeys(int key, int x, int y)中key可以为GLUT_KEY_LEFT、GLUT_KEY_UP等
    glutSpecialFunc(processSpecialKeys);
    //processNormalKeys(unsigned char key,int x,int y)中key为ASCII
    glutKeyboardFunc(processNormalKeys);
     //10ms后执行回调function,回调中一般glutPostRedisplay()刷新页面,如果想重复执行再继续定义
    glutTimerFunc(10, function, 0);
    
    //开始OPENGL的循环
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}
 
2. 用户初始化函数
void myinit(void) {
    //打开深度检测
    glEnable(GL_DEPTH_TEST);
    //启用光照并打开默认的0号光
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    //启用颜色材质并定义什么材料追踪颜色
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
 
    GLenum err = glewInit();   
    if (GLEW_OK != err)  {   
        printf("glew initionlize error: %s ", glewGetErrorString(err));
    }
    //设置矩阵模式
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //设置光源的位置、环境光、散射光、反射光的颜色
    glLightfv(GL_LIGHT0, GL_POSITION, G_vLit0Position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, G_vLit0Ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, G_vLit0Diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, G_vLit0Specular);

    //Setting the textures
    loadTexImages();
    //开启颜色混合(片元操作:裁剪测试、alpha测试、模板测试、深度测试、混合、抖动、逻辑操作),定义混合因子计算方法
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
 
3. 加载贴图函数
void loadTexImages(void) {
    //生成2个贴图存入全局GLuint G_texNameArray[2]
    glGenTextures(2, G_texNameArray);

    //载入water.tga纹理
    int nWidth, nHeight, nComponents;
    GLenum eFormat;
    const char *szFileName = "Textures\water2.tga";
    
    // 读TGA文件的数据
    GLbyte *pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    // 读BMP文件数据方法 AUX_RGBImageRec * pBits =auxDIBImageLoad(_T("tsIcon.bmp"));
    if(pBits == NULL)
        return;
    //切换第二幅贴图为操作贴图,指定显存指针
    glBindTexture(GL_TEXTURE_2D, G_texNameArray[1]);
    //根据图像Byte数据生成纹理,根据指针加载到显存
    gluBuild2DMipmaps(GL_TEXTURE_2D, nComponents, nWidth, nHeight, eFormat, GL_UNSIGNED_BYTE, pBits);
    free(pBits);
}
/*
  *  GLubyte checkImage[Height 0xff][Width 0xff][4];
  *  遍历像素,二进制某一位隔固定长度切换0/1,异或获得棋盘
  *  [0][1][2] = c = ( (i&0x8) ^ (j&0x8) ) * 255, alpha[3] = 255
  *  glBindTexture, glTexImage2D/gluBuild2DMipmaps
  */
 
4. 显示函数
void display(void) {
    //设置清除屏幕的颜色,并清除屏幕和深度缓冲
    glClearColor(0.9f,0.9f,0.9f,0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    //设置平滑
    glShadeModel(GL_FLAT/GL_SMOOTH);

    //切换MODELVIEW矩阵堆栈并初始化模型变换矩阵
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //坐标中心向Z轴平移-G_fDistance (使坐标中心位于摄像机前方)
    glTranslatef(0.0, 0.0, -G_fDistance);
    glRotatef(G_fAngle_horizon, 0.0f, 1.0f, 0.0f);
    glRotatef(G_fAngle_vertical, 1.0f, 0.0f, 0.0f);

    //绘制物体
    
    //设置物体材质参数(和光照glLightfv)类似
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, G_vMaterialSpecu);
    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 60.0f);
    glColor4f(0.0f, 1.0f, 0.0f, 0.0f);
    
    //开启2D贴图并绑定Gen的贴图GLuint
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, G_texNameArray[1]);
    //纹理过滤函数,设置S与T方向的贴图次数、放大缩小的过滤方式(LINEAR4像素加权平均、NEAREST像素中心)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //纹理如何映射到每个像素上,纹理颜色如何影响片元颜色
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   
    //切换TEXTURE矩阵堆栈是下一个矩阵操作的目标
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glTranslatef(G_fWaterTexOffset, 0.0f, 0.0f);
    //切换MODELVIEW矩阵堆栈是下一个矩阵操作的目标
    glMatrixMode(GL_MODELVIEW);
 
    //绘制四边形同时绘制绑定的贴图,点坐标和贴图坐标
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, -1.0f, -2.0f);
        glTexCoord2f(4.0f, 0.0f); glVertex3f(4.0f, -1.0f, -2.0f);
        glTexCoord2f(4.0f, 1.0f); glVertex3f(4.0f, 1.0f, -2.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 1.0f, -2.0f);
    glEnd();
    //关闭贴图
    glDisable(GL_TEXTURE_2D);

    //交换前后缓冲区
    glutSwapBuffers();
}
 
5. 初始化Shader 装载、编译、链接
获取GLuint类型的
点着色器对象G_vShader_simple;面着色器对象G_fShader_simple;着色器程序G_shaderProgram;
    // 创建顶点与面片Shader着色器对象
    G_vShader_simple = glCreateShader(GL_VERTEX_SHADER);  
    G_fShader_simple = glCreateShader(GL_FRAGMENT_SHADER);   
    // 读两个shader命令
    char *vs = textFileRead("Shader/simple.vert");  
/* Shader程序直接获取修改全局变量如gl_Position, gl_Vertex等
uniform float time;
void main(void)  {  
    vec4 v = gl_Vertex;  
    v.z = sin(5.0*v.x + time)*0.25;  
    gl_Position =gl_ModelViewProjectionMatrix * v;  
}
  */
    char *fs = textFileRead("Shader/simple.frag");
    const char *vv = vs;  
    const char *ff = fs; 
    // 绑定Shader命令
    glShaderSource(G_vShader_simple, 1, &vv, NULL);  
    glShaderSource(G_fShader_simple, 1, &ff, NULL);  
 
    free(vs);
    free(fs);

    // 编译与获得编译结果
    glCompileShader(G_vShader_simple);  
    glCompileShader(G_fShader_simple); 
    int checkResult;
    glGetShaderiv(G_vShader_simple, GL_COMPILE_STATUS, &checkResult);  
    if(GL_FALSE == checkResult) {
        printf("vertex shader compile error ");
        printShaderInfoLog(G_vShader_simple);
    }
    glGetShaderiv(G_fShader_simple, GL_COMPILE_STATUS, &checkResult);  
    if(GL_FALSE == checkResult) {
        printf("fragment shader compile error ");
        printShaderInfoLog(G_fShader_simple);
    }

    // 创建一个着色器程序
    G_shaderProgram = glCreateProgram();  
    // 装载着色器对象
    glAttachShader(G_shaderProgram, G_vShader_simple);  
    glAttachShader(G_shaderProgram, G_fShader_simple);  
    // 链接着色器程序
    glLinkProgram(G_shaderProgram);  
    glGetProgramiv(G_fShader_simple, GL_LINK_STATUS, &checkResult);  
    if(GL_FALSE == checkResult) {
        printf("shader link error ");
        printProgramInfoLog(G_shaderProgram);
    }
 
附获取着色器对象错误Log的程序
void printProgramInfoLog(GLuint programObject) {
    GLint logLen = 0, writtenLen;
    glGetShaderiv(programObject, GL_INFO_LOG_LENGTH , &logLen);       
    if (logLen > 0) {
        GLchar* info_log = (GLchar*)malloc(logLen);
        glGetProgramInfoLog(programObject, logLen, &writtenLen, info_log);  
        printf("%s ", info_log);
        free (info_log);
    }
}

6. display()函数中采用非固定管线Shader绘制
//用初始化的着色器程序G_shaderProgram画一个茶壶,传入Uniform参数time
    static float shaderTime = 0.0f;
    glUseProgram(G_shaderProgram);

    GLint location =glGetUniformLocation(G_shaderProgram,"time");
    glUniform1f(location, shaderTime);

    glPushMatrix();
    glTranslatef(-1.0f, 0.0f, 0.0f);
    glutWireTeapot(1.0);
    glPopMatrix();
    shaderTime += 1.0f;

    glUseProgram(0);


原文地址:https://www.cnblogs.com/updateofsimon/p/4535892.html