美文网首页iOS开发笔记
OpenGLES入门(二)创建program

OpenGLES入门(二)创建program

作者: 武小寺 | 来源:发表于2016-06-12 16:02 被阅读1824次

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,表示使用固定功能管线。如果程序已经在使用的时候,对程序进行重新编译,编译后的应用程序会自动替代以前的那个被调用,这时你不需要再次调用这个函数。

相关文章

网友评论

    本文标题:OpenGLES入门(二)创建program

    本文链接:https://www.haomeiwen.com/subject/bziedttx.html