当前位置: 首页 > news >正文

OpenGL绘制正方形、错误处理、统一变量、索引缓冲区

一、使用索引缓冲区绘制正方形

        由于opengl绘制图像都是以三角形为基础进行绘制的,所以当我们绘制多边形时,会使用多个三角形进行拼接,但是如果我们使用缓冲区将所有顶点都输入,那么在大型项目中会及其浪费内存,所以这里我们使用索引缓冲区,这样我们绘制多边形时,顶点缓冲区就可以不存放重复的点了。

 unsigned int indexArray[] = {0, 1, 2,0, 3, 1};//进行申请、绑定索引缓冲区内存
unsigned int indexBuffer = 0;glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indexArray, GL_STATIC_DRAW);/*
........
opengl其他操作
*/
while(!glfwWindowShouldClose(window))
{/*........opengl其他操作*///绘制,其中参数四:由于我们申请并绑定了索引缓冲区内存,所以这里我们给nullptr即可glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}

二、统一变量

        openGL中的统一变量类似于全局变量

1、在着色器代码中进行定义统一变量

uniform vec4 u_Color;

 2、在主函数中想着色器传统一变量

        注:在获取统一变量的索引时,需要判断是否正确找到,因为当统一变量未被使用时,可能会被编译器优化

int uniformIndex = glGetUniformLocation(program, "u_Color");
glUniform4f(uniformIndex, 0.2f, 0.3f, 0.8f, 1.0f);

三、错误处理

1、因为glDebugMessageCallback函数只能在4.3版本之后使用,索引为了通用性使用glGetError

2、为了方便调试使用vs宏__debugbreak()函数

3、由于我们每个gl函数都需要判断,索引将其编写为宏

#define ASSERT(x) if(x == false) __debugbreak();
#define GlCall(x) GlClearError();\x;\ASSERT(GlCheckError(#x, __FILE__, __LINE__))struct ShaderCodeT
{std::string vertexCode;std::string fragmentCode;
};static void GlClearError()
{while (glGetError() != GL_NO_ERROR);
}static bool GlCheckError(const char* funcChar, const char* fileChar, int line)
{while (unsigned int errorCode = glGetError()){std::cout << "[OpenGL Error] Error Code :" << errorCode << "\n" << funcChar << " " << fileChar << " :" << line << std::endl;return false;}return true;
}

四、完整代码

  1、主程序代码

#include <GL/glew.h>
#include <GLFW/glfw3.h>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>#define ASSERT(x) if(x == false) __debugbreak();
#define GlCall(x) GlClearError();\x;\ASSERT(GlCheckError(#x, __FILE__, __LINE__))struct ShaderCodeT
{std::string vertexCode;std::string fragmentCode;
};static void GlClearError()
{while (glGetError() != GL_NO_ERROR);
}static bool GlCheckError(const char* funcChar, const char* fileChar, int line)
{while (unsigned int errorCode = glGetError()){std::cout << "[OpenGL Error] Error Code :" << errorCode << "\n" << funcChar << " " << fileChar << " :" << line << std::endl;return false;}return true;
}static ShaderCodeT GetShaderCodeSrc(std::string filePath)
{enum class ShaderType{NONE = -1, VERTEX = 0, FRAGMENT = 1};std::fstream fileStream(filePath);std::stringstream ss[2];std::string line;ShaderType type = ShaderType::NONE;while (std::getline(fileStream, line)){if (line.find("shader") != std::string::npos){if (line.find("vertex") != std::string::npos)type = ShaderType::VERTEX;else if (line.find("fragment") != std::string::npos)type = ShaderType::FRAGMENT;}else{ss[(int)type] << line << '\n';}}std::cout << "VERTEX" << std::endl;std::cout << ss[(int)ShaderType::VERTEX].str() << std::endl;std::cout << "FRAGMENT" << std::endl;std::cout << ss[(int)ShaderType::FRAGMENT].str() << std::endl;return { ss[(int)ShaderType::VERTEX].str() ,ss[(int)ShaderType::FRAGMENT].str() };
}static unsigned int CompileSharder(const unsigned int type, const std::string src)
{int status;const char* srcCode = src.c_str();unsigned int id = glCreateShader(type);glShaderSource(id, 1, &srcCode, nullptr);glCompileShader(id);glGetShaderiv(id, GL_COMPILE_STATUS, &status);if (status == GL_FALSE){int length;glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);char* infoLog = (char*)alloca(length);glGetShaderInfoLog(id, length, &length, infoLog);std::cout << "Compile shader error:" << infoLog << std::endl;glDeleteShader(id);}return id;
}static unsigned int CreateProgram(const std::string vetexShard, const std::string fragmentShard)
{int id = glCreateProgram();if (id == 0){std::cout << "CreateProgram error" << std::endl;return 0;}unsigned int vs = CompileSharder(GL_VERTEX_SHADER, vetexShard);unsigned int fs = CompileSharder(GL_FRAGMENT_SHADER, fragmentShard);glAttachShader(id, vs);glAttachShader(id, fs);glLinkProgram(id);/*//可以不使用delete,内存占用不多glDeleteShader(vs);glDeleteShader(fs);*/return id;
}int main(void)
{GLFWwindow* window;float pointsArray[] = {0.5f,  0.5f,-0.5f, -0.5f,0.5f, -0.5f,-0.5f,  0.5f};unsigned int indexArray[] = {0, 1, 2,0, 3, 1};ShaderCodeT shaderCode = GetShaderCodeSrc("./res/shaders/Basic.shader");/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);glfwSwapInterval(1);int err = glewInit();if (err != GLEW_OK){std::cout << "error" << glewGetErrorString(err) << std::ends;return -1;}const GLubyte* version = glGetString(GL_VERSION);std::cout << "OpenGL版本:" << version << std::ends;unsigned int buffer = 0;//必须先绑定buffer后在使用glBufferDataGlCall(glGenBuffers(1, &buffer));GlCall(glBindBuffer(GL_ARRAY_BUFFER, buffer));GlCall(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), pointsArray, GL_STATIC_DRAW));GlCall(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0));GlCall(glEnableVertexAttribArray(0));unsigned int indexBuffer = 0;GlCall(glGenBuffers(1, &indexBuffer));GlCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer));GlCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indexArray, GL_STATIC_DRAW));GlCall(unsigned int program = CreateProgram(shaderCode.vertexCode, shaderCode.fragmentCode));GlCall(glUseProgram(program));GlCall(int uniformIndex = glGetUniformLocation(program, "u_Color"));if (uniformIndex == -1)ASSERT(false);float redColor = 0.0f;float redColorInterval = 0.01f;/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);if (redColor > 1.0f)redColorInterval = -0.01f;else if (redColor < 0.0f)redColorInterval = 0.01f;//使用opengl中着色器进行绘制// glDrawArrays(GL_TRIANGLES, 0, 3);GlCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));GlCall(glUniform4f(uniformIndex, redColor, 0.3f, 0.8f, 1.0f));redColor += redColorInterval;/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glDeleteProgram(program);glfwTerminate();return 0;
}

2、着色器代码 

#shader vertex#version 330 corelayout(location = 0) in vec4 position;void main()
{gl_position = position;
};#shader fragment#version 330 corelayout(location = 0) out vec4 color;uniform vec4 u_Color;void main()
{color = u_Color;
};

http://www.lryc.cn/news/598936.html

相关文章:

  • tcp基础协议
  • node.js中的path模块
  • MySQL深度理解-MySQL索引优化
  • AI服务器给一体成型电感带来多大的市场空间
  • Java学习日记_廖万忠
  • 深度解析:在Odoo 18中基于原生Owl框架为PWA定制功能丰富的底部导航栏
  • 面经 - 车载多媒体系统
  • Vue2——5
  • [CH582M入门第十一步]DS18B20驱动
  • 金仓数据库:从国产替代到AI融合的破局之路
  • Mysql窗口函数
  • 2025年海外短剧独立站开发:H5+PC端双平台技术实践与增长策略
  • 《AI流程编排中的Graph观测:设计原理与集成实践》
  • 高并发系统设计面试题
  • 深度分析Java多线程机制
  • MinIO 版本管理实践指南(附完整 Go 示例)
  • 【AI】Java生态对接大语言模型:主流框架深度解析
  • P1308 [NOIP 2011 普及组] 统计单词数
  • PH73211L_VC1/PH73211LQ_VC1:低功耗USB HiFi音频解码器固件技术解析
  • 力扣刷题HOT100——跳跃游戏
  • 康养休闲旅游服务虚拟仿真实训室:赋能人才培养的创新路径
  • 2025年7月23日 AI 今日头条
  • 2025最新MySQL面试题实战记录,互联网公司常问题目
  • day46day47 通道注意力
  • 高级04-Java 设计模式:常用模式详解与实战
  • 【STM32项目】智能台灯
  • 大模型Prompt优化工程
  • 将Scrapy项目容器化:Docker镜像构建的工程实践
  • 跨境支付入门~国际支付结算(稳定币)
  • 最大团--贪心例题