笔者为了做一些计算流体力学的东西,在看了很多论文后开始着手编写程序。原本是打算借用GitHub上面的项目框架,自己再往里添加自己的东西。但是,为了发文章以及在老师和学长的建议下,还是准备自己完成整个工程。于是乎,有了现在的再学OpenGL!!!
早在2017年6月,为了早点融入新的环境开始了自己新的学习之旅。第一个就是OpenGL!并没有太深入的学习,也就是网上找了一些简单的教程,跟着教程简单的学习一下,运行一下程序。感受了一下OpenGL,知道了“哦,原来是这么回事!”。到底怎么回事?
OpenGL和很多一些开源库(工具)不一样,OpenGL函数没有明确的是输入输出以及作用对象。就拿OpenCV来说,cvtColor函数如下:
cvtColor(Mat src,Mat dst,Size size);
有着明确的输入兼作用对象src,输出dst,卷积核大小size。很明确,很明了。只要会点C/C++的人都会使用这个函数!但是,OpenGL就很不一样了,比如:
glMatrixMode (GL_PROJECTION );
glLoadIdentity ();
新手一看就懵了,这是干啥啊?连个输入和输出都没有啊?
OpenGL代码看多会发现:很多函数是在对某个或某些“源”进行操作,而且这个或这些“源”是某个或某些公用的东东。
所以,无需像OpenCV那样需要指定每次操作的对象。比如,在上面其实就是对Projection矩阵的操作,不是没有操作对象。只是这个矩阵是个公用的,函数可以“看到”。后来知道了,OpenGL是一个
状态机
。在OpenGL里,可以理解为全局变量。为什么要使用状态机好像与由于OpenGL内核是由C写的有关,具体就不在这里讨论了。
#include
#include
#include
unsigned int shaderProgram;
GLFWwindow* window;
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int VAO,VBO;
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void vertexAndFragmentShader()
{
/*Vertex Shader*/
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
/*Compile Shader*/
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
/*fragment shader*/
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
/*Compile Shader*/
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
int success;
char 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;
}
/*Shader Program Object*/
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::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void initWork()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
//return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
//return -1;
}
glViewport(0, 0, 800, 600);
/* call this function on every window resize for resizing viewport*/
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
}
void linkingVertexAttributes()
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//attrib location ,attrib size,type,normalize,stride,offset
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);//attrib location
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
/************** MAIN ******************/
int main()
{
initWork();
/*shader*/
vertexAndFragmentShader();
linkingVertexAttributes();
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
while (!glfwWindowShouldClose(window))
{
/*keyborad input*/
processInput(window);
/*render*/
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
/*glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.*/
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
运行结果: