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;
};