OpenGLES入門(二)創建program

iOS代碼

/*
 * 
 * VertexShader-用于渲染形狀的頂點的OpenGLES 圖形代碼。
 * FragmentShader-用于渲染形狀的外觀(顏色或紋理)的OpenGLES 代碼。
 * Program-一個OpenGLES對象,包含了你想要用來繪制一個或多個形狀的shader。
 *
 */
// 創建program
+ (GLuint)createAndLinkProgramWith:(GLuint)vsHandle fsHandle:(GLuint)fsHandle attrs:(NSArray*)attrs {
    //創建一個空的OpenGL ES Program
    GLuint programHandle = glCreateProgram();
    if (programHandle != 0) {
         // 將vertex shader添加到program
        glAttachShader(programHandle, vsHandle);
        // 將fragment shader添加到program
        glAttachShader(programHandle, fsHandle);
        
        if (attrs != nil) {
            for (int i = 0; i < attrs.count; i++) {
                //把program的頂點屬性索引與頂點shader中的變量名進行綁定
                glBindAttribLocation(programHandle, i, [[attrs objectAtIndex:i] UTF8String]);
            }
        }
        GLint status;
         // 創建可執行的 OpenGL ES program
        glLinkProgram(programHandle);
        // glValidateProgram(programHandle);
        // 獲取program對象的參數值
        glGetProgramiv(programHandle, GL_LINK_STATUS, &status);
        if (status == GL_FALSE){
            if (vsHandle) glDeleteShader(vsHandle);
            if (fsHandle) glDeleteShader(fsHandle);
            programHandle = 0;
        }
    }
    assert(programHandle != 0);
    
    return programHandle;
}

安卓代碼

private int createProgram(String vertexSource, String fragmentSource) 
{
  // 加載頂點著色器
  int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
  if (vertexShader == 0) 
  {
    return 0;
  }
  
  // 加載片元著色器
  int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
  if (pixelShader == 0) 
  {
    return 0;
  }

  // 創建著色器程序
  int program = GLES20.glCreateProgram();
  // 若程序創建成功則向程序中加入頂點著色器與片元著色器
  if (program != 0) 
  {
    // 向程序中加入頂點著色器
    GLES20.glAttachShader(program, vertexShader);
    // 向程序中加入片元著色器
    GLES20.glAttachShader(program, pixelShader);
    // 鏈接程序
    GLES20.glLinkProgram(program);
    // 存放鏈接成功program數量的數組
    int[] linkStatus = new int[1];
    // 獲取program的鏈接情況
    GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
    // 若鏈接失敗則報錯并刪除程序
    if (linkStatus[0] != GLES20.GL_TRUE) 
    {
      Log.e(TAG, "Could not link program: ");
      Log.e(TAG, GLES20.glGetProgramInfoLog(program));
      GLES20.glDeleteProgram(program);
      program = 0;
    }
  }

  // 釋放shader資源
  GLES20.glDeleteShader(vertexShader );
  GLES20.glDeleteShader(pixelShader);

  return program;
}

1. glCreateProgram

在連接shader之前,首先要創建一個容納程序的容器,稱為著色器程序容器。可以通過glCreateProgram函數來創建一個程序容器。

函數原型:
int glCreateProgram ()
如果函數調用成功將返回一個正整數作為該著色器程序的id。

2.glAttachShader

接下來,我們要將shader容器添加到程序中。這時的shader容器不一定需要被編譯,他們甚至不需要包含任何的代碼。我們要做的只是將shader容器添加到程序中。使用glAttachShader函數來為程序添加shader容器。

函數原型:
void glAttachShader (int program, int shader)
參數含義:
program是著色器程序容器的id;
shader是要添加的頂點或者片元shader容器的id。

3. glLinkProgram

鏈接程序。

函數原型:
void glLinkProgram (int program)
參數含義:
program是著色器程序容器的id。

在鏈接操作執行以后,可以任意修改shader的源代碼,對shader重新編譯不會影響整個程序,除非重新鏈接程序。

4.glUseProgram

加載并使用鏈接好的程序。

函數原型:
void glUseProgram (int program)
參數含義:
program是要使用的著色器程序的id。

如果將program設置為0,表示使用固定功能管線。如果程序已經在使用的時候,對程序進行重新編譯,編譯后的應用程序會自動替代以前的那個被調用,這時你不需要再次調用這個函數。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,287評論 25 708
  • 你好,三角形 圖形渲染管線(Pipeline) 3D坐標轉為2D坐標的處理過程是由OpenGL的圖形渲染管線(Pi...
    IceMJ閱讀 7,489評論 2 13
  • 我是實驗小學五年級五班黃怡,在老師辛勤的教導和培養下,我努力學習,尊敬老師,團結同學。 這次我參加大隊委競選,是希...
    鄔達秀閱讀 340評論 0 0
  • 三百年前魂夢托,霜花墨月流年措。 當年入山塵緣斷,空留紅顏淚婆娑。
    墨月霜花閱讀 594評論 0 0