Catalogue
Basic Knowledge
1.1 OpenGL is a specification (API) or a library?
1.2 OpenGL pipeline
- 图片来源网络,侵删。
1.3 What’s the difference between glfw, glew and glut
- [glut]: OpenGL utility toolkit for OpenGL to put the platform-dependent details (e.g. creating windows and responding to mouse events) under one hood.
GLUT是一个实用工具库, 用于创建窗口和相应鼠标事件等。
- glfw: glfw is the latest library for creating OpenGL context, opening a window and managing input after glut and freeglut.
与glut类似,glut是比较早期的工具。
- glew: GPU manufacturers provide their own exclusive functions, OpenGL extension wrangle will automatic identify advanced extension functions supported by specific graphics cards.
GPU的厂商(如Nvidia,AMD)会提供他们独有的高级扩展函数,GLEW会自动搜索这些函数以供用户使用。
Development Environment
1.1 Visual Studio
- Additional include directories.
附加包含目录, C/C++ -> 常规 -> 附加包含目录。
- Additional library directories.
附加库目录,链接器 -> 常规 -> 附加库目录。
- Additional dependencies. (e.g. opengl32.lib\glew32s.lib\glfw3.lib)
添加依赖项,链接器 -> 输入 -> 添加依赖项。
- Preprocessor Definitions.
若采用静态链接库,则需要定义GLEW_STATIC。 C/C++ -> 预处理器 ->预处理器定义。
1.2 OpenGL dependency libraries (e.g. glfw etc.)
Resource
Example 1 - Create a Window
1.1 Source Code
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
// glewInit必须在context之后
GLenum err = glewInit();
if (GLEW_OK == err) {
std::cout << "Glew init successful!" << std::endl;
std::cout << glGetString(GL_VERSION) << std::endl;
}
else {
std::cout << "Glew init failed!" << std::endl;
return -1;
}
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
1.2 Notes
- glewInit must be after make context.
glew.h要在glfw3.h之前,glewInit要在glfwMakeContext之后。
1.3 Display
Example 2 - Draw a Triangle (legacy mode)
1.1 Source Code
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex2d(0.0f, 1.0f);
glVertex2d(0.5f, 0.0f);
glVertex2d(-0.5f, 0.0f);
glEnd();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
1.2 Notes
- The coordinate system of OpenGL is from -1 to 1.
OpenGl的坐标系是从-1到1的。
1.3 Display
Example 3 - Draw a Triangle (buffer mode)
1.1 Source Code
// 顶点信息
float positions[8] = {
0.0f, 1.0f,
0.5f, 0.0f,
-0.5f, 0.0f,
0.0f, 1.0f
};
// 缓存id
GLenum bufferId;
// 申请缓存
glGenBuffers(1, &bufferId);
// 选择当前缓存
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
// 缓存中的数据赋值
glBufferData(GL_ARRAY_BUFFER, sizeof(positions), &positions, GL_STATIC_DRAW);
// 启用(状态机的)顶点属性
glEnableVertexAttribArray(0);
// 设置顶点的布局,第一个参数为属性索引,对应glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
// 绘制缓存数据,最后一个参数为总共几个顶点
glDrawArrays(GL_LINE_STRIP, 0, 4);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
1.2 Notes
- OpenGL can be seen as a state machine, don’t forget enable the vertex attribute.
OpenGL可以看成是一个状态机,别忘了要启用顶点属性,不然画不出来。
1.3 Display
Example 4 - Color the Triangle Using Vertex Shader & Fragment Shader
1.1 About Shader(着色器)
1.1.1 Vertex Shader(顶点着色器)
- If there are 3 vertices, then the vertex shader will be called three times.
有几个顶点,则顶点着色器就会被调用几次,如三角形三个顶点会调用三次顶点着色器。
1.1.2 Fragment Shader(片元着色器)
- Fragment shader decides which color that pixel is supposed to be, and it may be called thousands of times.
片元着色器(也叫像素着色器)决定每个像素的颜色,所以可能被调用上千次。
1.2 About Rasterization(光栅化)
- The points, lines and surfaces description of vectors become the description of pixels.
矢量的点线面描述变成像素的描述。图片来源
1.3 Source Code
1.3.1 File Structure
1.3.2 Shader Code
1.3.3 ShaderLoader Code
- read source file (读取着色器文件)
- compile shaders (编译着色器)
- glCreateShader
- glShaderSource
- glCompileShader
- link to program. (链接着色器到程序)
- glCreateProgram
- glAttachShader
- glLinkProgram
- glValidateProgram
1.3.4 Application Code
/*载入着色器*/
std::map<std::string, unsigned int> shaderMap;
shaderMap["resources/shaders/BasicVertexShader.shader"] = GL_VERTEX_SHADER;
shaderMap["resources/shaders/BasicFragmentShader.shader"] = GL_FRAGMENT_SHADER;
ShaderLoader shaderLoader;
unsigned int shaderProgram = shaderLoader.createProgram(shaderMap);
// 启用着色器
glUseProgram(shaderProgram);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
// 绘制缓存数据,最后一个参数为总共几个顶点
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
// 删除着色器对象
glDeleteProgram(shaderProgram);