Modern OpenGL ES: ndk編程——畫一個三角形之Shader工程

OpenGL ES2.0以後,想畫一個東西必須使用 shader來完成。  而使用shader需要創建shader工程。使用shader來畫一個東西的大體步驟如下:
1 創建和編譯shader 
2 創建和鏈接shader工程
3 爲shader工程設置 uniform 和 attrubte變量
4 Shader編譯 並鏈接到工程,成最終的可執行文件


Vertex Shader 和 Fragment Shader
OpenGL 有很多種Shader對象,但我們需要經常使用的只有兩種,一種是 光柵化之前的Vertex Shader ,一種是光柵化之後的Fragment Shader
光柵化,就是將OpenGL中定義的 物體的頂點映射到屏幕像素的過程。

光柵化之前,我們需要定義所畫物體的頂點,頂點包括 位置,顏色等屬性, 通過這些屬性能實現物體的不同方向和位置,以及不同的表像、光照,這些都是通過 Vertex Shader來完成的

光柵化之後,我們需要將所畫物體映射爲屏幕的像素,最終現實出來圖像,這一步我們可以決定現實 圖像的哪一部分,如果兩個圖像疊加在一起,那麼它們的混合模式是怎樣的? 這些都是通過 Fragment Shader完成的


創建和編譯Shader對象
 1 創建Shader
     GLuint glCreateShader(GLenum type)
       參數: 要創建的shader類型,如GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
       返回: 返回這個Shader對象的句柄
       功能: 獲得了該shader的句柄後,我們就可以進一步對它操作了,如送入shader source, 編譯shader, 刪除shader。

 2 刪除Shader
    void glDeleteShader(GLuint shader)
     參數: 刪除的shader句柄
     注意: 如果該shader已經依附了一個shader工程,那麼調用該函數並不能立即刪除shader對象,知道該對象不再使用
  
 3 提供shader源碼
   void glShaderSource(GLuint shader,  GLsizei count,  const GLchar* const *string,  const  GLint *length)

   參數: 
       shader:
        count:  shader 源碼字串的個數。  一個完整的shader 源碼可能會有很多個字符串組成
        const GLchar* const *string: 指向一組shader源碼字符串
        length: shader源碼的字數,如果NULL,就是字符串到NULL時結束

4 編譯源碼
   shader對象,一旦被賦值了字符串
   void glCompileShader(GLuint shader)
   
5 獲取shader信息
   void  glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
  參數:
    shader: 
     pname: 要獲取信息的類型:
      GL_COMPILE_STATUS
      GL_DELETE_STATUS
      GL_INFO_LOG_LEGTH
      GL_SHADER_SOURCE_LENGTH
      GL_SHADER_TYPE
   params:
     用一個 整數來代表結果
  
  GL_COMPILE_STATUS 表示要查詢編譯信息, params如果是 GL_TRUE, 表示編譯成功, 反之,失敗

6  獲取shader日誌信息
    如果第5步獲取的信息失敗, 會將錯誤信息寫的日誌裏,通過以下函數獲取
    void glGetSahderInfoLog(GLuint shader,  GLsizei maxLength, GLsizei *length, GLchar *infoLog)
    參數:
      shader : 
      maxLength: 需要存儲 info log的buffer大小
      length: 需要寫進info的長度。 如果不知道長度,可以是NULL
     infoLog: 指向log字符串的buffer。

創建和鏈接工程:
   繼創建完shader對象之後,我們需要創建shader工程了。 shader工程更像是 一個 容納了shader對象的容器,假如shader好比.obj的話,那麼shader工程還具有將它們按照 管線流程,將這些.obj編譯鏈接成一個 .o文件。

 1 創建 shader工程
    GLuint glCreateProgram()
    如創建shader對象一樣, 創建了一個program的句柄
2  刪除shader工程
    void glDeleteProgram(GLuint program)

3  需要將shader對象添加到 shader program這個容器中
   void glAttachShader(GLuint program, GLuint shader)
4 Link完,或者Link失敗,都需要刪除shader工程裏的shader對象
   void glDetachShader(GLuint program, GLuint shader)
5 鏈接這些shader對象
  void glLinkProgram(GLuint program)
 Link的目的是要將這些shader對象 變爲一個GPU能執行的可執行文件

6  與獲取shader信息一樣,也可以獲取shader工程信息
    void glGetProgramiv(GLuint program, GLenum pname, GLint *params)
     參數:
       program:
       pname: 
          GL_ACTIVE_ATTRIBUTES  // 激活的(使用的)attribute變量的個數
          GL_ACTIVE_ATTRIBUTE_MAX_LENGTH //attribute名字的最大長度  
          GL_ACTIVE_UNIFORM_BLOCK
          GL_ACTIVE_UNIFORM_BLOCK_MAX_LENGTH
          GL_ACTIVE_UNIFORMS
          GL_ACTIVE_UNIFORM_MAX_LENGTH
          GL_ATTACHED_SHADERS  // 依附的 shader數
          GL_DELETE_STATUS
          GL_INFO_LOG_LENGTH  
          GL_LINK_STATUS   // 檢測鏈接是否成功
         GL_PROGRAM_BINARY_RETERIEVABLE_HINT
         GL_TRANSFORM_FEEDBACK_BUFFER_MODE   
         GL_TRANSFORM_FEEDBACK_VARYINGS  //在feedback 階段輸出的變量數
         GL_TRANSFORM_FEEDBACK_VARING_MAX_LENGTH
         GL_VALIDATE_STATUS


  7 獲取shader工程日誌
    void glGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizel *length, GLchar *infoLog)
    參數:
    program:
    maxLength: 存儲的最大buffer大小
    length:   需要寫入的字符長度,如果不知道天下null
    infoLog: 字符串

 8  一旦創建好, 我們就可以渲染該shader工程了。 這之前,還需要確定shader工程是否有效
     void glValidateProgram(GLuint program)

 9 使用shader工程
   void glUseProgram(GLuint program)
 

   


     
    
       
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章