• OpenGL 学习笔记 01 环境配置


    抱歉,本文写的很乱,建议跳过代码部分。


    以下教程仅适用于Mac下的Xcode编程环境!其他的我也不会搞。
    推荐教程:opengl-tutorial 
    本项目Github网址
     
     
     
    OpenGL太可怕了。。。必需得把学的记下来,不然绝壁忘。
     
    首先贴出代码,然后分析创建一个OpenGL程序都需要什么
      1 #include <cstdio>
      2 #include <cstdlib>
      3 
      4 #include <GL/glew.h>
      5 
      6 #include <GLFW/glfw3.h>
      7 
      8 #include <glm/glm.hpp>
      9 #include <glm/gtc/matrix_transform.hpp>
     10 using namespace glm;
     11 using namespace std;
     12 
     13 #include <shader.hpp>
     14 #include <shader.cpp>
     15 
     16 static const GLfloat g_vertex_buffer_data[] = {
     17     -1.0f,-1.0f,-1.0f, // triangle 1 : begin
     18     -1.0f,-1.0f, 1.0f,
     19     -1.0f, 1.0f, 1.0f, // triangle 1 : end
     20     1.0f, 1.0f,-1.0f, // triangle 2 : begin
     21     -1.0f,-1.0f,-1.0f,
     22     -1.0f, 1.0f,-1.0f, // triangle 2 : end
     23     1.0f,-1.0f, 1.0f,
     24     -1.0f,-1.0f,-1.0f,
     25     1.0f,-1.0f,-1.0f,
     26     1.0f, 1.0f,-1.0f,
     27     1.0f,-1.0f,-1.0f,
     28     -1.0f,-1.0f,-1.0f,
     29     -1.0f,-1.0f,-1.0f,
     30     -1.0f, 1.0f, 1.0f,
     31     -1.0f, 1.0f,-1.0f,
     32     1.0f,-1.0f, 1.0f,
     33     -1.0f,-1.0f, 1.0f,
     34     -1.0f,-1.0f,-1.0f,
     35     -1.0f, 1.0f, 1.0f,
     36     -1.0f,-1.0f, 1.0f,
     37     1.0f,-1.0f, 1.0f,
     38     1.0f, 1.0f, 1.0f,
     39     1.0f,-1.0f,-1.0f,
     40     1.0f, 1.0f,-1.0f,
     41     1.0f,-1.0f,-1.0f,
     42     1.0f, 1.0f, 1.0f,
     43     1.0f,-1.0f, 1.0f,
     44     1.0f, 1.0f, 1.0f,
     45     1.0f, 1.0f,-1.0f,
     46     -1.0f, 1.0f,-1.0f,
     47     1.0f, 1.0f, 1.0f,
     48     -1.0f, 1.0f,-1.0f,
     49     -1.0f, 1.0f, 1.0f,
     50     1.0f, 1.0f, 1.0f,
     51     -1.0f, 1.0f, 1.0f,
     52     1.0f,-1.0f, 1.0f
     53 };
     54 
     55 //每个顶点一个颜色
     56 static const GLfloat g_color_buffer_data[] = {
     57     0.583f,  0.771f,  0.014f,
     58     0.609f,  0.115f,  0.436f,
     59     0.327f,  0.483f,  0.844f,
     60     0.822f,  0.569f,  0.201f,
     61     0.435f,  0.602f,  0.223f,
     62     0.310f,  0.747f,  0.185f,
     63     0.597f,  0.770f,  0.761f,
     64     0.559f,  0.436f,  0.730f,
     65     0.359f,  0.583f,  0.152f,
     66     0.483f,  0.596f,  0.789f,
     67     0.559f,  0.861f,  0.639f,
     68     0.195f,  0.548f,  0.859f,
     69     0.014f,  0.184f,  0.576f,
     70     0.771f,  0.328f,  0.970f,
     71     0.406f,  0.615f,  0.116f,
     72     0.676f,  0.977f,  0.133f,
     73     0.971f,  0.572f,  0.833f,
     74     0.140f,  0.616f,  0.489f,
     75     0.997f,  0.513f,  0.064f,
     76     0.945f,  0.719f,  0.592f,
     77     0.543f,  0.021f,  0.978f,
     78     0.279f,  0.317f,  0.505f,
     79     0.167f,  0.620f,  0.077f,
     80     0.347f,  0.857f,  0.137f,
     81     0.055f,  0.953f,  0.042f,
     82     0.714f,  0.505f,  0.345f,
     83     0.783f,  0.290f,  0.734f,
     84     0.722f,  0.645f,  0.174f,
     85     0.302f,  0.455f,  0.848f,
     86     0.225f,  0.587f,  0.040f,
     87     0.517f,  0.713f,  0.338f,
     88     0.053f,  0.959f,  0.120f,
     89     0.393f,  0.621f,  0.362f,
     90     0.673f,  0.211f,  0.457f,
     91     0.820f,  0.883f,  0.371f,
     92     0.982f,  0.099f,  0.879f
     93 };
     94 
     95 int main() {
     96     if(!glfwInit()) {
     97         fprintf(stderr, "Failed To init OpenGL
    ");
     98     }
     99     
    100     // We want OpenGL 3.3
    101     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    102     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    103     // To make MacOS happy; should not be needed
    104     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    105     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
    106     
    107     // Open a window and create its OpenGL context
    108     // (In the accompanying source code, this variable is global)
    109     GLFWwindow* window;
    110     window = glfwCreateWindow(800, 600, "Tutorial 01", NULL, NULL);
    111     if( window == NULL ){
    112         fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.
    " );
    113         glfwTerminate();
    114         return -1;
    115     }
    116     glfwMakeContextCurrent(window); // Initialize GLEW
    117     glewExperimental = true; // Needed in core profile
    118     
    119     //z-buffer
    120     glEnable(GL_DEPTH_TEST);
    121     glDepthFunc(GL_LEFT);
    122     
    123     if (glewInit() != GLEW_OK) {
    124         fprintf(stderr, "Failed to initialize GLEW
    ");
    125         return -1;
    126     }
    127     
    128     //背景颜色
    129     glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    130     
    131     //shader
    132     GLuint programID = LoadShaders( "/Users/jeff/IDEProjects/xcode_projects/openGL/openGL/vertex.shader", "/Users/jeff/IDEProjects/xcode_projects/openGL/openGL/fragment.shader" );
    133     
    134     GLuint VertexArrayID;
    135     glGenVertexArrays(1, &VertexArrayID);
    136     glBindVertexArray(VertexArrayID);
    137     
    138     //vertex buffer
    139     GLuint vertexbuffer;
    140     glGenBuffers(1, &vertexbuffer);
    141     glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    142     glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    143     
    144     //color buffer
    145     GLuint colorbuffer;
    146     glGenBuffers(1, &colorbuffer);
    147     glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    148     glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
    149     
    150     mat4 Projection = perspective(radians(70.0f), (float)4/3, 0.1f, 1000.f);
    151     
    152     mat4 View = lookAt(vec3(3, 4, -5), vec3(0,0,0), vec3(0,1,0));
    153     
    154     mat4 Model = mat4(1.0f);
    155     
    156     //模型到投影转换
    157     mat4 mvp = Projection * View * Model;
    158     
    159     GLuint MatrixID = glGetUniformLocation(programID, "mvp");
    160     
    161     while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && !glfwWindowShouldClose(window)) {
    162         //每次开始时清空画布
    163         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    164         
    165         //使用shader
    166         glUseProgram(programID);
    167         
    168         //把变换矩阵送进shader
    169         glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);
    170         
    171         //画三角形
    172         glEnableVertexAttribArray(0);
    173         glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    174         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    175         
    176         //三角形颜色
    177         glEnableVertexAttribArray(1);
    178         glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    179         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    180         
    181         //draw call
    182         glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
    183         
    184         glDisableVertexAttribArray(0);
    185         glDisableVertexAttribArray(1);
    186         
    187         glfwSwapBuffers(window);
    188         glfwPollEvents();
    189     }
    190     glfwTerminate();
    191     return 0;
    192 }
    Code

     首先是OpenGL的文件

    对于OS X的用户来说,只要安装了Xcode,OpenGL也就被安装了(因为OS X用的就是这个。。)

    但是还需要其他几个库,用于处理平台相关的事情或者方便我们编程,他们分别是GLFW,GLEW,GLM

    在OS X上,用brew可以很方便的安装以上几个库,安装后进入下一步。

    一、配置项目文件

    打开Xcode,创建项目。

    在如所示的的地方配置以上3个库的头文件位置。如果不知道库安装在哪了,可以用brew info glew的方式找到安装路径

    配置结果如下,Libraray Search Path 不用管,后面会说

    现在可以在项目的代码中正确的调用各个库的头文件了,比如

    #include <GLFW/glfw3.h>

    但是这样是无法编译通过的,因为lib文件还没有被链接进来,编译器会找不到头文件里面函数的定义之类的。

    所以需要链接所有必要的lib文件。

    链接后应该如下

     

    点击那个“加号”添加lib

    其中,4个framework直接搜就可以找到。

    另外两个lib分别在GLEW和GLFW的安装目录下,比如我的路径如下:

    [brew安装路径]/glew/1.13.0/lib/libGLEW.a

    另一个同理,在安装目录的lib文件夹下面找得到。

    glm库不用添加lib

    至此所有的OpenGL代码应该就可以正常编译了,不过我上面贴的那段不行,因为我没贴全。。。

    二、OpenGL程序的基本结构

     首先需要按照以下顺序include一些头文件,这是魔法。

    #include <GL/glew.h>
    #include <GLFW/glfw3.h>

    以上是最主要的头文件了,当然我们还需要不少辅助的东西,全部的include如下

    #include <GL/glew.h>

    #include <GLFW/glfw3.h>

    #include <glm/glm.hpp>

    #include <glm/gtc/matrix_transform.hpp>

    using namespace glm;

    #include <cstdio>

    #include <cstdlib>

    using namespace std;

    OpenGL 3.0以后使用了可编程渲染管线,我们需要自己编写shader并编译

    这里有个现成的编译shader的函数,拿来用就好

    #ifndef SHADER_HPP
    #define SHADER_HPP
    
    GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
    
    #endif
    shader.hpp
      1 #include <stdio.h>
      2 #include <string>
      3 #include <vector>
      4 #include <iostream>
      5 #include <fstream>
      6 #include <algorithm>
      7 using namespace std;
      8 
      9 #include <stdlib.h>
     10 #include <string.h>
     11 
     12 #include <GL/glew.h>
     13 
     14 #include "shader.hpp"
     15 
     16 GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){
     17 
     18     // Create the shaders
     19     GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
     20     GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
     21 
     22     // Read the Vertex Shader code from the file
     23     std::string VertexShaderCode;
     24     std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
     25     if(VertexShaderStream.is_open()){
     26         std::string Line = "";
     27         while(getline(VertexShaderStream, Line))
     28             VertexShaderCode += "
    " + Line;
     29         VertexShaderStream.close();
     30     }else{
     31         printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !
    ", vertex_file_path);
     32         getchar();
     33         return 0;
     34     }
     35 
     36     // Read the Fragment Shader code from the file
     37     std::string FragmentShaderCode;
     38     std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
     39     if(FragmentShaderStream.is_open()){
     40         std::string Line = "";
     41         while(getline(FragmentShaderStream, Line))
     42             FragmentShaderCode += "
    " + Line;
     43         FragmentShaderStream.close();
     44     }
     45 
     46     GLint Result = GL_FALSE;
     47     int InfoLogLength;
     48 
     49 
     50     // Compile Vertex Shader
     51     printf("Compiling shader : %s
    ", vertex_file_path);
     52     char const * VertexSourcePointer = VertexShaderCode.c_str();
     53     glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
     54     glCompileShader(VertexShaderID);
     55 
     56     // Check Vertex Shader
     57     glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
     58     glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
     59     if ( InfoLogLength > 0 ){
     60         std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
     61         glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
     62         printf("%s
    ", &VertexShaderErrorMessage[0]);
     63     }
     64 
     65 
     66 
     67     // Compile Fragment Shader
     68     printf("Compiling shader : %s
    ", fragment_file_path);
     69     char const * FragmentSourcePointer = FragmentShaderCode.c_str();
     70     glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
     71     glCompileShader(FragmentShaderID);
     72 
     73     // Check Fragment Shader
     74     glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
     75     glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
     76     if ( InfoLogLength > 0 ){
     77         std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
     78         glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
     79         printf("%s
    ", &FragmentShaderErrorMessage[0]);
     80     }
     81 
     82 
     83 
     84     // Link the program
     85     printf("Linking program
    ");
     86     GLuint ProgramID = glCreateProgram();
     87     glAttachShader(ProgramID, VertexShaderID);
     88     glAttachShader(ProgramID, FragmentShaderID);
     89     glLinkProgram(ProgramID);
     90 
     91     // Check the program
     92     glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
     93     glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
     94     if ( InfoLogLength > 0 ){
     95         std::vector<char> ProgramErrorMessage(InfoLogLength+1);
     96         glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
     97         printf("%s
    ", &ProgramErrorMessage[0]);
     98     }
     99 
    100     
    101     glDetachShader(ProgramID, VertexShaderID);
    102     glDetachShader(ProgramID, FragmentShaderID);
    103     
    104     glDeleteShader(VertexShaderID);
    105     glDeleteShader(FragmentShaderID);
    106 
    107     return ProgramID;
    108 }
    shader.cpp

    别忘了#include <shader.hpp> 并把 shader.cpp 添加到项目的Compile Sources里

    g_vertex_buffer_data 和 g_color_buffer_data 储存正方形的顶点位置信息和颜色信息

    main 函数里:

     1 if(!glfwInit()) {
     2         fprintf(stderr, "Failed To init OpenGL
    ");
     3     }
     4     
     5     // We want OpenGL 3.3
     6     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
     7     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
     8     // To make MacOS happy; should not be needed
     9     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    10     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //We don't want the old OpenGL
    11     
    12     // Open a window and create its OpenGL context
    13     // (In the accompanying source code, this variable is global)
    14     GLFWwindow* window;
    15     window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL Window", NULL, NULL);
    16     if( window == NULL ){
    17         fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.
    " );
    18         glfwTerminate();
    19         return -1;
    20     }
    21     glfwMakeContextCurrent(window); // Initialize GLEW
    22     glewExperimental = true; // Needed in core profile
    23     
    24     if (glewInit() != GLEW_OK) {
    25         fprintf(stderr, "Failed to initialize GLEW
    ");
    26         return -1;
    27     }
    init 操作

    启用z-buffer

    glEnable(GL_DEPTH_TEST);

    glDepthFunc(GL_LESS);

    我感觉注释说的够清楚了。。。直接看代码吧

     1 //背景颜色
     2     glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
     3     
     4     //载入并编译shader
     5     GLuint programID = LoadShaders( "/Users/jeff/IDEProjects/xcode_projects/openGL/openGL/vertex.shader", "/Users/jeff/IDEProjects/xcode_projects/openGL/openGL/fragment.shader" );
     6     
     7     //VAO
     8     //加速存储效率,储存VBO
     9     //Veretx Array Object
    10     GLuint VertexArrayID;
    11     //创建
    12     glGenVertexArrays(1, &VertexArrayID);
    13     //绑定
    14     glBindVertexArray(VertexArrayID);
    15     
    16     //以下创建两个VBO
    17     //Vertex Buffer Object
    18     //用于将数据储存到显存中
    19     
    20     //第一个VBO
    21     //储存顶点数据
    22     GLuint vertexbuffer;
    23     //创建
    24     glGenBuffers(1, &vertexbuffer);
    25     //绑定
    26     glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    27     //储存数据
    28     glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    29     
    30     //第二个VBO
    31     //储存颜色信息
    32     //操作原理同上
    33     GLuint colorbuffer;
    34     glGenBuffers(1, &colorbuffer);
    35     glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    36     glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
    37     
    38     //创建坐标变换矩阵
    39     //本地   ->  世界  -> 视口    ->    齐次剪裁空间       空间变换流程
    40     //     Model    View    Projection                 对应需要的矩阵
    41     //透视变换
    42     mat4 Projection = perspective(radians(70.0f), (float)WIDTH / HEIGHT, 0.1f, 1000.f);
    43     //视口变换
    44     mat4 View = lookAt(vec3(3, 4, 5), vec3(0,0,0), vec3(0,1,0));
    45     //本地变换
    46     mat4 Model = mat4(1.0f);
    47     
    48     //集成本地到齐次剪裁空间的转换
    49     mat4 MVP = Projection * View * Model;
    50     
    51     //从shader中取出mvp (不是上面的MVP,特地用大小写区分了)
    52     //方便等会传入数据
    53     GLuint MatrixID = glGetUniformLocation(programID, "mvp");
    54     
    55     while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && !glfwWindowShouldClose(window)) {
    56         //每次开始时清空画布
    57         //同时清空z-buffer
    58         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    59         
    60         //使用shader
    61         glUseProgram(programID);
    62         
    63         //把变换矩阵送进shader
    64         glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
    65         
    66         //把顶点信息送入shader
    67         //数字0对应vertex shader中的 location = 0
    68         glEnableVertexAttribArray(0);
    69         glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    70         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    71         
    72         //把三角形颜色送入shader
    73         //数字0对应vertex shader中的 location = 1
    74         glEnableVertexAttribArray(1);
    75         glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    76         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    77 
    78         //draw call
    79         glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
    80         
    81         //一定要在draw call之后关闭
    82         glDisableVertexAttribArray(0);
    83         glDisableVertexAttribArray(1);
    84         
    85         //切换前后缓存,将渲染好的显示出来
    86         glfwSwapBuffers(window);
    87         glfwPollEvents();
    88     }
    main

    vertex shader:

     1 #version 330 core
     2 layout(location = 0) in vec3 vertexPosition_modelspace;
     3 layout(location = 1) in vec3 vertexColor;
     4 
     5 uniform mat4 mvp;
     6 out vec3 fragmentColor;
     7 
     8 void main() {
     9     gl_Position = mvp * vec4(vertexPosition_modelspace, 1);
    10     fragmentColor = vertexColor;
    11 }

    fragment shader:

    1 #version 330 core
    2 
    3 out vec3 color;
    4 in vec3 fragmentColor;
    5 
    6 void main() {
    7     color = fragmentColor;
    8 }

    至于这两个shader干嘛的。。。我先学习学习

  • 相关阅读:
    八皇后问题
    Catalan数与出栈顺序个数,Java编程模拟
    推荐系统中的协同过滤
    集成学习
    背包问题
    逆波兰表达式
    [leetcode]775. Global and Local Inversions
    [LeetCode]Minimum Moves to Equal Array Elements1,2
    链接属性
    常用表格属性
  • 原文地址:https://www.cnblogs.com/makejeffer/p/5575381.html
Copyright © 2020-2023  润新知