android 相机预览中讲到了,我们使用的是:samplerExternalOES ,这个不能自由的变化预览的尺寸,还会出现卡顿现象,为了克服这个问题,也是采用网上的一些人的解决方案,既将samplerExternalOES 转化为 sampler2D,然后再进行渲染。
这里我们还是以相机预览为基础,这里我们最终将 texture不再渲染到屏幕,而是渲染到buffer中,因此我们在draw 之前,创建(为空时候创建,只创建一次) 绑定 fFrame和outTextureId,这样我们draw就不会渲染到屏幕了,而是渲染到创建的outTextureId。这样就完成了samplerExternalOES 转化为 sampler2D
//创建
if(fFrame[0] ==0)
GLES20.glGenFramebuffers(1, fFrame, 0);
if(outTextureId[0] ==0)
EasyGlUtils.genTexturesWithParameter(1, outTextureId,0,GLES20.GL_RGBA,width,height);
//绑定
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferId);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, textureId, 0);
public static void genTexturesWithParameter(int size,int[] textures,int start,
int gl_format,int width,int height){
GLES20.glGenTextures(size, textures, start);
for (int i = 0; i < size; i++) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[i]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0,gl_format, width, height,
0, gl_format, GLES20.GL_UNSIGNED_BYTE, null);
useTexParameter();
}
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,0);
}
那么我们接下来要怎么显示outTexture呢,这里我们需要新的着色器(用sampler2D),例如最简单的着色器:
//#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 textureCoordinate;
uniform sampler2D vTexture;
//uniform samplerExternalOES vTexture;
void main()
{
gl_FragColor = texture2D( vTexture, textureCoordinate );
}
然后setTexute(outTexture),draw出来就好了。有时候为了添加多个filter,因此 写了一个groupFitler 这里可以 添加多个filter,并且只需要额外的创建2个 texture2d。
public class GroupFilter {
private ArrayList<LyFilter> lyFilters = new ArrayList<>();
private CameraFilter cameraFilter;
public GroupFilter(CameraFilter cameraFilter){
this.cameraFilter = cameraFilter;
width = cameraFilter.getWidth();
height = cameraFilter.getHeight();
createFrameBuffer();
}
public void addFilter(LyFilter lyFilter){
lyFilters.add(lyFilter);
}
private int textureIndex=0;
public void draw(){
cameraFilter.draw();
textureIndex=0;
for(LyFilter filter:lyFilters){
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fFrame[0]);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, fTexture[textureIndex%2], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, fRender[0]);
if(textureIndex ==0){
filter.setTextureId(cameraFilter.getOutTextureId());
}else{
filter.setTextureId(fTexture[(textureIndex - 1)%2]);
}
filter.draw();
unBindFrame();
textureIndex++;
}
}
public int getOutputTexture() {
if (lyFilters.size() == 0) {
return cameraFilter.getOutTextureId();
} else {
return fTexture[(textureIndex - 1) % 2];
}
}
public void onSizeChanged(int width, int height) {
this.width=width;
this.height=height;
cameraFilter.onSizeChanged(width , height);
createFrameBuffer();
}
//创建离屏buffer
private int fTextureSize = 2;
private int[] fFrame = new int[1];
private int[] fRender = new int[1];
private int[] fTexture = new int[fTextureSize];
private int width , height;
//创建FrameBuffer
private boolean createFrameBuffer() {
GLES20.glGenFramebuffers(1, fFrame, 0);
GLES20.glGenRenderbuffers(1, fRender, 0);
genTextures();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fFrame[0]);
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, fRender[0]);
GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, width,
height);
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, fTexture[0], 0);
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
GLES20.GL_RENDERBUFFER, fRender[0]);
// int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
// if(status==GLES20.GL_FRAMEBUFFER_COMPLETE){
// return true;
// }
unBindFrame();
return false;
}
//生成Textures
private void genTextures() {
GLES20.glGenTextures(fTextureSize, fTexture, 0);
for (int i = 0; i < fTextureSize; i++) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, fTexture[i]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height,
0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
}
}
//取消绑定Texture
private void unBindFrame() {
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
}
private void deleteFrameBuffer() {
GLES20.glDeleteRenderbuffers(1, fRender, 0);
GLES20.glDeleteFramebuffers(1, fFrame, 0);
GLES20.glDeleteTextures(1, fTexture, 0);
}
}
完整的demo欢迎各位老铁下载