OpenGL初始化,窗口创建,着色器配置

初始化glfw

glfwInit();

设置主版本号,次版本号,使用核心配置,设置窗口大小不能被改变

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

定义一个窗口唯一标识符,用来存储和被引用(相当于一个身份证信息)

GLFWwindow* window = glfwCreateWindow(800, 600, "i'm a lovely girl", nullptr, nullptr);

第一个参数:宽度。第二个参数:高度。三:名称。四:默认监视器(主显示屏)。五(是否和其它窗口共享上下文)

 创建失败就终止。

if (window == nullptr) {
	std::cout << "Failed to create GLFW window" << std::endl;
	glfwTerminate();
	return -1;
}

上下文是一个对象,它具有一下信息

  1. 渲染状态: 上下文中包含了当前的渲染状态,比如当前使用的顶点缓冲区、顶点数组对象、着色器程序、纹理单元等。这些状态会影响 OpenGL 渲染的结果。

  2. 视口信息: 视口是屏幕上用于显示图形的区域,上下文中包含了当前的视口设置,包括位置和大小。

  3. 着色器状态: 上下文中包含了当前的顶点着色器和片段着色器程序。这些程序定义了 GPU 如何处理图形数据。

  4. 缓冲区状态: 上下文中包含了与渲染相关的缓冲区,比如颜色缓冲区、深度缓冲区、模板缓冲区等。

  5. 纹理状态: 包括当前绑定的纹理对象、纹理过滤器、纹理包裹方式等设置。

  6. 帧缓冲状态: 上下文中包含了当前绑定的帧缓冲对象,它用于渲染到纹理或多重采样缓冲区。

  7. 渲染状态: 包括渲染模式(如线框模式或填充模式)、剔除面的设置等。

  8. OpenGL 版本信息: 上下文中包含了当前 OpenGL 实现的版本号、支持的扩展等信息。

现在的窗口并不具有上下文,只是一个空窗口,我们要将它与上下文联系起来

glfwMakeContextCurrent(window);

下面这个设置就完了,相当于开了一些新功能

glewExperimental = GL_TRUE;

 初始化glew

if (glewInit() != GLEW_OK){
	std::cout << "Failed to initialize GLEW" << std::endl;
	return -1;	
}

到目前为止,我们把该初始化的两个库,该设置的版本信息,该创建的窗口都做了,并把窗口和上下文对象连接了起来(牵了根线)。

下面设置帧缓冲区对象(要渲染的区域大小)的大小和窗口大小(渲染的区域在窗口的大小)

int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);

一般是一样的,可以理解为渲染的作用范围

在主函数之前,我们要写一个顶点着色器和片段着色器源码

//顶点着色器源码
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";


//片段着色器源码
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

layout (location = 0) in vec3 position意思是输入一个三维坐标

out vec4 color意思是输出一个四维的颜色

#version 330 core定义版本号

 下面创建顶点着色器

GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
//将着色器源码附在着色器上
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
//将字符串类型的源码编译
glCompileShader(vertexShader);

glCreatShader(类型)

检查是否创建成功

GLint success;
GLchar 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;
}

创建一个片段着色器,并检查是否出错

GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success){
	glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
	std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}

创建着色器程序,连接并链接

GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
	glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
	std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
//删除着色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);

glLinkProgram 会对指定的着色器程序进行链接操作,检查各个着色器之间的兼容性,并生成最终的可执行程序,用于在 GPU 上执行渲染操作。

下面输入顶点

GLfloat vertices[] = {
	-0.5f,-0.5f,0.0f,
	 0.5f,-0.5f,0.0f,
	 0.0f, 0.5f,0.0f
};

创建锅

GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

绑定锅(名字和锅具绑定到一起)

// 绑定VAO
glBindVertexArray(VAO);

// 绑定VBO,并将顶点数据复制到VBO中
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBufferData相当于数据线,用于传输数据的。

VAO就像一个餐桌,而VBO是各种盘子

下面配置顶点属性

位置(position=0),每个顶点坐标分量个数(3),类型,是否映射到[0,1](否,我们要[-1,1],步长下一个点的位置,这个不用管偏移量为0但是要强转)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
确保数据有效,从position=0开始
glEnableVertexAttribArray(0);

下面还有一个解绑操作,数据已经传输过去了,现在断开连接(断开VAO和VBO)

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

下面是游戏循环

while (!glfwWindowShouldClose(window)) {
		//检查事件
		glfwPollEvents();
		//这一部分是渲染(背景颜色)
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
       
		//启用着色器
		glUseProgram(shaderProgram);
        //VAO里存储了顶点的状态,我们每次渲染都需要绑定一次之前设置好的VAO
		glBindVertexArray(VAO);
        //画出三角形
		glDrawArrays(GL_TRIANGLES, 0, 3);
        //解绑,避免被更改
		glBindVertexArray(0);
		//交换前后缓冲
		glfwSwapBuffers(window);
	}
    //终止程序
	glfwTerminate();

一个普通的橙色三角形

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值