Question:
1. 使用OpenGL(3.3及以上)+GLFW或freeglut画一个简单的三角形。
2. 对三角形的三个顶点分别改为红绿蓝,像下面这样。
3. 给上述工作添加一个GUI,里面有一个菜单栏,使得可以选择并改变三角形的颜色。
4. 绘制其他的图元,除了三角形,还有点、线等。
5. 使用EBO(Element Buffer Object)绘制多个三角形。
Answer:
#include <glad/glad.h> #include <GLFW/glfw3.h> #include "imgui.h" #include "imgui_impl_glfw_gl3.h" #include <iostream> using namespace std; void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); } const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in vec3 aColor;\n" "out vec3 ourColor;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos, 1.0);\n" " ourColor = aColor;\n" "}\0"; const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "in vec3 ourColor;\n" "void main()\n" "{\n" " FragColor = vec4(ourColor, 1.0f);\n" "}\n\0"; static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Error %d: %s\n", error, description); } int main(int, char**) { // Setup window glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow* window = glfwCreateWindow(1280, 720, "my_window", NULL, NULL); glfwMakeContextCurrent(window); glfwSwapInterval(1); // Enable vsync glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwGL3_Init(window, true); // Setup style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); //bool show_demo_window = true; //bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); float r_1 = 0.0f; float g_1 = 0.0f; float b_1 = 1.0f; float r_2 = 1.0f; float g_2 = 0.0f; float b_2 = 0.0f; float r_3 = 0.0f; float g_3 = 1.0f; float b_3 = 0.0f; float r_4 = 0.0f; float g_4 = 1.0f; float b_4 = 0.0f; float vertices[] = { 0.5f, -0.5f, 0.0f, r_1, g_1, b_1, -0.5f, -0.5f, 0.0f, r_2, g_2, b_2, 0.0f, 0.5f, 0.0f, r_3, g_3, b_3 }; unsigned int VBO, VAO, EBO; unsigned int VBO1, VAO1; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glUseProgram(shaderProgram); static int e = 1; // Main loop while (!glfwWindowShouldClose(window)) { processInput(window); glfwPollEvents(); ImGui_ImplGlfwGL3_NewFrame(); // 1. Show a simple window. // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static int counter = 0; ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) //ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) counter++; ImGui::SameLine(); ImGui::Text("counter = %d", counter); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); //static int e = 0; if (ImGui::CollapsingHeader("Shape")) { ImGui::RadioButton("triangle", &e, 0); ImGui::RadioButton("point", &e, 1); ImGui::RadioButton("line", &e, 2); ImGui::RadioButton("rectangle", &e, 3); } int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAO); if (e == 0) { glDrawArrays(GL_TRIANGLES, 0, 3); // 描绘三角形 } if (e == 1) { glDrawArrays(GL_POINTS, 0, 3); //描绘点 glPointSize(6); // 改变点的大小 } if (e == 2) { glDrawArrays(GL_LINES, 0, 3); // 描绘线 } if (e == 3) { float vertices[] = { 0.5f, 0.5f, 0.0f, r_1, g_1, b_1, 0.5f, -0.5f, 0.0f, r_2, g_2, b_2, -0.5f, -0.5f, 0.0f, r_3, g_3, b_3, -0.5f, 0.5f, 0.0f, r_4, g_4, b_4 }; unsigned int indices[] = { 0, 1, 3, 1, 2, 3 }; glGenVertexArrays(1, &VAO1); glGenBuffers(1, &VBO1); glGenBuffers(1, &EBO); glBindVertexArray(VAO1); glBindBuffer(GL_ARRAY_BUFFER, VBO1); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glUseProgram(shaderProgram); glBindVertexArray(VAO1); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } if (ImGui::CollapsingHeader("Color")) { if (ImGui::SliderFloat("1_color:red", &r_1, 0.0f, 1.0f) || ImGui::SliderFloat("1_color:green", &g_1, 0.0f, 1.0f) || ImGui::SliderFloat("1_color:blue", &b_1, 0.0f, 1.0f) || ImGui::SliderFloat("2_color:red", &r_2, 0.0f, 1.0f) || ImGui::SliderFloat("2_color:green", &g_2, 0.0f, 1.0f) || ImGui::SliderFloat("2_color:blue", &b_2, 0.0f, 1.0f) || ImGui::SliderFloat("3_color:red", &r_3, 0.0f, 1.0f) || ImGui::SliderFloat("3_color:green", &g_3, 0.0f, 1.0f) || ImGui::SliderFloat("3_color:blue", &b_3, 0.0f, 1.0f)) { float vertices[] = { 0.5f, -0.5f, 0.0f, r_1, g_1, b_1, -0.5f, -0.5f, 0.0f, r_2, g_2, b_2, 0.0f, 0.5f, 0.0f, r_3, g_3, b_3 }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glUseProgram(shaderProgram); } } } ImGui::Render(); ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteVertexArrays(1, &VAO1); glDeleteBuffers(1, &VBO1); // Cleanup ImGui_ImplGlfwGL3_Shutdown(); ImGui::DestroyContext(); glfwTerminate(); return 0; }
Algorithm description:
使用opengl和imgui进行编程,在一个源代码中实现以上所有功能。题目较简单,只是一些基本的opengl函数调用,以及对imgui的初步了解使用。