計算機圖形處理(一)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章