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的初步了解使用。