OpenGL学习记录
由于昨天晚上电脑没电了,导致没能发出去,今天补上
第二天的学习主要是对渲染管线的流程有了一个大概的了解
部分问题:
- 函数返回引用时应该使用引用类型接收,否则接收的变量会变为新创建的临时变量
- 函数内部的非静态成员变量不能作为返回参数,想要返回内部成员变量只能设置为静态变量
顶点输入
- 三角形
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
- 矩形
float vertices[] = {
0.5f, 0.5f, 0.0f, // 右上角
0.5f, -0.5f, 0.0f, // 右下角
-0.5f, -0.5f, 0.0f, // 左下角
-0.5f, 0.5f, 0.0f // 左上角
};
unsigned int indices[] = {
0, 1, 3, // 第一个三角形
1, 2, 3 // 第二个三角形
};
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//生成一个VBO对象,将数据放进缓冲的内存中
unsigned int VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//生成一个EBO对象,将索引放进缓冲的内存中
unsigned int EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
/*告诉OpenGL如何解析顶点数据
* 第一个参数为位置值
* 第二个参数为顶点属性的大小
* 第三个参数为顶点数据类型
* 第四个参数为是否将数据标准化
* 第五个参数为顶点组的步长(这里是三个float的长度)
* 最后一个参数是偏移量
*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
顶点着色器:
为了方便调用,这里都用了函数来封装着色器的初始化
unsigned int& vertex_shader() {
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
static unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
return vertexShader;
}
片元着色器
unsigned int& fragment_shader() {
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\0";
static unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
int success;
char infoLog[512];
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
return fragmentShader;
}
建立着色器程序
static unsigned int shaderProgram;
shaderProgram = glCreateProgram();
//将两个着色器绑定在程序上
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
//链接着色器程序
glLinkProgram(shaderProgram);
//检测链接着色器程序是否失败
int success;
char infoLog[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::Program::COMPILATION_FAILED\n" << infoLog << std::endl;
}
//链接完成后删除着色器
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
渲染
//渲染循环
while (!glfwWindowShouldClose(window))
{
//按键输入事件
processInput(window);
//设置一个清屏颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
//执行清屏,这里选用的参数只会清除颜色缓冲
glClear(GL_COLOR_BUFFER_BIT);
//渲染部分
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
/* 矩形
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
*/
//交换颜色缓冲
glfwSwapBuffers(window);
//检查触发事件
glfwPollEvents();
}
总的来说只是照着LearnOpenGL敲了一遍,了解了一下渲染的流程,对其中不少函数的调用还是一知半解