OpenGL ES2 學習教程5——頂點屬性

頂點屬性聲明

一個屬性能夠聲明在一個頂點着色器,但若是它不使用,那麼它是不被激活的。你能使用glGetActiveAttrib查詢一個被激活的屬性內容。GL_ACTIVE_ATTRIBUTESgit

void glGetActiveAttrib( GLuint program, GLuint index, GLsizei bufsize,
                        GLsizei *length, GLint *size, GLenum *type, GLchar *name)

bufsize是那些能被寫爲屬性名的字符的最大數目,包括空('\0')。length是返回的名字長度,type是數據的類型GL_FLOAT等。size是返回的屬性大小,是返回type的單位大小,若是是數組就是數組的尺寸,不是數組就是1。name是着色器聲明的屬性變量的名字。github

頂點着色器中使用glBindAttribLocation綁定一個普通的頂點屬性索引到屬性變量,這個綁定在項目下次連接時有效,在當前連接的項目裏不會改變。若是一個名字前面被綁定過,它分配的綁定被一個索引取代。glBindAttribLocation甚至能在頂點着色器被鏈接到一個項目對象前使用。這意味着這個調用能被使用去綁定任何屬性名字。屬性名字不存在或者沒激活的綁定在項目裏被忽略。segmentfault

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)

另外一種選擇是讓GLES綁定屬性變量名到一個普通的屬性索引。在連接階段GLES2爲每一個屬性變量執行下面的步驟:檢查每一個屬性變量是否已經過glBindAttribLocation綁定。若是已綁定,指定的屬性索引將被使用;若是沒有,編譯工具將產生一個通常的頂點屬性索引。而這個分配依賴工具的不一樣而不一樣,咱們可使用glGetAttribLocation去獲取這個分配的值。api

GLint glGetAttribLocation(GLuint program, const GLchar *name)

指定頂點屬性數據:

  • 指定頂點屬性常量數組

void glVertexAttrib1f(GLuint index, GLfloat x);
void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z,
GLfloat w);
void glVertexAttrib1fv(GLuint index, const GLfloat *values);
void glVertexAttrib2fv(GLuint index, const GLfloat *values);
void glVertexAttrib3fv(GLuint index, const GLfloat *values);
void glVertexAttrib4fv(GLuint index, const GLfloat *values);

index是要裝載的頂點屬性索引,x y z values是要填充的值。glVertexAttrib?f和glVertexAttrib?fv都是裝載一個vec4的值。介紹Shader語言時說過它們都會存儲爲具備4個份量的存儲單元。填充時最後一個會爲1.0,中間不足的爲0.0。如glVertexAttrib1fv填充1,那麼index最終的值爲{x,0.0,0.0,1.0}。注意到GLES2只支持了浮點型的設置屬性常量api。less

  • 頂點數組ide

void glVertexAttribPointer( GLuint index, GLint size, GLenum type,
                            GLboolean normalized,
                            GLsizei stride,
                            const void *ptr)

要裝在數組到頂點屬性,使用glVertexAttribPointer,index是頂點屬性的索引,size是數組裏組成元素的大小(例如只是指定二維的位置那麼只須要x,y那麼賦值爲2),type是數據格式,normalized用於指定非浮點數據格式轉變成浮點型數據時是否標準化,strides是頂點屬性數據的存儲間隔,0表示無間隔,連續存儲的。ptr就是咱們要放進去的數據了。正如第二節例子裏的:工具

// _vPositionHandle的值就來自於glGetAttribLocation獲取獲得的索引
glVertexAttribPointer(_vPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);

出了加載數據,咱們還要爲屬性啓用屬性數組。oop

// 啓用
void glEnableVertexAttribArray(GLuint index);
// 不啓用
void glDisableVertexAttribArray(GLuint index);
// index就是前面的屬性索引值

栗子

接着之前的項目,這裏咱們主要修改Director裏的內容:代碼看裏面的lesson5的tagui

想聲明着色器和全局數據

// 頂點着色器,聲明倆個着色器屬性,分別放位置和顏色,易變變量做爲輸出將傳給片斷着色器
static const char gVertexShader[] =
    "attribute vec4 a_position;\n"
    "attribute vec4 a_color;\n"
    "varying vec4 v_color;\n"
    "void main()\n"
    "{\n"
    "  v_color = a_color;\n"
    "  gl_Position = a_position;\n" 
    "}\n";
// 片斷着色器,接收顏v_color傳來的顏色
static const char gFragmentShader[] =
    "varying vec4 v_color;\n"
    "void main()\n"
    "{\n"
    "  gl_FragColor = v_color;\n"
    "}\n";
// 和之前的同樣的三角形數據
const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f,
                                     -0.5f, 0.5f, -0.5f };
// 接下來用給a_color的
const GLfloat gColor[4] = { 1.0f, 1.0f, 0.0f, 1.0f };

在mainloop循環中修改

void Director::mainLoop()
{
    static float grey;
    grey += 0.01f;
    if (grey > 1.0f) {
        grey = 0.0f;
    }
    glClearColor(grey, grey, grey, 1.0f);
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    glVertexAttrib4fv(0, gColor);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); 
    glEnableVertexAttribArray(1);
    glBindAttribLocation(_glProgram->getProgramHandle(), 0, "a_color"); 
    glBindAttribLocation(_glProgram->getProgramHandle(), 1, "a_position");
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

查看效果,能夠看到咱們設置的黃色三角形:

clipboard.png

相關文章
相關標籤/搜索