一、视频链接
【最好的OpenGL教程之一】https://www.bilibili.com/video/BV1MJ411u7Bc?p=5&vd_source=44b77bde056381262ee55e448b9b1973
二、相关网站
docs.gl
三、代码整理
c++
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include<iostream>
int main(void)
{
GLFWwindow* window;
//初始化glfw
if (!glfwInit())
return -1;
//创建一个窗口模式的窗口并设置OpenGL上下文
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)//如果窗口创建失败,则终止程序
{
glfwTerminate();//释放glfw资源
return -1;
}
//设置当前窗口的上下文,之后所有的OpenGL调用都会在这个上下文中进行
glfwMakeContextCurrent(window);
//初始化GLEW
if (glewInit() != GLEW_OK)
std::cout << "Error!" << std::endl;
//打印OpenGL版本信息
std::cout << glGetString(GL_VERSION) << std::endl;
//通过GL顶点属性指针的函数告诉OpenGL的数据是如何布局的
//这里我们告诉OpenGL,position数据是两个float,每个float占4字节
//第一个float表示x坐标,第二个float表示y坐标
//由于我们的数据是2D坐标,所以这里的stride为8字节
// 参数:
// 1.顶点属性的索引,这里是0
// 2.数据类型,这里是GL_FLOAT
// 3.数据类型占用字节数,这里是4
// 4.是否归一化,这里是GL_FALSE
// 5.stride,这里是8,表示两个float的大小
// 6.偏移量,这里是0,表示数据从开头开始
// 注意:这里的顶点属性指针的设置必须在启用顶点属性数组之前
// glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, 0);
//启用顶点属性数组
// 参数:
// 1.顶点属性的索引,这里是0
// glEnableVertexAttribArray(0);
//准备数据
float position[6] = {
0.0f, 0.5f,
- 0.5f, -0.5f,
0.5f, -0.5f
};
//可以将需要的图形(如三角形)绑定缓冲区,传递缓冲区的id给OpenGL,然后通过OpenGL渲染
//shader语法以字符串的形式给出,再由gl解析后让GPU执行GLSL程序
unsigned int buffer;
//功能:生成缓冲区,并将缓冲区绑定到OpenGL的指定目标
//参数:
//1.缓冲区数量,表示要生成的缓冲区数量
//2.指向无符号整数的指针,表示生成的缓冲区id的存储位置
glGenBuffers(1,&buffer);
//功能:绑定缓冲区到OpenGL的指定目标
//参数:
//1.目标,数组缓冲区,表示绑定到OpenGL的缓冲区
//2.缓冲区id,表示要绑定的缓冲区的id
glBindBuffer(GL_ARRAY_BUFFER, buffer);
//功能:将数据写入缓冲区
//参数:
//1.目标,数组缓冲区,表示要写入的缓冲区
//2.数据大小,表示要写入的数据的大小
//3.数据指针,表示要写入的数据的指针
//4.写入模式,表示数据写入的模式,这里是静态写入。
// 静态写入:数据不会被修改,仅仅是一次性写入,写入后缓冲区内容不会改变。
// 动态写入:数据会被修改,写入后缓冲区内容会改变。
// 一般情况下,静态写入效率更高。
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);
//渲染循环,直到窗口被关闭
while (!glfwWindowShouldClose(window))
{
//这部分主要:渲染窗口内容
glClear(GL_COLOR_BUFFER_BIT);
/*
//方法一:通过顶点属性指针渲染
glBegin(GL_TRIANGLES);
glVertex2f(0.0f, 0.5f);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.5f, -0.5f);
glEnd();
*/
/*
//方法二
//功能:指定如何从缓冲区中读取数据
//参数
// mode
// 指定要渲染的原始类型。接受符号常量
// GL_POINTS、GL_LINE_STRIP、GL_LINE_LOOP、GL_LINES、
// GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN 和 GL_TRIANGLES。
// first
// 指定在启用的数组中的起始索引。
// count
// 指定要渲染的索引数量。
glDrawArrays(GL_TRIANGLES, 0, 3);
*/
/*
//方法三:通过索引缓冲区渲染
//功能:指定如何从缓冲区中读取数据
//参数
// mode
// 指定要渲染的原始类型。符号常量 GL_POINTS、GL_LINE_STRIP、
// GL_LINE_LOOP、GL_LINES、GL_LINE_STRIP_ADJACENCY、GL_LINES_ADJACENCY、
// GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN、GL_TRIANGLES、
// GL_TRIANGLE_STRIP_ADJACENCY、GL_TRIANGLES_ADJACENCY
// 和 GL_PATCHES 被接受。
// count
// 指定要渲染的元素数量。
// type
// 指定 indices 中值的类型。必须是 GL_UNSIGNED_BYTE、GL_UNSIGNED_SHORT
// 或 GL_UNSIGNED_INT 中的一种。
// indices
// 指定缓冲区当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的数据存储中数组第一个索引的偏移量。
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
*/
//刷新缓冲区并交换窗口
glfwSwapBuffers(window);
//处理窗口事件,如键盘输入、鼠标移动等
glfwPollEvents();
}
glfwTerminate();
return 0;
}