LearnGL - 05.3 - 封装 Main.cpp 中重复 GLFW代码


LearnGL - 学习笔记目录

本人才疏学浅,如有什么错误,望不吝指出。

上一篇:LearnGL - 05.2 - Texture - 实现类似2D UI流光动画

这一篇:到这篇,我终于忍不了了,太多重复代码了。所以我们将一些可复用代码整理一下,一些通用型比较强的功能都统统封装一下。


这次先提取 Main 中的重复代码。

后面再提炼:GameObject、Mesh、Camera、Material、等。

以方便后续增加 OpenGL 学习项目的便利性。

但前提先增加对 OpenGL 设计规范的熟悉程度。

my_init.h

初始化相关的内容:

  • 创建窗体
  • 创建 OpenGL Context
  • 提供外部设置回调初始化
  • 提供外部设置更新/绘制回调
  • 提供外部设置退出程序前回调
  • 提供执行入口:run()

my_gl_check_error.h

对 GL 的错误状态的检测

my_simple_load_tex.h

简单加载纹理

外部使用

// jave.lin
#include<glad/glad.h>
//#include"linmath.h"
// 把linmath.h 放在 iostream 之前include会有错误,所以放到iostream 后include就好了
// 而这个错误正式 xkeycheck.h 文件内 #error 提示的,所以可以使用 #define _XKEYCHECK_H 这个头文件的引用标记宏
// 就可以避免对 xkeycheck.h 头文件的 include 了。
#include<iostream>
#include<linmath.h>
#include<shader.h>
// 使用 stb_image.h 的加载库
// github 源码:https://github.com/nothings/stb/blob/master/stb_image.h
#define STB_IMAGE_IMPLEMENTATION
#include<stb_image.h>
// 将之前的打印版本信息代码包含一下
#include<my_init.h>
#include<my_gl_check_error.h>
#include<my_simple_load_tex.h>

using namespace my_util;

GLfloat vertices[] = {
	// x,	y,	  z
	// 直接放4个顶点
	-0.5f, -0.5f, 0.0f,							// 第0个顶点,左下角
	 0.5f, -0.5f, 0.0f,							// 第1个顶点,右下角
	 0.5f,  0.5f, 0.0f,							// 第2个顶点,右上角
	-0.5f,  0.5f, 0.0f,							// 第3个顶点,左上角
};

GLfloat uvs[] = {								// 顶点的 uv 坐标
	0.0f, 0.0f,									// 左下角
	1.0f, 0.0f,									// 右下角
	1.0f, 1.0f,									// 右上角
	0.0f, 1.0f,									// 左上角
};

GLuint indices[] = {							// 注意索引从0开始!通过索引缓存来指定 图元 组成 用的 顶点有哪些
	0, 1, 3,									// 放置顶点的索引,第一个三角形
	1, 2, 3										// 放置顶点的索引,第二个三角形
};

GLint vpos_location, vuv_location;
GLuint vertex_buffer[2], index_buffer;
GLuint vertex_array_object;
GLuint texture[3];
GLuint pixelBufObject;
GLint success, infoLogLen;
ShaderProgram* shaderProgram;
GLuint win_width, win_height;

void _stdcall OnBeforeInitWinCallback(InitInfo* info) {
	info->width = win_width = 600;
	info->height = win_height = 600;
	info->print_version_info = true;
	const char* title = "05_03_ExtracMain_GLFW_SrcCode";
	strcpy_s(info->win_title, strlen(title) + 1, title);
}

void _stdcall OnInitCallback() {
	// 打印支持最大的顶点支持的数量
	int nrAttributes;
	glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &nrAttributes);
	std::cout << "Maximum number of vertex attributes supported : " << nrAttributes << std::endl;

	// 打印着色器支持最大的纹理图像单元的数量
	int maxTexUnit;
	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnit);
	std::cout << "Maximun number of texture image units : " << maxTexUnit << std::endl;

	// 打印着色器支持最大的所有组合的纹理图像单元的数量
	int maxCombinedTexUnit;
	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTexUnit);
	std::cout << "Maximun number of Combined texture image units : " << maxCombinedTexUnit << std::endl;

	// 用 lambda 设置,获取 pic 目录的回调,后面在封装
	g_GetPicturePathCallback = [](char* receiveBuff, const char* file)->char* {
		char buf[MAX_PATH];
		sprintf_s(buf, "..\\..\\Dependencies\\Pic\\%s", file);
		strcpy_s(receiveBuff, MAX_PATH, buf);
		return receiveBuff;
	};
	// 用 lambda 设置,获取 shader 目录的回调,后面在封装
	g_GetShaderPathCallback = [](char* receiveBuff, const char* file)->char* {
		char buf[MAX_PATH];
		sprintf_s(buf, "..\\..\\Dependencies\\Shaders\\%s", file);
		strcpy_s(receiveBuff, MAX_PATH, buf);
		return receiveBuff;
	};

	shaderProgram = new ShaderProgram;
	// shader program init 5 - 根据shader源码的相对路径(变量),加载deps下的shader
	char vs_path[MAX_PATH], fs_path[MAX_PATH];
	g_GetShaderPathCallback(vs_path, "TestingTexture\\tex_2d_ui_flash_light.vert");
	g_GetShaderPathCallback(fs_path, "TestingTexture\\tex_2d_ui_flash_light.frag");
	if (!shaderProgram->initByPath(vs_path, fs_path)) {
		std::cout << "ShaderProgram init Error: " << shaderProgram->errorLog() << std::endl; // 输出shader program错误
		exit(EXIT_FAILURE);
	}

	glCreateTextures(GL_TEXTURE_2D, 3, texture);					// 创建 3 个纹理对象

	glActiveTexture(GL_TEXTURE0);									// 激活第 0 索引纹理单元
	glBindTextureUnit(0, texture[0]);								// 纹理单元 0 绑定:主纹理
	glActiveTexture(GL_TEXTURE1);									// 激活第 1 索引纹理单元
	glBindTextureUnit(1, texture[1]);								// 纹理单元 0 绑定:遮罩纹理
	glActiveTexture(GL_TEXTURE2);									// 激活第 2 索引纹理单元
	glBindTextureUnit(2, texture[2]);								// 纹理单元 0 绑定:闪光/流光纹理
	checkGLError();

	loadTexture(texture[0], "my_tex.png");							// 加载纹理对象0:主纹理
	loadTexture(texture[1], "my_tex_flash_mask.jpg");				// 加载纹理对象1:遮罩纹理
	loadTexture(texture[2], "flash.png");							// 加载纹理对象2:闪光/流光纹理
	checkGLError();

	vpos_location = shaderProgram->getAttributeLoc("vPos");			// 获取 顶点着色器中的顶点 attribute 属性的 location
	vuv_location = shaderProgram->getAttributeLoc("vUV");			// 获取 顶点着色器中的顶点 attribute 属性的 location

	glGenVertexArrays(1, &vertex_array_object);						// 生成1个 VAO

	glGenBuffers(2, vertex_buffer);									// 创建2个 VBO,这里我们因为有一个一样的顶点坐标,一个一样的顶点UV
	glGenBuffers(1, &index_buffer);									// 创建1个 EBO,因为两个 Quad 的顶点索引顺序都是一样的
	//
	// === VAO[0] ===
	//
	glBindVertexArray(vertex_array_object);						// 绑定 VAO[0],那么之后的 vbo, ebo,的绑定指针都是指向该 VAO 中的,还有顶点格式(规范)都会保存在该 VAO

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]);				// 绑定 VBO[0]
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 设置 VBO 坐标数据

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[1]);				// 绑定 VBO[1]
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW); // 设置 VBO uv数据

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);			// 绑定 EBO
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 设置 EBO 数据

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]);				// 绑定 VBO[0],因为后面要设置该 VBO 的坐标格式
	glVertexAttribPointer(vpos_location, 3, GL_FLOAT, GL_FALSE,		// 设置 顶点属性 vPos 格式
		sizeof(GLfloat) * 3, (GLvoid*)0);
	glEnableVertexAttribArray(vpos_location);						// 启用 顶点缓存 location 位置的属性

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[1]);				// 绑定 VBO[1],因为后面要设置该 VBO 的uv格式
	glVertexAttribPointer(vuv_location, 2, GL_FLOAT, GL_FALSE,		// 设置 顶点属性 vUV 格式
		sizeof(GLfloat) * 2, (GLvoid*)0);
	glEnableVertexAttribArray(vuv_location);						// 启用 顶点缓存 location uv的属性

	glViewport(0, 0, win_width, win_height);						// 设置视口坐标
}

void _stdcall OnBackBuffResizeCallback(const int width, const int height) {
	glViewport(0, 0, width, height);
	win_width = width;
	win_height = height;
}

void _stdcall OnUpdateCallback() {
	glClearColor(0.1f, 0.2f, 0.1f, 0.f);							// 设置清理颜色缓存时,填充颜色值
	glClear(GL_COLOR_BUFFER_BIT);									// 清理颜色缓存

	shaderProgram->use();											// 使用此着色器程序
	shaderProgram->setInt("main_tex", 0);							// 主			纹理设置采样器采样 0 索引纹理单元
	shaderProgram->setInt("mask_tex", 1);							// 遮罩			纹理设置采样器采样 1 索引纹理单元
	shaderProgram->setInt("flash_light_tex", 2);					// 闪光/流光	纹理设置采样器采样 2 索引纹理单元
	shaderProgram->setFloat("time", (float)glfwGetTime());			// 测试用就直接用字符串了,方便一些

	glBindVertexArray(vertex_array_object);							// 先绘制 VAO[0] 的 VBO,EBO,VAF,ENABLED
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (GLvoid*)0);	// 参数1:绘制三角图元;参数2:取6个索引来绘制三角图元(每个三角图元需要3个,所以可以画两个三角图元);参数3:将 GL_ELEMENT_ARRAY_BUFFER 每个元素视为 uint 类型;参数4:设置索引缓存的字节偏移量。也可以设置为另一个 缓存数据的指针,即:使用另一个数据。
}

void _stdcall OnBeforeExitCallback() {
	glDeleteBuffers(1, &pixelBufObject);							// 测试删除 BO
	glDeleteBuffers(2, vertex_buffer);								// 测试删除 VBO
	glDeleteBuffers(1, &index_buffer);								// 测试删除 EBO
	glDeleteBuffers(1, &vertex_array_object);						// 测试删除 VAO
	glDeleteTextures(3, texture);									// 删除纹理对象 TO
	delete shaderProgram;											// 销毁 shader program
	checkGLError();													// 最后再看看GL还有什么错误
}

int main() {
	g_BeforeInitWinCallback		= OnBeforeInitWinCallback;
	g_InitCallback				= OnInitCallback;
	g_BackBuffResizeCallback	= OnBackBuffResizeCallback;
	g_UpdateCallback			= OnUpdateCallback;
	g_BeforeExitCallback		= OnBeforeExitCallback;
	return run();
} // int main() {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值