《Learn OpenGL》https://learnopengl.com/Introduction 讲述 OpenGL 3.3 core profile 版本。
Getting Started
OpenGL
OpenGL 3.0 引入 API 废弃机制;OpenGL 3.1 废弃了fixed-function pipeline相关的函数;OpenGL 3.2 开始划分 core profile 和 compatibility profile。
OpenGL context 是一个大状态机,OpenGL object 是状态机里的一部分状态,使用模式如下:
// An OpenGL object struct object_name { float option1; int option2; char[] name; }; // The State of OpenGL struct OpenGL_Context { ... object_name* object_Window_Target; ... }; // create object unsigned int objectId = 0; glGenObject(1, &objectId); // bind/assign object to context glBindObject(GL_WINDOW_TARGET, objectId); // set options of object currently bound to GL_WINDOW_TARGET glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH, 800); glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600); // set context target back to default glBindObject(GL_WINDOW_TARGET, 0); // delete object glDeleteObject(objectId);
Hello Triangle
OpenGL Pipeline
- Vertex puller
- Vertex Shader: 处理单个 vertex,变换坐标,改变属性
- Primitive Assembly: 处理构成一个基本图形的所有 vertex,输出基本图形(点,三角形、线段)
- Tessellation
- Tessellation Control Shader
- Primitive Assembly
- Tessellation Primitive Generator
- Tessellation Evaluation Shader
- Primitive Assembly
- Geometry Shader: 处理基本图形,输出额外 vertex
- Primitive Assembly
- Transform Feedback (optional)
- Flat shading
- Clipping
- Perpspective Divide
- Viewport Transform
- Front/Back Face Selection
- Rasterization:处理基本图形,输出像素点
- Fragment Shader:为像素点着色,处理光照、阴影等。Fragment 指 OpenGL 里为了渲染单个像素点所需要的所有数据。
- Per-Fragment Operation: scissor test, stencil test, depth test, blending, logical operation, write mask
- Framebuffer
只有 Vertex Shader 和 Fragment Shader 是没有默认值,必须自行提供的。
Normalized Device Coordinates(NDC): 被 vertex shader 处理后,x、y、z坐标应该在 [-1.0, 1.0]之间,x 轴向右,y 轴向上(与 screen space coordinate 相反),且原点在坐标系中间(在屏幕坐标系中原点是左上角)。在 viewport transform 中会使用 glViewport() 指定的参数将 NDC 坐标转换到 SSC 坐标,转换后的坐标称为 fragment shader 的输入。
使用 shader
使用 Vertex Buffer Object
unsigned int vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // GL_STREAM_DRAW: 写一次,读几次 // GL_STATIC_DRAW: 写一次,读多次 // GL_DYNAMIC_DRAW: 多次写,多次读