日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

OpenGL中的Shader

發(fā)布時(shí)間:2023/12/2 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenGL中的Shader 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.csdn.net/huangcanjun187/article/details/52474365

學(xué)習(xí)總結(jié)自:http://learnopengl.com/#!Getting-started/Hello-Triangle?
http://learnopengl.com/#!Getting-started/Shaders?
繼上篇文章中提到,OpenGL是為了在GPU上同時(shí)跑成千上萬(wàn)個(gè)程序,在GPU上跑的這些小程序,稱為Shader。

準(zhǔn)備

我們?cè)谶\(yùn)行GPU程序前,得準(zhǔn)備幾樣?xùn)|西:1)輸入數(shù)據(jù)。2)數(shù)據(jù)緩沖區(qū)。3)Shader程序。4)GLSL(OpenGL Shade Language)主程序。?
以畫(huà)一個(gè)三角形為例,?
1)輸入數(shù)據(jù)包括:a. 三點(diǎn)頂點(diǎn)的坐標(biāo)。b. 三個(gè)頂點(diǎn)的顏色。

GLfloat vertices[] = {// 坐標(biāo) // 顏色0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下角 -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下角 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 頂點(diǎn) };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2)數(shù)據(jù)緩存區(qū)包括:a. 數(shù)據(jù)怎么識(shí)別。哪一塊是坐標(biāo)數(shù)據(jù)?哪一塊是顏色數(shù)據(jù)? b. 哪一塊數(shù)據(jù)是第一個(gè)三角形的數(shù)據(jù)?哪一塊數(shù)據(jù)是第二個(gè)三角形的數(shù)據(jù)?

GLuint VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);// 首先綁定VAO結(jié)構(gòu)。一個(gè)VAO對(duì)應(yīng)一個(gè)形狀對(duì)象,包含了一個(gè)形狀的所有屬性,包括顏色、坐標(biāo)等等。用shader程序調(diào)用VAO這個(gè)結(jié)構(gòu),可以畫(huà)出對(duì)應(yīng)的圖像來(lái)。 glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//在綁定VAO之后,綁定VBO結(jié)構(gòu)。**這樣VBO就屬于之前被綁定VAO的一部分。**里面包含了預(yù)先定義好的數(shù)組vertices,vertices就是一個(gè)浮點(diǎn)數(shù)組,包含具體的坐標(biāo)、顏色值。 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0);// 坐標(biāo)屬性。讓Vertex Shader將這部分?jǐn)?shù)據(jù)作為坐標(biāo)導(dǎo)入。 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1);// 顏色屬性。讓Vertex Shader將這部分?jǐn)?shù)據(jù)作為坐標(biāo)顏色值導(dǎo)入。 glBindVertexArray(0); // Unbind VAO
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3)Shader 程序。將導(dǎo)入GPU的數(shù)據(jù),為對(duì)應(yīng)的坐標(biāo)點(diǎn)畫(huà)上對(duì)應(yīng)的顏色。

// Shaders const GLchar* vertexShaderSource = "#version 330 core\n""layout (location = 0) in vec3 position;\n"//location = 0,與之前綁定VAO步驟中的函數(shù)glEnableVertexAttribArray(0)對(duì)應(yīng),把坐標(biāo)數(shù)據(jù)導(dǎo)入到 vec3 position 這個(gè)shader中的坐標(biāo)變量。 "layout (location = 1) in vec3 color;\n"//location = 1,與之前綁定VAO步驟中的函數(shù)glEnableVertexAttribArray(1)對(duì)應(yīng),把坐標(biāo)數(shù)據(jù)導(dǎo)入到 vec3 color這個(gè)shader中的顏色變量。 "out vec3 ourColor;\n" "void main()\n" "{\n" "gl_Position = vec4(position, 1.0);\n" "ourColor = color;\n"//將顏色值直接賦值給輸出的變量ourColor,在Fragment Shader中也有一個(gè)同名的變量,所有最終像素的顏色就是此顏色值。 "}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n" "in vec3 ourColor;\n" //OpenGL Shader程序會(huì)直接將同名的變量聯(lián)系到一起,這個(gè)ourColor就是vertex shader中的輸出的ourColor "out vec4 color;\n" "void main()\n" "{\n" "color = vec4(ourColor, 1.0f);\n" "}\n\0";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

4)GLSL 主程序

GLuint shaderProgram = glCreateProgram(); //創(chuàng)建一個(gè)GLSL主程序glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);//將兩個(gè)shader掛載到主程序上glLinkProgram(shaderProgram);//鏈接shader程序。編譯shader的步驟在此之前。接下來(lái)會(huì)詳細(xì)介紹
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

步驟

為何要將1)輸入數(shù)據(jù)。2)數(shù)據(jù)緩沖區(qū)。3)Shader程序。4)GLSL(OpenGL Shade Language)主程序。這個(gè)幾個(gè)模塊分開(kāi)介紹呢??
因?yàn)檫@幾塊相互獨(dú)立,這是OpenGL比較明顯的特點(diǎn)。詳細(xì)說(shuō),就是GLSL主程序可以鏈接任意一個(gè)編譯好的shader程序,編譯好的shader程序可以裝載不同的VAO(Vertext Array Object,它是VBO的老大,Shader 調(diào)用的時(shí)候是直接調(diào)VAO,VBO包含了數(shù)據(jù),VAO包含了VBO以及如何讓Shader識(shí)別這些VBO數(shù)據(jù)的一些屬性),VAO又可以用不同的方式裝載不同的數(shù)據(jù)。?
以這段代碼為例,只粘貼了比較關(guān)鍵的代碼,完整源碼請(qǐng)參考:?
http://learnopengl.com/code_viewer.php?code=getting-started/shaders-interpolated?
程序的結(jié)果就是對(duì)三角形的三個(gè)頂點(diǎn)畫(huà)上紅、綠、藍(lán)三種顏色,三角形中間區(qū)域的顏色OpenGL會(huì)自動(dòng)插值出來(lái),這是OpenGL的神奇之處(我也還沒(méi)懂原理)。?

//--------------這不是完整源碼,著重介紹重要的幾個(gè)步驟------------------////---------編寫(xiě)shader 程序----------// const GLchar* vertexShaderSource = "#version 330 core\n""layout (location = 0) in vec3 position;\n" "layout (location = 1) in vec3 color;\n" "out vec3 ourColor;\n" "void main()\n" "{\n" "gl_Position = vec4(position, 1.0);\n" "ourColor = color;\n" "}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n" "in vec3 ourColor;\n" "out vec4 color;\n" "void main()\n" "{\n" "color = vec4(ourColor, 1.0f);\n" "}\n\0";//簡(jiǎn)單易懂的Shader源碼 //---------編譯和鏈接shader程序----------// GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); //因?yàn)閟hader程序是在GPU上跑,所以不是和CPP文件一起編譯。Shader程序如果有BUG,在編譯CPP的時(shí)候不會(huì)出錯(cuò),而是在運(yùn)行CPP工程的時(shí)候報(bào)錯(cuò)。 GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); //將shader程序與GLSL主程序鏈接到一起 //---------編寫(xiě)VAO,VBO以及具體導(dǎo)入的數(shù)據(jù)----------// GLfloat vertices[] = { // Positions // Colors 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // Bottom Right -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Left 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // Top };//三個(gè)頂點(diǎn)的坐標(biāo)和顏色值 GLuint VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO);//可以生成多個(gè)VAO和多個(gè)VBO。一個(gè)只能對(duì)應(yīng)一個(gè)VBO。畫(huà)多個(gè)圖形,就得用不同的VAO包含不同的VBO glBindVertexArray(VAO);//綁定VAO之后,接下來(lái)的所有操作都被記錄到此VAO當(dāng)中,直到這個(gè)VAO被解除綁定為止。VAO就是畫(huà)一個(gè)圖形所需要的所有屬性。綁定完這個(gè)VAO之后,可以接著綁定其它的VAO。 glBindBuffer(GL_ARRAY_BUFFER, VBO);//綁定VBO到當(dāng)前VAO中,注意GL_ARRAY_BUFFER這個(gè)類(lèi)型只能綁定一個(gè)VBO glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//綁定數(shù)據(jù)到VBO對(duì)象當(dāng)中 // Position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);//坐標(biāo)位置在vertices數(shù)組中起始點(diǎn)為0,步長(zhǎng)為6個(gè)FLOAT數(shù)據(jù)的長(zhǎng)度 glEnableVertexAttribArray(0);//用vertex shader中的Location0來(lái)導(dǎo)入數(shù)據(jù),Location0就是坐標(biāo)數(shù)據(jù) // Color attribute glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));//坐標(biāo)位置在vertices數(shù)組中起始點(diǎn)為3,步長(zhǎng)為6個(gè)FLOAT數(shù)據(jù)的長(zhǎng)度 glEnableVertexAttribArray(1);//用vertex shader中的Location1來(lái)導(dǎo)入數(shù)據(jù),Location0就是顏色標(biāo)數(shù)據(jù) glBindVertexArray(0); // 解除綁定VAO,對(duì)這個(gè)VAO的所有操作到此為止,之前的操作被全部保存 // 循環(huán)畫(huà)圖 while (!glfwWindowShouldClose(window)) { // 檢測(cè)是否有鍵盤(pán)觸發(fā)事件 glfwPollEvents(); // Render // Clear the colorbuffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//設(shè)置背景顏色 glClear(GL_COLOR_BUFFER_BIT); // Draw the triangle glUseProgram(shaderProgram);//導(dǎo)入一個(gè)GLSL主程序 glBindVertexArray(VAO);//導(dǎo)入其中一個(gè)VAO,一個(gè)主程序可以鏈接多個(gè)VAO,在畫(huà)完這個(gè)VAO之后,可以接著畫(huà)另外一個(gè)VAO代表的圖形。這是OpenGL比較明顯的特征 glDrawArrays(GL_TRIANGLES, 0, 3);//畫(huà)三角形 glBindVertexArray(0); //glBindVertexArray()將VAO屬性復(fù)位,也就是不綁定任意一個(gè)VAO // Swap the screen buffers glfwSwapBuffers(window); }

轉(zhuǎn)載于:https://www.cnblogs.com/jukan/p/6999890.html

總結(jié)

以上是生活随笔為你收集整理的OpenGL中的Shader的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。