程式碼可以直接去Notion貼。跟著這影片打ㄉ,只是做其他延伸。成品:
先從Main看
glew是OpenGL Extension Wrangler Library,提供方便開發(fā)的程式庫。
他文件有講
82-86行: 定義3個2維座標。 怎麼知道是2維的下面會說。《First you need to create a valid OpenGL rendering context and call glewInit() to initialize the extension entry points. If glewInit() returns GLEW_OK, the initialization succeeded and you can use the available extensions as well as core OpenGL functionality. For example:》意思是要先有"視窗"可以render才能glewInit()。 所以才需放在生成視窗的程式碼下方。
89行 glGenBuffers(1, &buffer); // 產(chǎn)生指定數(shù)量的buffer namesunsigned int是不為負數(shù)的整數(shù)宣告,同opengl自己創(chuàng)的型態(tài)"GLuint"。影片中有講到建議使用c++原本的型態(tài)而非openGL的,原因是不想被綁定在opengl。
glGenBuffers(buffer 數(shù)量, &id)"&id"官方文件說是 《an array in which the generated buffer object names are stored.》說是array,應(yīng)該是array開始的位置。如果調(diào)皮這樣玩:輸出: b1 1 b2 4
無法保證id是連續(xù)的int,但能保證回傳的id目前沒被使用。
glBindBuffer(target, buffer)
設(shè)定該buffer的儲存處理方式(?。
target: 決定bind的處理型態(tài)。 (表)
Buffer Binding Target Purpose GL_ARRAY_BUFFER Vertex attributes GL_ATOMIC_COUNTER_BUFFER Atomic counter storage GL_COPY_READ_BUFFER Buffer copy source GL_COPY_WRITE_BUFFER Buffer copy destination GL_DISPATCH_INDIRECT_BUFFER Indirect compute dispatch commands GL_DRAW_INDIRECT_BUFFER Indirect command arguments GL_ELEMENT_ARRAY_BUFFER Vertex array indices GL_PIXEL_PACK_BUFFER Pixel read target GL_PIXEL_UNPACK_BUFFER Texture data source GL_QUERY_BUFFER Query result buffer GL_SHADER_STORAGE_BUFFER Read-write storage for shaders GL_TEXTURE_BUFFER Texture data buffer GL_TRANSFORM_FEEDBACK_BUFFER Transform feedback buffer GL_UNIFORM_BUFFER Uniform block storage
91行 glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), position, GL_STATIC_DRAW);
creates and initializes a buffer object's data store。
void glBufferData(
GLenum target, //哪種型態(tài)的容器駐列
GLsizeiptr size, //資料大小const GLvoid * data, //資料GLenum usage);
size這裡直接hardcode 6 * sizeof(float)。usage is a hint to the GL implementation as to how a buffer object's data store will be accessed.(告訴GL該資料是如何被訪問的。)
依訪問頻率分:
- STREAM : 資料只寫入一次,並訪問次數(shù)少。
- STATIC : 資料只寫入一次,並訪問次數(shù)多。
- DYNAMIC : 資料寫入次數(shù)多,訪問次數(shù)多。
依訪問性質(zhì)分(參考):
- DRAW : app寫入但不讀取。 you will put data into the buffer, but you will not read from it
- READ: 讀取但不寫入。 you will read data from the buffer, but you will not write to it (typically for transform feedback or pixel buffers)
- COPY:對buffer資料不直接讀寫,由GL讀寫。you will neither read from nor write to the buffer directly.
index=0,意思是從頭開始讀取vertex。在這裡就是position[0]
void glVertexAttribPointer(
注意stride是指vertex資料之間的byte數(shù)量。 這裡vertex資料只有單純的xy兩個float,所以是sizeof(float) * 2。GLuint index,GLint size, //維度,僅1~4,2=2DGLenum type, //data typeGLboolean normalized, //是否需要做normalized處理GLsizei stride, //vertex與vertex之間的byte數(shù)量const GLvoid * pointer);假設(shè)一個點有{
float xfloat yfloat uv_xfloat uv_y
96-120行: hardcode vs和fs程式碼。}則stride= sizeof(float) * 4但一個 vertex資料型態(tài)通常會有position、normal、uv、textcord....等資訊,可以將該資訊包成一個資料型態(tài)Vertex,則stride=sizeof(Vertex)*n
會將values四個陣列空間放置在索引2,3,4,5。layout(location = 2) in vec3 values[4];
更多詳細的可以看Layout Qualifier (GLSL),擷取段有趣的地方:
121行: 自訂函數(shù)如下似乎搞懂了Unity shader的vs和fs變數(shù)宣告道理了
寫(const string& vertexShader, const string& fragmentShader) 或(string vertexShader, string fragmentShader)都可以動,&符號作為引用聲明用,意即給變數(shù)取別名,但使用的是同一個位址,後者寫法是直接將值copy一份進入函數(shù)。
第8行: unsigned int id = glCreateShader(type); 產(chǎn)生並回傳一個空的shader object。傳入的type可以有:GL_COMPUTE_SHADER ,GL_VERTEX_SHADER , GL_TESS_CONTROL_SHADER ,GL_TESS_EVALUATION_SHADER , GL_GEOMETRY_SHADER ,GL_FRAGMENT_SHADER。
GLuint shader, //shader 物件
第15-36行: 用glGetShaderiv(id, GL_COMPILE_STATUS, &result); 抓取GL_COMPILE_STATUS狀態(tài),若FALSE則送出error資訊並刪除shader。就....CompileShader 編譯成功回傳GL_TRUE(=1) 反之GL_FALSE (=0) ,可以用GL_COMPILE_STATUS檢查。
第44、45行: 傳入Shader_type取得shader id。
備註:A program Object represents fully processed executable code。如果cout vs和fs會得到2和3。
void glDrawArrays( GLenum mode, //繪製的種類
GLint first, //first index
這裡是剛好是畫3個點。GLsizei count); //數(shù)量