opengl 创建context_OpenGL学习笔记1-创建窗口,绘制三角形

27eca285b7456a118c4eec23c69dae03.png

使用GLFW创建窗口

首先引用头文件

#include <glad/glad.h>  
#include <GLFW/glfw3.h>  
//注意头文件引用的先后顺序
glfwInit();

//设置窗口标识
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//glfw大版本
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//glfw小版本
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//opengl库
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);//在mac平台下需要这样设置

windowHandler = glfwCreateWindow(1280, 800, "GLFW created window", nullptr, nullptr);//创建1280*800大小的窗口,同时设定了窗口标题
if(!windowHandler){
    Debug::GetInstance()->LogE("Creating GLFW window FAIL!", "Window");
    glfwTerminate();
    return;
}
//设定当前线程的绘制在刚刚创建的窗口上进行
glfwMakeContextCurrent(windowHandler);

//加载opengl库函数
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
    Debug::GetInstance()->LogE("GLAD init FAILD", "Window");
    return;
}

//设置viewport大小
glViewport(0, 0, 1280, 800);

//设置窗口大小改变事件回调,当窗口的大小被用户改变时回调用_WindowResizeCallBack函数
glfwSetFramebufferSizeCallback(windowHandler, _WindowResizeCallBack);
//窗口大小改变事件回调函数的定义
void _WindowResizeCallBack(GLFWwindow *win, int w, int h){
    glViewport(0, 0, w, h);
}

定义四边形(两个三角形)

//VAO
unsigned int vao;
glGenVertexArrays(1, &vao);//生成一个vao
glBindVertexArray(vao);//绑定vao

//VBO
float vs[] = {//定义四边形的四个点的3d坐标
     0.5f,  0.5f, 0.0f,  // top right
     0.5f, -0.5f, 0.0f,  // bottom right
    -0.5f, -0.5f, 0.0f,  // bottom left
    -0.5f,  0.5f, 0.0f   // top left 
};
unsigned int indices[] = {//定义两个三角形所使用的点,索引vs中的顶点
    0, 1, 3,   // first triangle
    1, 2, 3    // second triangle
};
unsigned int vbo;//vbo储存所有顶点信息
glGenBuffers(1, &vbo);//生成一个buffer,并将id储存到vbo中
glBindBuffer(GL_ARRAY_BUFFER, vbo);//将array buffer绑定到vbo
glBufferData(GL_ARRAY_BUFFER, sizeof(vs), vs, GL_STATIC_DRAW);//自动将vs中的顶点数据传输到array buffer所绑定的buffer即vbo中

//EBO
unsigned int ebo;//ebo用来储存索引vbo中的信息
glGenBuffers(1, &ebo);//生成一个buffer,并将id储存到ebo中
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);//将element array buffer绑定到ebo中
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//自动将indices中的索引数据传输到element array buffer所绑定的buffer即ebo中

//linking vertex attributes
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//设定第0号顶点信息配置,每个顶点占用3个GL_FLOAT的元素(即3d坐标),同时向量化设为否,一个顶点数据的长度为3 * sizeof(float)
glEnableVertexAttribArray(0);//启用第0号顶点信息配置,这里的编号对应于vertex shader 中的layout(location = 0)
glBindVertexArray(0);//取消绑定vao

加载顶点着色器(vertex shader)和片元着色器(fragment shader)

//vertex shader
//读取顶点着色器源代码
string verString = FileHelper::ReadString(theApp->currentExecutionPath + "/shaders/ver.txt");

unsigned int ver = glCreateShader(GL_VERTEX_SHADER);//创建顶点着色器
auto verCString = verString.c_str();
Debug::GetInstance()->LogI(verCString, "vertex shader");
glShaderSource(ver, 1, &(verCString), nullptr);//向shader添加源代码
glCompileShader(ver);//编译shader

int success;
char infoLog[512];
glGetShaderiv(ver, GL_COMPILE_STATUS, &success);//获取是否编译成功
if(!success)
{
    glGetShaderInfoLog(ver, 512, nullptr, infoLog);//获取编译信息
    Debug::GetInstance()->LogE(infoLog, "Vertex Shader Compile Error");
}

//fragment shader
//获取片元着色器源代码
string fragString = FileHelper::ReadString(theApp->currentExecutionPath + "/shaders/frag.txt");

unsigned frag = glCreateShader(GL_FRAGMENT_SHADER);//创建片元着色器
auto fragCString = fragString.c_str();
Debug::GetInstance()->LogI(fragCString, "fragment shader");
glShaderSource(frag, 1, &(fragCString), nullptr);//向shader添加源代码
glCompileShader(frag);//编译shader

glGetShaderiv(frag, GL_COMPILE_STATUS, &success);//获取是否编译成功
if(!success)
{
    glGetShaderInfoLog(frag, 512, nullptr, infoLog);//获取编译信息
    Debug::GetInstance()->LogE(infoLog, "Fragment Shader Compile Error");
}

//shader program
unsigned int shaderProgram = glCreateProgram();//创建一个program
glAttachShader(shaderProgram, ver);//添加顶点着色器
glAttachShader(shaderProgram, frag);//添加片元着色器
glLinkProgram(shaderProgram);//执行链接操作

glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);//获取是否链接成功
if(!success)
{
    glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);//获取链接消息
    Debug::GetInstance()->LogE(infoLog, "Shader Program Link Error");
}

glUseProgram(shaderProgram);//使用program

glDeleteShader(ver);//释放顶点着色器
glDeleteShader(frag);//释放片元着色器

绘制定义好的四边形(在循环中执行的渲染过程)

//清屏操作
glClearColor(0.2f, 0.1f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

//设置以线框模式绘制
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glUseProgram(theShaderProgram);//使用之前编译好的shader program
glBindVertexArray(theVAO);//绑定vao,之后的绘制函数都将在绑定的vao上进行
//glDrawArrays(GL_TRIANGLES, 0, 3);//绘制vbo
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);//绘制ebo
//glBindVertexArray(0);//取消绑定vao


glfwSwapBuffers(windowHandler);
glfwPollEvents();

顶点着色器和片元着色器的源代码

Vertex Shader

#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

fragment Shader

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(0.4f, 0.6f, 0.7f, 1.0f);
}

关于VAO,VBO, EBO

b8965016d4a042025ade7de81ee2504c.png

VAO会储存VBO, EBO以及设置好的顶点信息配置。所以在添加VBO和EBO之前,先绑定好VAO。然后在后续的绘制渲染过程仅需要提供VAO即可,VBO,EBO和顶点信息配置都能通过VAO获取。


版权声明:本文为weixin_39843782原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。