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\n");
 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.\n" );
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\n");
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 += "\n" + 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 !\n", 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 += "\n" + 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\n", 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\n", &VertexShaderErrorMessage[0]);
 63     }
 64 
 65 
 66 
 67     // Compile Fragment Shader
 68     printf("Compiling shader : %s\n", 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\n", &FragmentShaderErrorMessage[0]);
 80     }
 81 
 82 
 83 
 84     // Link the program
 85     printf("Linking program\n");
 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\n", &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\n");
 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.\n" );
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\n");
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干嘛的。。。我先学习学习

 

posted @ 2016-06-11 15:17  prop_jeff  阅读(2350)  评论(0编辑  收藏  举报