計算機圖形學作業(一):利用OpenGL繪製三角形,並利用ImGUI增加顏色編輯窗口

計算機圖形學作業(一):利用OpenGL繪製三角形,並利用ImGUI增加顏色編輯窗口

前言

OpenGL一般被認爲是一個API(Application Programming Interface, 應用程序編程接口),包含了一系列可以操作圖形、圖像的函數。由於OpenGL是一個圖形API,並不是一個獨立的平臺,它需要一個編程語言來工作,在這裏我們使用的是C++,而編輯器使用VS2017。關於OpenGL有個非常詳細的官方教程:https://learnopengl-cn.github.io/intro/,這裏僅僅對OpenGL的學習作總結。

繪製三角形

只要按照教程的步驟一步步進行,繪製三角形的過程並不難,代碼在下面會給出。效果圖如下所示:
在這裏插入圖片描述

顏色編輯窗口

ImGUI的配置

前往ImGUI的github倉庫https://github.com/ocornut/imgui,然後將庫文件壓縮包下載到本地,然後解壓。把下圖這些文件添加到剛纔畫三角形的VS2017的項目中。
在這裏插入圖片描述

然後進入ImGUI庫的example文件夾,因爲此次我們的項目是利用ImGUI給OpenGL所畫的圖形增加顏色編輯窗口,所以我們選擇下圖的文件,添加到項目中。
在這裏插入圖片描述
還有以下兩個文件:
在這裏插入圖片描述

最終,原來的利用OpenGL畫三角形的項目中,多個ImGUI的庫文件,文件結構如下:
在這裏插入圖片描述

修改imgui_impl_opengl3.h文件

按照前面OpenGL的官方教程,配置環境時,我們使用到了一個glad的庫,而不是gl3w的庫,所以在imgui_impl_opengl3.h文件中,把IMGUI_IMPL_OPENGL_LOADER_GL3W替換爲IMGUI_IMPL_OPENGL_LOADER_GLAD

#if !defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)     \
 && !defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)     \
 && !defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)     \
 && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
#define IMGUI_IMPL_OPENGL_LOADER_GLAD          //IMGUI_IMPL_OPENGL_LOADER_GL3W
#endif

編寫顏色編輯器代碼

這部分主要代碼如下:

//創建並綁定ImGui
 const char* glsl_version = "#version 130";
 IMGUI_CHECKVERSION();
 ImGui::CreateContext();
 ImGuiIO& io = ImGui::GetIO(); (void)io;
 ImGui::StyleColorsDark();
 ImGui_ImplGlfw_InitForOpenGL(window, true);
 ImGui_ImplOpenGL3_Init(glsl_version);
 
 //創建imgui
 ImGui_ImplOpenGL3_NewFrame();
 ImGui_ImplGlfw_NewFrame();
 ImGui::NewFrame();

 ImGui::Begin("Edit color", &show_window, ImGuiWindowFlags_MenuBar);
 ImGui::ColorEdit3("top color", (float*)&topColor);
 ImGui::ColorEdit3("left color", (float*)&leftColor);
 ImGui::ColorEdit3("right color", (float*)&rightColor);
 ImGui::End();

 ImGui::Render();
 int display_w, display_h;
 glfwMakeContextCurrent(window);
 glfwGetFramebufferSize(window, &display_w, &display_h);
 glViewport(0, 0, display_w, display_h);
 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

效果

如下圖:
在這裏插入圖片描述

項目源代碼

main.cpp的代碼如下:

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);

//頂點着色器可以向片段着色器傳數據
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.x, aPos.y, aPos.z, 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.0);\n"
	"}\0";

int main() {
	//初始化opengl窗口和配置
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	
	GLFWwindow* window = glfwCreateWindow(1000, 800, "LearnOpenGL", NULL, NULL);
	if (window == NULL) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//創建並綁定ImGui
	const char* glsl_version = "#version 130";
	IMGUI_CHECKVERSION();
	ImGui::CreateContext();
	ImGuiIO& io = ImGui::GetIO(); (void)io;
	ImGui::StyleColorsDark();
	ImGui_ImplGlfw_InitForOpenGL(window, true);
	ImGui_ImplOpenGL3_Init(glsl_version);

	//頂點着色器
	unsigned int vertexShader;
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);

	//片段着色器
	unsigned int fragmentShader;
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);

	//着色器程序
	unsigned int shaderProgram;
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);

	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	/*
	float vertices[] = {
		-0.5f, -0.5f, 0.0f,
		0.5f, -0.5f, 0.0f,
		0.0f, 0.5f, 0.0f
	};
	*/

	//顏色數據
	ImVec4 topColor = ImVec4(0.0f, 0.0f, 1.0f, 1.0f);
	ImVec4 leftColor = ImVec4(0.0f, 1.0f, 0.0f, 1.0f);
	ImVec4 rightColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);

	bool show_window = true;

	unsigned int VAO;
	unsigned int VBO;
	unsigned int EBO;

	while (!glfwWindowShouldClose(window)) {
		float vertices[] = { // 注意索引從0開始! 
		//位置				顏色
		0.5f, -0.5f, 0.0f, rightColor.x, rightColor.y, rightColor.z,
		-0.5f, -0.5f, 0.0f, leftColor.x, leftColor.y, leftColor.z,
		0.0f, 0.5f, 0.0f, topColor.x, topColor.y, topColor.z,
		1.0f, -0.5f, 0.0f, rightColor.x, rightColor.y, rightColor.z,
		0.5f, -0.5f, 0.0f, leftColor.x, leftColor.y, leftColor.z,
		0.75f, 0.25f, 0.0f, topColor.x, topColor.y, topColor.z,
		-0.75f, 0.5f, 0.0f, rightColor.x, rightColor.y, rightColor.z,
		-0.75f, -0.5f, 0.0f, leftColor.x, leftColor.y, leftColor.z,
		};

		unsigned int indices[] = { // 注意索引從0開始! 
			0, 1, 2, // 第一個三角形
			3, 4, 5,
			6, 7, 8
		};

		//必須先綁定VA0
		glGenVertexArrays(1, &VAO);
		glBindVertexArray(VAO);


		//再綁定VBO
		glGenBuffers(1, &VBO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


		//使用EBO畫多個三角形,組合成其它圖形
		glGenBuffers(1, &EBO);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


		//再設置屬性
		//位置屬性
		//屬性位置值爲0的頂點屬性
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(0);

		//顏色屬性
		//屬性位置值爲1的頂點屬性。顏色值有3個float那麼大
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
		glEnableVertexAttribArray(1);

		processInput(window);

		//使用着色器程序
		glUseProgram(shaderProgram);

		glfwPollEvents();

		//清除屏幕
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		//創建imgui
		ImGui_ImplOpenGL3_NewFrame();
		ImGui_ImplGlfw_NewFrame();
		ImGui::NewFrame();

		ImGui::Begin("Edit color", &show_window, ImGuiWindowFlags_MenuBar);
		ImGui::ColorEdit3("top color", (float*)&topColor);
		ImGui::ColorEdit3("left color", (float*)&leftColor);
		ImGui::ColorEdit3("right color", (float*)&rightColor);
		ImGui::End();

		ImGui::Render();
		int display_w, display_h;
		glfwMakeContextCurrent(window);
		glfwGetFramebufferSize(window, &display_w, &display_h);
		glViewport(0, 0, display_w, display_h);
		ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

		//畫三角形
		glBindVertexArray(VAO);
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		//畫線段,偏移6個點,畫2點之間的線段
		glDrawArrays(GL_LINES, 6, 2);

		glfwSwapBuffers(window);
	}

	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);

	

	glfwTerminate();

	return 0;
}

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);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章