
一、顶点着色器
顶点着色器输入包括:
- 着色器程序-描述顶点上执行操作的顶点着色器程序源代码或者可执行文件。
- 顶点着色器输入(或者属性)-用顶点数组提供的每个顶点的数据。
- 统一变量(Uniform)-顶点(或者片段)着色器使用的不变数据。
- 采样器-代表顶点着色器使用纹理的特殊统一变量类型。
内建变量:
gl_color、gl_PointSize
输出数据申明为out即输出变量。
示例YUV420P顶点着色器:
//版本信息
#version 300 es
//精度限定符
precision mediump float;
//变换矩阵
uniform mat4 uMVPMatrix;
//顶点坐标
layout(location=1)in vec4 vPosition;
//纹理坐标
layout(location=2)in vec2 a_texCoord;
//输出变量
out vec2 tc;
void main() {
gl_Position=vPosition*uMVPMatrix;
tc=a_texCoord;
}
几个uMVPMatrix坐标:
//TODO待补充
二、图元装配
图元是三角形、直线、点精灵等几何对象。图元的顶点被发送到顶点着色器的不同拷贝。在图元装备期间这些顶点被组合成图元。对于每个图元,必须确定是否在视锥体之内,不在则裁剪,裁剪之后,顶点位置被转换为屏幕坐标,也可以进行一次淘汰。经过裁剪、淘汰之后传递下一管线。
三、光栅化
此阶段绘制图元。光栅化是将图元转化为一组二维片段的过程,然后这些片段由片段着色器处理。这些二维片段代表着可在屏幕上绘制的像素。

四、片段着色器
片段着色器输入:
- 着色器程序-描述片段上所执行操作的片段着色器程序源代码或者可执行文件。
- 输入变量-光栅化单元用插值为每个片段生成的顶点着色器输出。
- 统一变量-片段(或者顶点)着色器使用的不变数据。
- 采样器-代表片段着色器所用的纹理的特殊统一变量类型。
片段着色器输出:
可以一个或多个颜色,根据渲染目标而定。
示例yuv420P片段着色器:
#version 300 es
precision mediump float;
uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;
in vec2 tc;
layout(location=0) out vec4 fragColor;
void main() {
// vec3 yuv;
// vec3 rgb;
// yuv.r=texture(tex_y, tc);
// yuv.r=texture(tex_u, tc);
// yuv.r=texture(tex_v, tc);
// rgb=mat3(1.0, 1.0, 1.0,
// 0.0, -0.39465, 2.03211,
// 1.13983, -0.58060, 0.0
// )*yuv;
// fragColor=(rgb, 1.0);
vec4 c = vec4((texture(tex_y, tc).r - 16./255.) * 1.164);
vec4 U = vec4(texture(tex_u, tc).r - 128./255.);
vec4 V = vec4(texture(tex_v, tc).r - 128./255.);
c += V * vec4(1.596, -0.813, 0, 0);
c += U * vec4(0, -0.392, 2.017, 0);
c.a = 1.0;
fragColor=c;
}
五、OpenGL ES 渲染YUV420P代码示例
//
// Created by 86132 on 2019/7/27.
//
#include <malloc.h>
#include <cstdlib>
#include "OpenGl.h"
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <memory.h>
//GL_NO_ERROR :(0)当前无错误值
//GL_INVALID_ENUM :(1280)仅当使用非法枚举参数时,如果使用该参数有指定环境,则返回 GL_INVALID_OPERATION
//GL_INVALID_VALUE :(1281)仅当使用非法值参数时,如果使用该参数有指定环境,则返回 GL_INVALID_OPERATION
//GL_INVALID_OPERATION :(1282)命令的状态集合对于指定的参数非法。
//GL_STACK_OVERFLOW :(1283)压栈操作超出堆栈大小。
//GL_STACK_UNDERFLOW :(1284)出栈操作达到堆栈底部。
//GL_OUT_OF_MEMORY :(1285)不能分配足够内存时。
//GL_INVALID_FRAMEBUFFER_OPERATION :(1286)当操作未准备好的真缓存时。
//GL_CONTEXT_LOST :(1287)由于显卡重置导致 OpenGL context 丢失。
bool OpenGl::initialEgl(JNIEnv *env, jobject surface, jobject jAssetManager) {
/**********************************经过以下步骤,搭建EGL和OPENGL环境**************************************/
//1、创建EGLDisplay对象
eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (eglDisplay == EGL_NO_DISPLAY) {
__android_log_print(ANDROID_LOG_ERROR, "opengl", "eglGetDisplay return error %d",
eglGetError());
return false;
};
//2、初始化显示设备 后面两个参数是EGL版本
if (!eglInitialize(eglDisplay, 0, 0)) {
LOG_I("eglInitialize return error %d",
eglGetError());