OpenGL是什么?Win10+VS2019下搭建glfw+glad开发环境
1、什么是OpenGL
什么是OpenGL
-
OpenGL 是一套API接口。
學習這套接口,就可以在那些支持OpenGL的機器上正常使用這些接口,在屏幕上看到繪制的結(jié)果。 -
顯卡廠商的支持
這套接口是 Khronos(科納斯) 這個組織在維護,怎么維護呢? 就是寫一個說明書,指導(dǎo)各個GPU廠家,如果他們要支持OpenGL的話,要怎么實現(xiàn)一個具體的OpenGL庫。Khronos說要實現(xiàn)glDrawArray這個接口,那么廠家就得在他的庫里實現(xiàn)這個接口。如果不實現(xiàn),那么就不算支持OpenGL。也有一些接口不一定要實現(xiàn)。
Khronos每隔一段時間發(fā)布一個新的OpenGL API版本,就是發(fā)布這個說明書。一般兩個,一個是core profile,一定要實現(xiàn)的,還有另一個是為了兼容舊版本接口的說明書。
廠家實現(xiàn)的OpenGL庫的內(nèi)容其實就是廠家自己的團隊整合自己的圖形知識以及GPU硬件的指令。
OpenGL的Open指的是接口是開放的,而具體實現(xiàn)的庫一般都是不公開的。目前據(jù)我所知,mesa 3d是一個開源的實現(xiàn)。 -
與Direct3D的關(guān)系
像AMD、Nvidia等圖形硬件廠家還得支持Direct3D,所以他們還得按照微軟的接口說明書,整合Direct3D的庫給Windows使用。
在Windows上,還有一種情況,就是這個OpenGL庫可能是Direct3D接口的一個封裝(Wrapper)。表面上調(diào)用OpenGL接口,實際上里面的實現(xiàn)是間接調(diào)用了Direct3D接口。 -
另外OpenGL 只是關(guān)注于怎么調(diào)用接口實現(xiàn)繪畫 。
為了使用OpenGL,還得初始化一個OpenGL環(huán)境。這個環(huán)境需要AGL、WGL、GLX這些庫里的接口來建立。這幾個庫分別對應(yīng)蘋果系統(tǒng)、Windows、還有Linux的X-Window,沒有實現(xiàn)跨平臺。
這也是為什么存在glut(已經(jīng)不更新了,代替者freeglut,不支持macOS)、glfw這些 “半”跨平臺的框架幫助你輕松地在各平臺下使用OpenGL。 -
與OpenCV的關(guān)系
OpenCV是Intel開源計算機視覺庫。
Opencv是從圖像到數(shù)據(jù)
OpenGL是從數(shù)據(jù)到圖像
OpenGL主要功能是什么
-
1、建模:OpenGL圖形庫除了提供基本的點、線、多邊形的繪制函數(shù)外,還提供了復(fù)雜的三維物體(球、錐、多面體、茶壺等)以及復(fù)雜曲線和曲面繪制函數(shù)。
-
2、變換:OpenGL圖形庫的變換包括基本變換和投影變換。基本變換有平移、旋轉(zhuǎn)、縮放、鏡像四種變換,投影變換有平行投影(又稱正射投影)和透視投 影兩種變換。其變換方法有利于減少算法的運行時間,提高三維圖形的顯示速度。
-
3、顏色模式設(shè)置:OpenGL顏色模式有兩種,即RGBA模式和顏色索引(Color Index)。
-
4、光照和材質(zhì)設(shè)置:OpenGL光有自發(fā)光(Emitted Light)、環(huán)境光(Ambient Light)、漫反射光(Diffuse Light)和高光(Specular Light)。材質(zhì)是用光反射率來表示。場景(Scene)中物體最終反映到人眼的顏色是光的紅綠藍分量與材質(zhì)紅綠藍分量的反射率相乘后形成的顏色。
-
5、紋理映射(Texture Mapping)。利用OpenGL紋理映射功能可以十分逼真地表達物體表面細節(jié)。
-
6、位圖顯示和圖象增強圖象功能除了基本的拷貝和像素讀寫外,還提供融合(Blending)、抗鋸齒(反走樣)(Antialiasing)和霧(fog)的特殊圖象效果處理。以上三條可使被仿真物更具真實感,增強圖形顯示的效果。
-
7、雙緩存動畫(Double Buffering)雙緩存即前臺緩存和后臺緩存,簡言之,后臺緩存計算場景、生成畫面,前臺緩存顯示后臺緩存已畫好的畫面。
2、OpenGL環(huán)境配置
① OpenGL的組成部分
————先來看一篇引用文章(OpenGL的前生今世)
OpenGL中的各類庫
gl.h
gl庫是核心庫,gl中包含了最基本的3D函數(shù),可以再本地電腦中的: C:\Program Files (x86)\ Microsoft SDKs\Windows \v7.0A\Include\gl 路徑下找到gl.h頭文件,打開后可以看到其中定義的上百個相關(guān)函數(shù)。
glu.h
glu是實用庫,包含有43個函數(shù),函數(shù)名的前綴為glu。glu 為了減輕繁重的編程工作,glu對gl中的函數(shù)進行部分封裝,glu函數(shù)通過調(diào)用核心庫的函數(shù),為開發(fā)者提供相對簡單的用法,實現(xiàn)一些較為復(fù)雜的操作。如果算術(shù)好,在不使用glu庫的情況下,使用gl庫可以實現(xiàn)同樣的效果。
glut.h
gult:OpenGL工具庫 OpenGL Utility Toolkit。 glut是基本的窗口界面,是獨立于gl和glu的,如果不喜歡用glut可使用MFC和Win32窗口等代替。但是glut是跨平臺的,這就保證了我們編出的程序具有跨平臺性,而使用MFC或Win32只能在windows操作系統(tǒng)上使用。
主要包括窗口操作函數(shù),窗口初始化、窗口大小、窗口位置等函數(shù);回調(diào)函數(shù):響應(yīng)刷新消息、鍵盤消息、鼠標消息等等。 這個頭文件自動包含了gl.h和glu.h,編程時不必再次包含它們。
freeglut.h
各種教程和書里常見的是閉源的GLUT。但由于GLUT的作者已經(jīng)很久沒更新過了(最后更新于2000年!= =),所以其他人另外做了一個接口兼容GLUT的freeglut,開源而且一直在維護中。可以理解為glut的替代庫。
glew
GLUT或者FREEGLUT主要是1.0的基本函數(shù)功能;GLEW是使用OPENGL2.0之后的一個工具函數(shù)。不同的顯卡公司,也會發(fā)布一些只有自家顯卡才支持的擴展函數(shù),你要想用這數(shù)涵數(shù),不得不去尋找最新的glext.h,有了GLEW擴展庫,你就再也不用為找不到函數(shù)的接口而煩惱,因為GLEW能自動識別你的平臺所支持的全部OpenGL高級擴展函數(shù)。也就是說,只要包含一個glew.h頭文件,你就能使用gl,glu,glext,wgl,glx的全部函數(shù)。
glad和glew的作用相同,可看做它的升級版。
glfw.h
GLFW無愧于其號稱的lightweight的OpenGL框架,一個頭文件,很少量的API,就完成了任務(wù)。GLFW的開發(fā)目的是用于替代glut的,從代碼和功能上來看,我想它已經(jīng)完全的完成了任務(wù)。它是一個輕量級的,開源的,跨平臺的library。支持OpenGL及OpenGL ES,用來管理窗口,讀取輸入,處理事件等。因為OpenGL沒有窗口管理的功能,所以很多熱心的人寫了工具來支持這些功能,比如早期的glut,現(xiàn)在的freeglut等。那么GLFW有何優(yōu)勢呢?glut太老了,最后一個版本還是90年代的。freeglut完全兼容glut,算是glut的代替品,功能齊全,但是bug太多。穩(wěn)定性也不好(不是我說的啊),GLFW應(yīng)運而生。并且glfw也是跨平臺的~!
glfw可以看做是freeglut的升級版,freeglut可以看做是glut的升級版
- 綜上所述,為了安裝一個OpenGL,你需要一個3D函數(shù)庫和一個窗口管理庫。
3D函數(shù)庫可選:gl&glu,升級版glew,再升級glad。
窗口管理庫可選:glut,升級版freeglut,再升級glfw。
② 窗口管理庫GLFW的安裝
-
GLFW官網(wǎng)下載:https://www.glfw.org/download.html
windows一般下載 ,32-bit.。此處32和64指的不是本機器的位數(shù),而是生成目標的位數(shù)。 windows pre-compiled binaries,為windows預(yù)編譯版本
-
整理所需文件到另一個文件夾:需要include文件夾和本機對應(yīng)版本的"lib-vc20**"文件夾。如我的vs是2019,就復(fù)制include和lib-vc2019。
-
打開VS2019,新建一個c++win32控制臺項目
-
依次點擊“視圖" —>“屬性頁”, 在vc++目錄,“包含目錄”和“庫目錄”分別添加解壓復(fù)制后的Incude和lib目錄。 注意路徑。
-
在 “連接器” ->“附加依賴項”中添加“opengl32.lib”和"glfw3.lib",用分號隔開
-
在在源文件中添加如下代碼測試環(huán)境
#include <GLFW/glfw3.h>int main(void) {GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);glBegin(GL_TRIANGLES);glVertex2d(0.5f, 0.5f);glVertex2d(-0.5f, -0.5f);glVertex2d(0.5f, -0.5f);glEnd();/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0; }
③3D函數(shù)庫 glad的安裝
-
glad官網(wǎng)下載:https://glad.dav1d.de/
語言選擇C/C++,在API選項中,選擇3.3以上的OpenGL(gl)版本(因為glfw不支持更早的版本,>=3.3都可以,具體可以看顯卡支持到哪個版本 )。
之后將模式(Profile)設(shè)置為Core,并且保證生成加載器(Generate a loader)的選項是選中的。
現(xiàn)在可以先(暫時)忽略拓展(Extensions)中的內(nèi)容。
都選擇完之后,點擊生成(Generate)按鈕來生成庫文件。
-
下載glad.zip文件解壓,就可以得到我們需要的include\glad\ glad.h、include\KHR\ khrplatform.h和src\ glad.c這3個文件
-
進入VS2019項目,在項目屬性 ----> C/C++ —> 附加包含目錄 —> your_path\glad\include
-
最后在項目中添加glad.c 文件
-
以下代碼測試是否安裝成功
#include <glad\glad.h> //這個必須放在GLFW之前 #include <GLFW\glfw3.h>#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow* window);// settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600;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"; 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";int main() {// glfw: initialize and configure// ------------------------------glfwInit(); //glfw 初始化//設(shè)置OpenGL版本等信息glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X #endif// glfw window creation// --------------------//創(chuàng)建GLFW窗口GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL) {std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}//設(shè)置當前上下文glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);// glad: load all OpenGL function pointers// ---------------------------------------//把OpenGL的函數(shù)指針導(dǎo)入給GLADif (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// build and compile our shader program// ------------------------------------// vertex shaderint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);// check for shader compile errorsint 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;}// fragment shaderint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// check for shader compile errorsglGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}// link shadersint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// check for linking errorsglGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);// set up vertex data (and buffer(s)) and configure vertex attributes// ------------------------------------------------------------------float vertices[] = {0.5f, 0.5f, 0.0f, // top right0.5f, -0.5f, 0.0f, // bottom right-0.5f, -0.5f, 0.0f, // bottom left-0.5f, 0.5f, 0.0f // top left };unsigned int indices[] = {// note that we start from 0!0, 1, 3, // first Triangle1, 2, 3 // second Triangle};unsigned int VBO, VAO, EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);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, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbindglBindBuffer(GL_ARRAY_BUFFER, 0);// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.glBindVertexArray(0);// uncomment this call to draw in wireframe polygons.//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// render loop// -----------//循環(huán)渲染while (!glfwWindowShouldClose(window)) {// input// -----processInput(window);// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// draw our first triangleglUseProgram(shaderProgram);glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized//glDrawArrays(GL_TRIANGLES, 0, 6);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);// glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------//交換緩存glfwSwapBuffers(window);//事件處理glfwPollEvents();}// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);// glfw: terminate, clearing all previously allocated GLFW resources.// ------------------------------------------------------------------//停止glfwTerminate();return 0; }// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- //輸入處理函數(shù) void processInput(GLFWwindow* window) {if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true); }// glfw: whenever the window size changed (by OS or user resize) this callback function executes //窗口大小設(shè)置回調(diào)函數(shù) // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) {// make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays.glViewport(0, 0, width, height); }
總結(jié)
以上是生活随笔為你收集整理的OpenGL是什么?Win10+VS2019下搭建glfw+glad开发环境的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java script特效_javasc
- 下一篇: javascript特效