isCreate = true; }
@Override public void onChange(int width, int height) { if (isChange) { return; } onChangePre(); setWidth(width); setHeight(height); onViewport(); onInitFbo(); onChangeAfter(); isChange = true; }
@Override public void onDraw(int textureId) { if (!onReadyToDraw()) { return; } onDrawPre(); onClear(); onUseProgram(); onInitLocation(); onBindFbo(); onBindVbo(); onActiveTexture(textureId); onEnableVertexAttributeArray(); onSetVertexData(); onSetCoordinateData(); onSetOtherData(); onDraw(); onDisableVertexAttributeArray(); onUnBind(); onDrawAfter(); }
@Override public void onRelease() { onDeleteProgram(program); onDeleteShader(vertexShader); onDeleteShader(fragShader); onDeleteTexture(textureId); onDeleteTexture(fboTextureId); onDeleteFbo(fboId); onDeleteVbo(vboId); }
/**
- 创建之前
*/ public void onCreatePre() {
}
/**
- 设置背景颜色
*/ public void onClearColor() { GLES20.glClearColor(0, 0, 0, 1); }
/**
- 是否启用混色
*/ public boolean onEnableBlend() { return false; }
/**
- 初始化混色
*/ private void onInitBlend() { if (!onEnableBlend()) { return; } GLES20.glEnable(GLES20.GL_BLEND); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); }
/**
- 初始化顶点坐标
*/ public void onInitVertexBuffer() { vertexBuffer = OpenGLESUtils.getSquareVertexBuffer(); }
/**
- 初始化纹理坐标
*/ public void onInitCoordinateBuffer() { if (isBindFbo) { coordinateBuffer = OpenGLESUtils.getSquareCoordinateReverseBuffer(); } else { coordinateBuffer = OpenGLESUtils.getSquareCoordinateBuffer(); } }
/**
- 初始化Vbo
*/ public void onInitVbo() { vboId = OpenGLESUtils.getVbo(vertexBuffer, coordinateBuffer); }
/**
- 初始化Program
*/ public void onInitProgram() { String vertexShaderCode = OpenGLESUtils.getShaderCode(context, vertexFilename); String fragShaderCode = OpenGLESUtils.getShaderCode(context, fragFilename);
vertexShader = OpenGLESUtils.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); fragShader = OpenGLESUtils.loadShader(GLES20.GL_FRAGMENT_SHADER, fragShaderCode);
program = OpenGLESUtils.linkProgram(vertexShader, fragShader); }
/**
- 创建之后
*/ public void onCreateAfter() {
}
/**
- 设置尺寸之前
*/ public void onChangePre() {
}
/**
- 设置窗口尺寸
*/ public void onViewport() { GLES20.glViewport(0, 0, width, height); }
/**
- 初始化Fbo
*/ public void onInitFbo() { if (!isBindFbo) { return; } int[] fboData = OpenGLESUtils.getFbo(width, height); fboId = fboData[0]; fboTextureId = fboData[1]; }
/**
- 设置尺寸之后
*/ public void onChangeAfter() {
}
/**
- 绘制之前的准备
*/ public boolean onReadyToDraw() { return true; }
/**
- 绘制之前
*/ public void onDrawPre() {
}
/**
- 清屏
*/ public void onClear() { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); }
/**
- 使用Program
*/ public void onUseProgram() { GLES20.glUseProgram(program); }
/**
- 初始化着色器各个位置
*/ public void onInitLocation() { aPosLocation = GLES20.glGetAttribLocation(program, “aPos”); aCoordinateLocation = GLES20.glGetAttribLocation(program, “aCoordinate”); uSamplerLocation = GLES20.glGetUniformLocation(program, “uSampler”); }
/**
- 绑定Fbo
*/ public void onBindFbo() { if (!isBindFbo) { return; } GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboId); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, fboTextureId, 0); GLES20.glViewport(0, 0, width, height); }
/**
- 绑定Vbo
*/ public void onBindVbo() { GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vboId); }
/**
- 激活并绑定纹理
*/ public void onActiveTexture(int textureId) { this.textureId = textureId; GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); GLES20.glUniform1i(uSamplerLocation, 0); }
/**
- 启用顶点坐标
*/ public void onEnableVertexAttributeArray() { GLES20.glEnableVertexAttribArray(aPosLocation); GLES20.glEnableVertexAttribArray(aCoordinateLocation); }
/**
- 设置顶点坐标
*/ public void onSetVertexData() { GLES20.glVertexAttribPointer(aPosLocation, vertexSize, GLES20.GL_FLOAT, false, vertexStride, 0); }
/**
- 设置纹理坐标
*/ public void onSetCoordinateData() { GLES20.glVertexAttribPointer(aCoordinateLocation, coordinateSize, GLES20.GL_FLOAT, false, coordinateStride, vertexBuffer.limit() * 4); }
/**
- 设置其他数据
*/ public void onSetOtherData() {
}
/**
- 绘制
*/ public void onDraw() { GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount); }
/**
- 禁用顶点坐标
*/ public void onDisableVertexAttributeArray() { GLES20.glDisableVertexAttribArray(aPosLocation); GLES20.glDisableVertexAttribArray(aCoordinateLocation); }
/**
- 解除绑定
*/ public void onUnBind() { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); }
/**
- 绘制之后
*/ public void onDrawAfter() {
}
/**
- 删除Program
*/ public void onDeleteProgram(int program) { GLES20.glDeleteProgram(program); }
/**
- 删除Shader
*/ public void onDeleteShader(int shader) { GLES20.glDeleteShader(shader); }
/**
- 删除纹理
*/ public void onDeleteTexture(int textureId) { GLES20.glDeleteTextures(1, new int[]{textureId}, 0); }
/**
- 删除Fbo
*/ public void onDeleteFbo(int fboId) { GLES20.glDeleteFramebuffers(1, new int[]{fboId}, 0); }
/**
- 删除Vbo
*/ public void onDeleteVbo(int vboId) { GLES20.glDeleteBuffers(1, new int[]{vboId}, 0); }
public Context getContext() { return context; }
public void setContext(Context context) { this.context = context; }
public FloatBuffer getVertexBuffer() { return vertexBuffer; }
public void setVertexBuffer(FloatBuffer vertexBuffer) { this.vertexBuffer = vertexBuffer; }
public FloatBuffer getCoordinateBuffer() { return coordinateBuffer; }
public void setCoordinateBuffer(FloatBuffer coordinateBuffer) { this.coordinateBuffer = coordinateBuffer; }
public int getVertexSize() { return vertexSize; }
public void setVertexSize(int vertexSize) { this.vertexSize = vertexSize; }
public int getCoordinateSize() { return coordinateSize; }
public void setCoordinateSize(int coordinateSize) { this.coordinateSize = coordinateSize; }
public int getVertexStride() { return vertexStride; }
public void setVertexStride(int vertexStride) { this.vertexStride = vertexStride; }
public int getCoordinateStride() { return coordinateStride; }
public void setCoordinateStride(int coordinateStride) { this.coordinateStride = coordinateStride; }
public int getVertexCount() { return vertexCount; }
public void setVertexCount(int vertexCount) { this.vertexCount = vertexCount; }
public int getCoordinateCount() { return coordinateCount; }
public void setCoordinateCount(int coordinateCount) { this.coordinateCount = coordinateCount; }
public int getProgram() { return program; }
public void setProgram(int program) { this.program = program; }
public int getFboTextureId() { return fboTextureId; }
public void setFboTextureId(int fboTextureId) { this.fboTextureId = fboTextureId; }
public int getFboId() { return fboId; }
public void setFboId(int fboId) { this.fboId = fboId; }
public int getVboId() { return vboId; }
public void setVboId(int vboId) { this.vboId = vboId; }
public String getVertexFilename() { return vertexFilename; }
public void setVertexFilename(String vertexFilename) { this.vertexFilename = vertexFilename; }
public String getFragFilename() { return fragFilename; }
public void setFragFilename(String fragFilename) { this.fragFilename = fragFilename; }
public int getWidth() { return width; }
public void setWidth(int width) { this.width = width; }
public int getHeight() { return height; }
public void setHeight(int height) { this.height = height; }
public boolean isBindFbo() { return isBindFbo; }
public void setBindFbo(boolean bindFbo) { isBindFbo = bindFbo; }
public int getPosLocation() { return aPosLocation; }
public void setPosLocation(int aPosLocation) { this.aPosLocation = aPosLocation; }
public int getCoordinateLocation() { return aCoordinateLocation; }
public void setCoordinateLocation(int aCoordinateLocation) { this.aCoordinateLocation = aCoordinateLocation; }
public int getSamplerLocation() { return uSamplerLocation; }
public void setSamplerLocation(int uSamplerLocation) { this.uSamplerLocation = uSamplerLocation; }
public boolean isCreate() { return isCreate; }
public void setCreate(boolean create) { isCreate = create; }
public boolean isChange() { return isChange; }
public void setChange(boolean change) { isChange = change; }
public BaseRenderBean getRenderBean() { return renderBean; }
public void setRenderBean(BaseRenderBean renderBean) { this.renderBean = renderBean; }
public void updateRenderBean(BaseRenderBean renderBean) { setRenderBean(renderBean); } }
代码有点长,但是里面尽可能地考虑到了渲染和扩展的需求
顶点着色器 vertex.frag
attribute vec4 aPos; attribute vec2 aCoordinate; varying vec2 vCoordinate; void main(){ vCoordinate = aCoordinate; gl_Position = aPos; }
片元着色器 frag.frag
precision mediump float; uniform sampler2D uSampler; varying vec2 vCoordinate; void main(){ gl_FragColor = texture2D(uSampler, vCoordinate); }
注意到,里面有用到一个工具类OpenGLESUtils和实体类BaseRenderBean具体就不贴出来了,可以到Github 上查看
四、BaseOesRender
注意到,BaseRender 里面绑定的纹理是2D纹理 ,而如果想实现相机预览,则需要使用Oes纹理 ,所以需要创建一个BaseOesRender 为相机做渲染
package com.yk.media.opengles.render.base;
import android.content.Context; import android.graphics.SurfaceTexture; import android.opengl.GLES11Ext; import android.opengl.GLES20;
import com.yk.media.utils.OpenGLESUtils;
public class BaseOesRender extends BaseRender { /**
- oes纹理id
*/ private int oesTextureId;
/**
- 顶点变换矩阵位置
*/ private int uMatrixLocation;
/**
- 纹理变换矩阵位置
*/ private int uOesMatrixLocation;
/**
- oes尺寸
*/ private int oesW = -1; private int oesH = -1;
/**
- 顶点变换矩阵
*/ private float[] mMVPMatrix = new float[16];
/**
- 纹理变换矩阵
*/ private float[] mOesMatrix = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
/**
- 是否准备好绘制
*/ private boolean isReadyToDraw = false;
/**
- SurfaceTexture
*/ private SurfaceTexture surfaceTexture;
/**
- SurfaceTexture回调
*/ private OnSurfaceTextureListener onSurfaceTextureListener;
public BaseOesRender(Context context) { super(context, “render/base/oes/vertex.frag”, “render/base/oes/frag.frag”); setBindFbo(true); oesTextureId = OpenGLESUtils.getOesTexture(); }
@Override public void onInitCoordinateBuffer() { setCoordinateBuffer(OpenGLESUtils.getSquareCoordinateBuffer()); }
@Override public boolean onReadyToDraw() { if (!isReadyToDraw) { if (onSurfaceTextureListener != null) { if (surfaceTexture != null) { surfaceTexture.release(); surfaceTexture = null; } surfaceTexture = new SurfaceTexture(oesTextureId); onSurfaceTextureListener.onSurfaceTexture(surfaceTexture); isReadyToDraw = true; } else if (surfaceTexture != null) { surfaceTexture.attachToGLContext(oesTextureId); isReadyToDraw = true; } else { return false; } } return oesW != -1 && oesH != -1; }
@Override public void onDrawPre() { super.onDrawPre(); mMVPMatrix = OpenGLESUtils.getMatrix(getWidth(), getHeight(), oesW, oesH);
surfaceTexture.updateTexImage();
float[] oesMatrix = new float[16]; surfaceTexture.getTransformMatrix(oesMatrix); if (!OpenGLESUtils.isIdentityM(oesMatrix)) { mOesMatrix = oesMatrix; } }
@Override public void onInitLocation() { super.onInitLocation(); uMatrixLocation = GLES20.glGetUniformLocation(getProgram(), “uMatrix”); uOesMatrixLocation = GLES20.glGetUniformLocation(getProgram(), “uOesMatrix”); }
@Override public void onActiveTexture(int textureId) {
最后
希望本文对你有所启发,有任何面试上的建议也欢迎留言分享给大家。
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以加一下下面的技术群。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
这里放一下资料获取方式:GitHub
好了~如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
cation(getProgram(), “uOesMatrix”); }
@Override public void onActiveTexture(int textureId) {
最后
希望本文对你有所启发,有任何面试上的建议也欢迎留言分享给大家。
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以加一下下面的技术群。来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
这里放一下资料获取方式:GitHub
[外链图片转存中…(img-OAcuyt6Z-1645092487723)]
好了~如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
[外链图片转存中…(img-fULNKoz2-1645092487724)]
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能点个小赞和关注下我,以后还会更新技术干货,谢谢您的支持!
|