初心者や議論のため、この記事を参照してください、専門家は〜を見ていない好きではない、誤りを指摘、批判を歓迎した
学習支援小さな赤い本(新バージョン)で推奨
OpenGLのチュートリアルのウェブサイトのリンクhttp://www.opengl-tutorial.org/
構築するために、特定の環境を質問ブログの前に、いくつかの解決策は、問題の交換で前方に置くことができます。
チュートリアルに基づいたサイトに基づき、私は全体の手順を説明要約、ここではカラーキューブでこのレッスンを組み合わせた要約を、(建築環境を含まない)最初の3つのコースのために行きました。
レッスン四
色のキューブ
//**第一部分,编译环境的配置**
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
// Include GLFW
#include <glfw3.h>
GLFWwindow* window; //创建窗口句柄
// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
//将加载着色器的代码放在此文件中
#include <common/shader.hpp>
int main( void )
{
//**第二部分,配置环境,设置窗口**
//2.1初始化glfw库
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
getchar();//暂停屏幕输出和程序运行,提供作者的浏览时间
return -1;//通常返回-1表示程序出错
}
//2.2设置窗口和显示参数
//hint是线索的意思,这里意为选项Hint也有很多种,这里我们只设置了3种,分别是:
glfwWindowHint(GLFW_SAMPLES, 4); //采用四倍抗锯齿
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); //选择OpenGL主版本
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); //选择OpenGL副版本
//所以合起来就是OpenGL版本为2.1
//2.3创建窗口,创建对应的context(上下文)
//创建窗口,并设置大小和名称
window = glfwCreateWindow( 1024, 768, "Tutorial 04 - Colored Cube", NULL, NULL);
//保证窗口创建成功
if( window == NULL ){
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" );
getchar();
glfwTerminate(); //若失败则需要终止glfw库
return -1;
}
//在使用OpenGL API之前,必须设置好当前的OpenGL上下文
glfwMakeContextCurrent(window);
//2.4初始化glew库
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
//2.5设置相关参数
// 确保我们可以捕捉下面按下的转义键,函数讲解见下文
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// 设置背景颜色为深蓝色(四个参数为red,green,blue,透明度)
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// 允许深度测试(消隐)
glEnable(GL_DEPTH_TEST);
//如果像素比之前的像素更接近相机,则接受当前像素
glDepthFunc(GL_LESS);
//**第三部分,传入数据,开始绘制**
//3.1调用已经写好的顶点着色器和片元着色器
//从着色器创建和编译GLSL程序
GLuint programID = LoadShaders( "TransformVertexShader.vertexshader", "ColorFragmentShader.fragmentshader" );
//3.2在C++中创建MVP矩阵
//创建uniform MVP矩阵的句柄
GLuint MatrixID = glGetUniformLocation(programID, "MVP");
// 为缓冲对象创建顶点位置句柄
GLuint vertexPosition_modelspaceID = glGetAttribLocation(programID, "vertexPosition_modelspace");
// 为缓冲对象创建顶点颜色句柄
GLuint vertexColorID = glGetAttribLocation(programID, "vertexColor");
// P矩阵:创建投影矩阵:45?Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
//V矩阵:创建视角矩阵
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,-3), // Camera is at (4,3,-3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// M矩阵:创建模型矩阵 : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// 计算得到MVP矩阵 : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
//3.3 在C++中设置顶点数据的参数
// 以下是我们的顶点数据,三个浮点数代表着3D的点坐标,每三个点构成一个三角形
// 一个立方体有六个面,每个面可以由两个三角形组成,所以一共是6*2=12个三角形,12*3=36个点(有重复的点)
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
// 为每个点设置颜色,参数是随机生成的
static const GLfloat g_color_buffer_data[] = {
0.583f, 0.771f, 0.014f,
0.609f, 0.115f, 0.436f,
0.327f, 0.483f, 0.844f,
0.822f, 0.569f, 0.201f,
0.435f, 0.602f, 0.223f,
0.310f, 0.747f, 0.185f,
0.597f, 0.770f, 0.761f,
0.559f, 0.436f, 0.730f,
0.359f, 0.583f, 0.152f,
0.483f, 0.596f, 0.789f,
0.559f, 0.861f, 0.639f,
0.195f, 0.548f, 0.859f,
0.014f, 0.184f, 0.576f,
0.771f, 0.328f, 0.970f,
0.406f, 0.615f, 0.116f,
0.676f, 0.977f, 0.133f,
0.971f, 0.572f, 0.833f,
0.140f, 0.616f, 0.489f,
0.997f, 0.513f, 0.064f,
0.945f, 0.719f, 0.592f,
0.543f, 0.021f, 0.978f,
0.279f, 0.317f, 0.505f,
0.167f, 0.620f, 0.077f,
0.347f, 0.857f, 0.137f,
0.055f, 0.953f, 0.042f,
0.714f, 0.505f, 0.345f,
0.783f, 0.290f, 0.734f,
0.722f, 0.645f, 0.174f,
0.302f, 0.455f, 0.848f,
0.225f, 0.587f, 0.040f,
0.517f, 0.713f, 0.338f,
0.053f, 0.959f, 0.120f,
0.393f, 0.621f, 0.362f,
0.673f, 0.211f, 0.457f,
0.820f, 0.883f, 0.371f,
0.982f, 0.099f, 0.879f
};
//3.4创建VBO,将顶点数组的元素数据传入GLSL(OpenGL shading language),即着色器。
//创建一个储存其顶点信息的VBO对象
GLuint vertexbuffer;
//返回n个当前未使用的缓存名称(此处是1),并保存到后面的数组中
glGenBuffers(1, &vertexbuffer);
//绑定缓存对象到OpenGL环境,绑定缓存时需要指明缓存对象的类型,这里是GL_ARRAY_BUFFER(顶点数据)
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
//创建并初始化VBO对象的数据区,参数为(类型,指针大小,数据的指针,enum(用处))
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
//创建一个用于存储点的颜色信息的VBO对象
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
//3.5在着色器中利用MVP矩阵变换顶点,并实现绘制过程
/*下面是一个无限执行的循环,负责一直处理窗口和操作系统的用户输入等操作,只有用户想退出的时候,才会终止循环*/
do{
// 清屏
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 使用着色器
glUseProgram(programID);
// 将我们的转换发送到当前绑定的着色器,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
// 第一个属性缓冲区:顶点
glEnableVertexAttribArray(vertexPosition_modelspaceID);//启动顶点属性数组
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);//指定当前激活的对象
glVertexAttribPointer( //函数详解见下
vertexPosition_modelspaceID, // index为想要设定的属性为顶点位置属性 3, //每个顶点的元素数目 GL_FLOAT, // 元素类型 GL_FALSE, //是否需要归一化处理,限制在[-1,1]之间
0, //数据紧密封装在一起 (void*)0 // array buffer offset
);
// 第二个属性缓冲:颜色
glEnableVertexAttribArray(vertexColorID);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glVertexAttribPointer(
vertexColorID, // The attribute we want to configure
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 画三角形
glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
glDisableVertexAttribArray(vertexPosition_modelspaceID);
glDisableVertexAttribArray(vertexColorID);
//将画面展现给用户
glfwSwapBuffers(window);
//检查操作系统返回的任何信息
glfwPollEvents();
}
//**第四部分,绘制结束,清理缓存**
//判断ESC键有没有按下或者有没有关闭窗口的行为
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// 清理VBO和着色器
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &colorbuffer);
glDeleteProgram(programID);
// 关闭OpenGL,终止GLFW库
glfwTerminate();
return 0;
}
知識サプリメント
1.glfwライブラリ、GLEWライブラリとライブラリGLM
GLEWは、C ++の拡張機能のクロスプラットフォームのOpenGLベースのグラフィックスインターフェースです。GLEWは自動的に現在のプラットフォームは、シニア漢の数すべてのOpenGLの拡張をサポートして識別することができます。Glew.hあれば、ヘッダファイルが含まれているとして、あなたはすべての機能のGL、GLU、glext、WGL、使用することができます GLX のを。GLEWは、一般的なオペレーティングシステムの様々なサポート。
次のように公式の説明は:です。GLEWは、このページ上のOpenGLの拡張機能とコア機能をチェックするための使いやすくかつ効率的な方法を提供するオープンソースのクロスプラットフォーム拡張は、複数のレンダリングコンテキストと自動コード生成機能GLEWのためのスレッドセーフなサポートでライブラリをロードしています。
GLFW OpenGLはクロスプラットフォームアプリケーションフレームワークであり、ウィンドウの作成をサポートし、入力機能及びイベントを受け入れます。
次のように公式の説明は次のとおりです。GLFWは、既存のアプリケーションに簡単に統合でき、メインループでを主張しないINPUTとイベントをOpenGLのコンテキストでWindowsを作成し、受信するためのオープンソース、マルチプラットフォームライブラリ..です
GLMは、OpenGLの数学であります倉庫
官方解释如下:GLMは、OpenGLシェーディング言語(GLSL)仕様に基づくグラフィックソフトウェアのためのC ++数学ライブラリです。
そのソートアウト:
GLEW図書館:
glGenbuffer()、などのOpenGL関数ライブラリglBindBufferが含まれ、基本的なOpenGLのあるライブラリ。
GLFWライブラリーは:
いくつかの作成などのアプリケーションフレームワークであり、窓の機能なので、ライブラリがされて最初に初期化して。
GLMライブラリ:数学ライブラリ、行列のためのコンピューティング。
glfwMakeContextCurrent(窓)機能について2.
初心者として、私は、コンテキスト(すなわちコンテキスト)は、一つのことを理解することは容易ではないと思う
情報へのアクセス:そのコンテキストは非常に抽象的概念であり、それは暫定的にオブジェクトに彼の理解を置くことができますこのオブジェクトは、OpenGLのすべてのオブジェクトが含まれています。
また、このことについて覚えておいて、
OpenGLのは、状態機械モデルは、私はまだそれを学ぶために継続し、このことを理解していないクライアント・サーバモードで使用されています!
3.関数glfwSetInputMode(GLFWwindow *ウィンドウ、INTモード
、UBT値)はGLFW入力基準に利用できるSEE
他の言葉を、この機能は、次の3つのGLFW_CURSOR、GLFW_STICKY_KEYS GLFW_STICKY_MOUSE_BUTTONSの一つだけ、入力モードのオプションを設定します
スティッキーキー:一回だけのボタンを押すことができ、接着スタートボタンは、Alt + F4などのキーをブロックした後、
キーボードが押されたときに学生がやった、我々は上記によると、英語で提供されており、上の移動は、この関数は、キーが存在するブロックでき、ボンドが呼び出された後、glfwGetKey機能がGLFW_PRESSを返した場合、唯一の唯一のあなただけのこのキーが押されたかどうかを知りたい状況に適用されますが、次のような状況には適用されません。あなたが知りたい場合や、どのような順序プレスでプレス。
4.glVertexAttribPointer函数
可以先看看函数名字,gl代表glew库里的函数,vertex是顶点,Attrib是attribution的缩写,意思是属性,pointer 指针,这个函数也就是:指定渲染时索引值为 index(index是着色器中的属性位置) 的顶点属性数组的数据格式和位置。(转自百度百科)
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer);
参数:
index
指定要修改的顶点属性的索引值
size
指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
type
指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。
normalized
指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。
ストライドは、
連続した頂点属性の間で指定したオフセット。それが0であれば、頂点は理解されるように属性:彼らは接近して配置されていること。ゼロの初期値。
ポインタは、
最初の配列頂点属性にオフセット最初のコンポーネントを指定します。バッファに格納され、結合したGL_ARRAY_BUFFERの配列。0の初期値。