?下面这个结构图太给力了.分成surfaceTexture和Opengl 两个部分
senario1: Camera采集:多filter+FBO
Camera通过surfaceTexture采集图片,经过3个filter处理,输出到shareContext SurfaceTexture.updateTexImage()将camera采集的图片传入opengl 纹理 第一个filter:camera filter 第一次filter:CameraInputFilter外部纹理getExternalOESTextureID转成本地2D纹理 第二个filter:打开fbo:mFilter添加背景滤镜.第二个filter开始,使用share context,mSharedTexture? 第三个filter:关闭fbo. mSimpleFilter 输出到shareContext?
??GLSL step: Java层opengl
public int onDrawToTexture(final int textureId) {
//0
GLES20.glUseProgram(mGLProgId);
//1
GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);
//2 打开fbo;绑定 FBO
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
//3
onPreDrawTask();
//4 CubeBuffer and TextureBuffer
mGLCubeBuffer.position(0);
GLES20.glVertexAttribPointer(mGLAttribPosition, 2, GLES20.GL_FLOAT, false, 0, mGLCubeBuffer);
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mGLAttribPosition);
mGLTextureBuffer.position(0);
// Prepare the <insert shape here> coordinate data
GLES20.glVertexAttribPointer(mGLAttribTextureCoordinate, 2, GLES20.GL_FLOAT, false, 0, mGLTextureBuffer);
GLES20.glEnableVertexAttribArray(mGLAttribTextureCoordinate);
//5 使用纹理
if (textureId != GlUtil.NO_TEXTURE) {
//1)调用 glActiveTexture()把活动的纹理单元设置为纹理单元0
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
//2) 调用 glBindTexture()把纹理绑定到纹理单元;GL_TEXTURE_EXTERNAL_OES
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
//3) 调用 glUniformli()把选定的纹理单元传递到片元着色器中的采样器上
GLES20.glUniform1i(mGLUniformTexture, 0);
}
//6 开始绘制;通过GLES20.glDrawArrays或者glDrawElements 开始绘制//opengl是画三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
//7 使用了glEnableVertexAttribArray方法就必须使用glDisableVertexAttribArray方法
GLES20.glDisableVertexAttribArray(mGLAttribPosition);
GLES20.glDisableVertexAttribArray(mGLAttribTextureCoordinate);
//8
onAfterDrawTask();
//9 关闭纹理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
}
onDrawFrame和onDrawToTexture区别是: onDrawFrame先执行GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);(最后一个参数为0),关闭fbo. 这样GLES画图直接画到屏幕上.
上层实现:onPreDrawTask();onAfterDrawTask();
Native 层opengl
/*填充片元的纹理和填充片元的颜色不同,纹理不会被直接绘制,它们要绑定到纹理单元,然后把这些纹理单元传递到着色器中。 通过在纹理单元中把纹理切来切去,我们还可以在场景中绘制不同的纹理,但是过分的切换可能使性能下降。 我们调整纹理来适应它们将要被绘制的形状,既可以通过调整纹理坐标,也可以通过拉伸或者压扁纹理本身来实现*/
1 程式相关方法 glUseProgram() 2 顶点着色器相关方法:glGetAttribLocation(),glEnableVertexAttribArray(),glVertexAttribPointer() 3 片元着色器相关方法:glGetUniformLocation(),glUniform4fv() 4 绘制相关方法 glDrawArrays-绘制方法 5 收尾相关方法glDisableVertexAttribArray()*/ //具体绘画 //和下面的OnDrawToTexture函数类似,这个是直接渲染,不是离屏渲染 //GL_TEXTURE_2D
?? ?/*创建VBO需要3个步骤: ?? ?使用glGenBuffers()生成新缓存对象。 ?? ?使用glBindBuffer()绑定缓存对象。 ?? ?使用glBufferData()将顶点数据拷贝到缓存对象中*/
int GPUImageFilter::OnDrawFrame(GLuint textureId)
{
//==1 ====使用GLSL程式 - Add program to OpenGL ES environment
glUseProgram(gl_prog_id_);
///**首先执行被挂起的任务**/
RunPendingOnDrawTasks();
//==2 ====顶点坐标=======顶点着色器相关方法====================
glBindBuffer(GL_ARRAY_BUFFER, gl_cube_buffer_);
//3 设置指针 (Set Pointers)----告诉OpenGL ES缓存中的数据类型和所有需要访问的数据的内存偏移*/
glVertexAttribPointer(gl_attrib_position_, 2, GL_FLOAT, false, 0, 0);
// 4 从cpu传数据到gpu,默认情况下,着色器无法读到这个数据,需要启用一个这个数据才能读取到
glEnableVertexAttribArray(gl_attrib_position_);
//========纹理坐标=========================
glBindBuffer(GL_ARRAY_BUFFER, gl_texture_buffer_);
// Prepare the <insert shape here> coordinate data
glVertexAttribPointer(gl_attrib_texture_, 2, GL_FLOAT, false, 0, 0);
// 启用vertex Enable a handle to the triangle vertices//使用一次glEnableVertexAttribArray方法就要使用一次glVertexAttribPointer方法
glEnableVertexAttribArray(gl_attrib_texture_);
//====5==使用纹理==============
if (textureId != OpenGLUtils::kNoTexture) {
//5.1 调用 glActiveTexture()把活动的纹理单元设置为纹理单元0
glActiveTexture(GL_TEXTURE0);
//5.2 调用 glBindTexture()把纹理绑定到纹理单元;如果是EXTERNAL,把摄像头纹理绑定到这激活的图层中
glBindTexture(GL_TEXTURE_2D, textureId);
//5.3 将纹理设置给Shader
glUniform1i(gl_uniform_texture_, 0);
}
//========6 绘制相关方法 glDrawArrays-绘制方法=================
OnDrawArraysPre();
// =======7 通过 GLES20.glDrawArrays 或者 GLES20.glDrawElements 开始绘制
//opengl画图都是三角形,GL_TRIANGLE_STRIP是一种模式。https://www.cnblogs.com/calence/p/7489947.html
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//========8==========
OnDrawArraysAfter();
//========9 使用了glEnableVertexAttribArray方法就必须使用glDisableVertexAttribArray方法
glDisableVertexAttribArray(gl_attrib_position_);
glDisableVertexAttribArray(gl_attrib_texture_);
//=========10=================
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return OpenGLUtils::kOnDrawn;
}
glViewport(0,0,512,512);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,1,&vertex_shader,NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragment_shader,NULL);
glCompileShader(fragmentShader);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glUseProgram(program);
GLuint aPositionLocation =glGetAttribLocation(program, "a_Position");
glVertexAttribPointer(aPositionLocation,2,GL_FLOAT,GL_FALSE,0,tableVerticesWithTriangles);
glEnableVertexAttribArray(aPositionLocation);
//draw something
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,6);
eglSwapBuffers(eglDisp,eglSurface);
?scenario2: 第三方glsl lib
|