目录
概述
在本节中,我们提供创建 Shader
对象,并且编译链接到一个程序对象的完整流程,主要内容如下:
Shader
和程序对象概述- 创建和编译
Shader
- 创建和链接程序对象
- 设置和获取统一变量
- 获取和设置属性
Shader
编译器和程序二进制代码
想要用 Shader
进行渲染,必须创建两个基本的对象:Shader
对象和程序对象(program object
);它们之间的关系类似于C语言链接程序和编译器
- C语言对象将一段源代码生成目标对象
- C链接程序将对象文件链接为最后的文件
Shader
对象是包含多个 Shader
的对象,源代码提供给 Shader
对象,Shader
对象被编译为一个目标形式(类似于 obj
文件),编译之后,Shader
对象可以连接到一个程序对象,一个程序对象可以连接多个 Shader 对象 ,在 OpenGL-ES
中,每个程序对象必须连接到一个 Vertex Shader
对象和 Fragment Shader.
之后使用 Shader
进行渲染,步骤如下:
创建和编译Shader
创建和编译Shader使用的 API如下:
glCreateShader (GLenum type)
glDeleteShader(GLuint shader)
说明:创建/删除 VertexShader
or FragmentShader
,返回新 Shader
的 handle
glShaderSource (GLuint shader, GLsizei count, const GLchar const string, const GLint *length)
说明:指定 Shader
的 src_code
源代码
glCompileShader (GLuint shader)
说明:编译 Shader
glGetShaderiv (GLuint shader,GLenum pname,GLint * params)
说明:检查 Shader
是否编译成功
glGetShaderInfoLog (GLuint shader,GLsizei maxLength,GLsizei *length,GLchar *infoLog)
说明:获取编译 Shader
的 log
信息
链接程序对象
链接程序对象使用的 API 如下:
API | 说明 |
---|---|
glCreateProgram() | 创建程序对象 |
glDeleteProgram() | 删除程序对象 |
glAttachShader() | Shader 对象连接到程序对象 |
glDetachShader() | Shader 对象从程序对象分离 |
glLinkPrigram() | 链接程序对象 |
glGetProgramiv | 查询Shader 链接信息 |
glGetProgramInfoLog | 获取程序信息日志 |
绘制一个最简单的三角形
绘制一个基本三角形,示例输入顶点坐标和颜色坐标如下:
c
//R G B A
GLfloat color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
// 3 vertices, with (x,y,z) per-vertex
GLfloat vertexPos[3 * 3] = {
1.0f, 0.0f, 0.0f, // v0
0.0f, 1.0f, 0.0f, // v1
0.0f, 0.0f, 1.0f // v2
};
vertexPos
数组表示的是三个顶点的三维坐标,OpenGL-ES
中使用的坐标系如下图所示:

示例代码
c
#include "esUtil.h"
typedef struct
{
GLuint programObject;
} UserData;
static int Init(ESContext *esContext)
{
UserData *userData = esContext->userData;
const char vShaderStr[] =
"#version 300 es \n"
"layout(location = 0) in vec4 a_position; \n"
"layout(location = 1) in vec4 a_color; \n"
"out vec4 v_color; \n"
"void main() \n"
"{ \n"
" v_color = a_color; \n"
" gl_Position = a_position; \n"
"}";
const char fShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"in vec4 v_color; \n"
"out vec4 o_fragColor; \n"
"void main() \n"
"{ \n"
" o_fragColor = v_color; \n"
"}";
GLuint programObject;
// Create the program object
programObject = esLoadProgram(vShaderStr, fShaderStr);
if (programObject == 0) {
return GL_FALSE;
}
// Store the program object
userData->programObject = programObject;
// R G B A
glClearColor(1.0f, 1.0f, 1.0f, 0.5f);
return GL_TRUE;
}
static void Shutdown(ESContext *esContext)
{
UserData *userData = esContext->userData;
glDeleteProgram(userData->programObject);
}
static void Draw(ESContext *esContext)
{
UserData *userData = esContext->userData;
//R G B A
GLfloat color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
// 3 vertices, with (x,y,z) per-vertex
GLfloat vertexPos[3 * 3] =
{
1.0f, 0.0f, 0.0f, // v0
0.0f, 1.0f, 0.0f, // v1
0.0f, 0.0f, 1.0f // v2
};
glViewport(0, 0, esContext->width, esContext->height);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(userData->programObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexPos);
glEnableVertexAttribArray(0);
glVertexAttrib4fv(1, color);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}