您的位置:首页 > 编程语言

Modern OpenGL ES: ndk编程——画一个三角形之Shader工程

2015-11-02 21:14 495 查看
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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: