著色器: triangles.vert
#version 430 corelayout(location = 0) in vec4 vPosition;void main(){ gl_Position = vPosition;}其中 1.在程序起始的位置使用#version來聲明所使用的版本,這里430表示使用OpenGL4.3對應的GLSL語言,core表示使用OpenGL核心模式。 2.vec4是GLSL的四維浮點數向量,vec4的默認值為(0,0,0,1) 3.in字段指定了數據進入著色器的流向 4.layout(location = 0)是布局限定符,目的是為變量提供元數據。
triangles.frag
#version 430 coreout vec4 fColorvoid main(){ fColor = vec4(0.0,0.0,1.0,1.0);}其中 1.指定out限定符,進fColor對應的數值輸出。
實現程序:
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"enum VAO_IDs{ Triangles, NumVAOs };enum Buffer_IDs{ ArrayBuffer, NumBuffers };enum Attrib_IDs{ vPosition = 0 };GLuint VAOs[NumVAOs];GLuint Buffers[NumBuffers];const GLuint NumVertices = 6;void init(void){ //void glGenVertexArrays(GLsizei n,GLuint *arrays); //返回n個未使用的對象名到數組arrays中,用作頂點數組對象。返回的名字可以用來分配更多的緩存對象, //并且他們已經使用未初始化的頂點數組集合的默認狀態進行了數值的初始化。 glGenVertexArrays(NumVAOs, VAOs); //void glBindVertexArray(GLuint array) //如果輸入的變量array非0,并且是glGenVertexArrays()所返回的,那么它將創建一個新的頂點數組對象并且與其名稱 //關聯起來。如果綁定到一個已經創建的頂點數組對象中,那么會激活這個頂點數組對象,并且直接影響對象中所保存 //的頂點數組狀態。如果輸入的變量array為0,那么OpenGL將不再使用程序所分配的任何頂點數組對象,并且將渲染狀 //態重設為頂點數組的默認狀態。如果array不是glGenVertexArrays()所返回的數值,或者它已經被glDeleteVertexArrays() //函數釋放了,那么這里將產生一個GL_INVALID_OperaTION錯誤。 glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2] = { { -0.90, -0.90 }, { 0.85, -0.90 }, { -0.90, 0.85 }, { 0.90, -0.85 }, { 0.90, 0.90 }, { -0.85, 0.90 } }; //void glGenBuffers(GLsizei n,GLuint *buffers) //返回n個當前未使用的緩存對象名稱,并保存到buffers數組中。返回到buffers中的名稱不一定 //是連續的整形數據。這里返回的名稱只用于分配其他緩存對象,他們在綁定之后只會記錄一個可用 //的狀態。0是一個保留的緩存對象名稱,glGenBuffers()永遠都不會返回這個值的緩存對象。 glGenBuffers(NumBuffers, Buffers); //void glBindBuffer(GLenum target,GLuint buffer) //指定當前激活的緩存對象。target必須設置為以下類型中的一個:GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER //GL_PIXEL_PACK_BUFFER,GL_PIXEL_UNPACK_BUFFER,GL_COPY_READ_BUFFER,GL_COPY_WRITE_BUFFER,GL_TRANSFORM_FEEDBACK_BUFFER //和GL_UNIFORM_BUFFER.buffer設置的是要綁定的緩存對象名稱。 //如果是第一次綁定buffer,且它是一個非零的無符號整形,那么將創建一個與該名稱相對應的新緩存對象。如果綁定到一個已經創建的緩存對象 //那么它將成為當前被激活的緩存對象。如果綁定的buffer值為0,那么OpenGL將不再對當前target應用任何緩存對象。 glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]); //void glBufferData(GLenum target,GLsizeiptr size,const GLvoid *data,GLenum usage) //在OpenGL服務端內存中分配size個存儲單位(通常為byte),用于存儲數據或者索引。如果當前綁定的對象已經存在了關聯的數據,那么會首先刪除這些數據。 //對于頂點屬性數據,target設置為GL_ARRAY_BUFFER,索引數據為GL_ELEMENT_ARRAY_BUFFER;OpenGL的像素數據為GL_PIXEL_UNPACK_BUFFER;對于從OpenGL中獲取 //的像素數據為GL_PIXEL_PACK_BUFFER,對于緩存之間的復制數據為GL_COPY_READ_BUFFER和GL_COPY_WRITE_BUFFER;對于紋理緩存中存儲的紋理數據為GL_TEXTURE_BUFFER //對于通過transform feedback著色器獲得的結果設置為GL_TRANSFORM_FEEDBACK_BUFFER;而一致變量要設置為GL_UNIFORM_BUFFER.size表示存儲數據的總數量。這個數值 //等于data中存儲的元素的總數乘以單位元素存儲空間的結果。data要么是一個客戶端內存的指針,以便初始化緩存對象,要么是NULL.如果傳入的指針合法,那么將會有 //size大小的數據從客戶端拷貝到服務端。如果傳入NULL,那么將保留size大小的初始化數據,以備后用。usage用于設置分配數據之后的讀取和寫入方式??捎玫姆绞桨? //GL_STREAM_DRAW,GL_STREAM_READ,GL_STREAM_COPY,GL_STATIC_DRAW,GL_STATIC_READ,GL_STATIC_COPY,GL_DYNAMIC_DRAW,GL_DYNAMIC_READ和GL_DYNAMIC_COPY.如果所需 //的size大小超過了服務端能夠分配的額度,那么glBufferData()將產生一個GL_OUT_OF_MEMORY錯誤。如果usage設置的不是可用的模式值,那么將產生GL_INVALID_VALUE錯誤。 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag" }, { GL_NONE, NULL } }; GLuint PRogram = LoadShaders(shaders); //void glUseProgram(GLuint program) //使用鏈接過的著色器程序program.如果program為0,那么所有當前使用的著色器都會被清除。如果沒有綁定任何著色器,那么OpenGL的操作結果是未定義的,但是不會產生錯誤。 //如果已經啟用了一個程序,而它需要關聯新的著色器對象,或者解除之前關聯的對象,那么我們需要重新對它進行鏈接。如果鏈接過程成功,那么新的程序會直接替代之前啟用 //的程序。如果鏈接失敗,那么當前綁定的著色器程序依然是可用的,不會被替代,知道我們成功地重新鏈接或者使用glUseProgram()指定了新的程序為止。 glUseProgram(program); //void glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid*pinter) //設置index(著色器中的屬性位置,即layout(location = 0) in vec4 vPosition;中的0)位置對應的數據值。pointer表示緩存對象中,從其實位置開始計算的數組數據的偏移值 //(假設起始地址為0),使用基本的系統單位(byte).size表示每個頂點需要更新的分量數目,可以是1,2,3,4或者GL_BGRA。type指定了數組中每個元素的數據類型(GL_BYTE, //GL_UNSIGNED_BYTE,GL_SHORT,GL_UNSIGNED_SHORT,GL_INT,GL_UNSIGNED_INT,GL_FIXED,GL_HALF_FLOAT,GL_FLOAT或GL_DOUBLE)。normalized設置頂點數據在存儲前是否需要歸一化 //(或者使用glVertexAttribFourN*()函數)。stride是數組中每2個元素之間的大小偏移值(byte).如果stride為0,那么數據應該緊密地封裝在一起。 glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); //void glEnableVertexAttribArray(GLuint index) //設置是否啟用與index索引相關聯的頂點數組。index必須是一個介于0到GL_MAX_VERTEX_ATTRIBS-1之間的值。 glEnableVertexAttribArray(vPosition);}void display(void){ //void glClear(GLbitfield mask) //清除指定的緩存數據并重設為當前的清除值。mask是一個可以通過邏輯“或”操作來指定多個數值的參數。可用的數值:顏色緩存:GL_COLOR_BUFFER_BIT //深度緩存GL_DEPTH_BUFFER_BIT,模板緩存:GL_STENCIL_BUFFER_BIT. glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]); //void glDrawArrays(GLenum mode,GLint first, GLsizei count) //使用數組元素建立連續的幾何圖元序列,每個啟用的數組中起始位置為first,結束位置為first+count-1.mode表示構建圖元的類型,它必須是GL_TRIANGLES, //GL_LINE_LOOP,GL_LINES,GL_POINTS等類型標識符之一。 glDrawArrays(GL_TRIANGLES, 0, NumVertices); //glFlush() //強制之前的OpenGL命令立即執行,這樣可以保證他們在一定時間內全部完成。 glFlush();}int main(int argc, char** argv){ //負責初始化GLUT庫. //它會處理向程序輸入的命令行參數,并且移除其中與控制GLUT如何操作相關的部分(例如設置窗口的大小) //glutInit必須是應用程序調用的第一個GLUT函數,它會負責設置其他GLUT例程所必須的數據結構。 glutInit(&argc, argv); //設置程序所使用的窗口類型。其中GLUT_RGBA表示RGBA顏色空間。 glutInitDisplayMode(GLUT_RGBA); //設置所需的窗口大小。 glutInitWindowSize(512, 512); //設置使用OpenGL4.3版本 glutInitContextVersion(4, 3); //設置使用OpenGL核心模式。 glutInitContextProfile(GLUT_CORE_PROFILE); //創建窗口 glutCreateWindow(argv[0]); //不加這句glGenVertexArrays奔潰 glewExperimental = GL_TRUE; if (glewInit()) { cerr << "Unable to initialize GLEW .. exiting" << endl; exit(EXIT_FAILURE); } init(); //設置顯示回調,即GLUT在每次更新窗口內容的時候會自動調用的例程。 glutDisplayFunc(display); //這是一個無限執行的循環,它會負責一直處理窗口和操作系統的用戶輸入等操作。 //例如它會判斷窗口是否需要重繪,然后它就會自動調用glutDisplayFunc()中注冊的函數。 //glutMainLoop是一個無限循環,因此不會執行在它之后的所有命令。 glutMainLoop();}新聞熱點
疑難解答