Created
June 30, 2017 06:24
-
-
Save guodong1111/453fcaf061b572e028ab379675a32ad6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.gogomaper.meat.feature.live_chat.apprtc; | |
import android.opengl.GLES11Ext; | |
import android.opengl.GLES20; | |
import org.webrtc.GlShader; | |
import org.webrtc.GlUtil; | |
import org.webrtc.RendererCommon; | |
import java.nio.FloatBuffer; | |
import java.util.Arrays; | |
/** | |
* Created by tony on 2017/6/28. | |
*/ | |
class GaussianBlurGlDrawer implements RendererCommon.GlDrawer { | |
// Simple vertex shader, used for both YUV and OES. | |
private static final String VERTEX_SHADER_STRING = | |
"varying vec2 interp_tc;\n" | |
+ "attribute vec4 in_pos;\n" | |
+ "attribute vec4 in_tc;\n" | |
+ "\n" | |
+ "uniform mat4 texMatrix;\n" | |
+ "\n" | |
+ "void main() {\n" | |
+ " gl_Position = in_pos;\n" | |
+ " interp_tc = (texMatrix * in_tc).xy;\n" | |
+ "}\n"; | |
private static final String YUV_FRAGMENT_SHADER_STRING = | |
"precision mediump float;\n" | |
+ "varying vec2 interp_tc;\n" | |
+ "\n" | |
+ "uniform sampler2D y_tex;\n" | |
+ "uniform sampler2D u_tex;\n" | |
+ "uniform sampler2D v_tex;\n" | |
+ "\n" | |
+ "void main() {\n" | |
// CSC according to http://www.fourcc.org/fccyvrgb.php | |
+ " float y = texture2D(y_tex, interp_tc).r;\n" | |
+ " float u = texture2D(u_tex, interp_tc).r - 0.5;\n" | |
+ " float v = texture2D(v_tex, interp_tc).r - 0.5;\n" | |
+ " gl_FragColor = vec4(y + 1.403 * v, " | |
+ " y - 0.344 * u - 0.714 * v, " | |
+ " y + 1.77 * u, 1);\n" | |
+ "}\n"; | |
private static final String OES_FRAGMENT_SHADER_STRING = | |
"#extension GL_OES_EGL_image_external : require\n" | |
+"precision mediump float;\n" | |
+"uniform samplerExternalOES oes_tex;\n" | |
+"varying vec2 interp_tc;\n" | |
+"uniform float blurSize;\n" | |
+"uniform float width;\n" | |
+"uniform float height;\n" | |
+"\n" | |
+"void main(){\n" | |
+" float dx = float(blurSize/width);\n" | |
+" float dy = float(blurSize/height);\n" | |
+" vec4 color = texture2D(oes_tex, interp_tc);\n" | |
+" vec3 sum = vec3(0, 0, 0);\n" | |
+" float collorOffset = 1.0 / (2.0 * 2.0 * blurSize * blurSize);\n" | |
+" for (float x = -blurSize; x < blurSize; x++) {\n" | |
+" for (float y = -blurSize; y < blurSize; y++) {\n" | |
+" sum += texture2D(oes_tex, vec2(interp_tc.x + dx * x, interp_tc.y + dy * y)).rgb * collorOffset;\n" | |
+" }\n" | |
+" }\n" | |
+" gl_FragColor = vec4(sum, color.a);\n" | |
+"}\n"; | |
private static final FloatBuffer FULL_RECTANGLE_BUF = | |
GlUtil.createFloatBuffer(new float[] { | |
-1.0f, -1.0f, // Bottom left. | |
1.0f, -1.0f, // Bottom right. | |
-1.0f, 1.0f, // Top left. | |
1.0f, 1.0f, // Top right. | |
}); | |
private static final FloatBuffer FULL_RECTANGLE_TEX_BUF = | |
GlUtil.createFloatBuffer(new float[] { | |
0.0f, 0.0f, // Bottom left. | |
1.0f, 0.0f, // Bottom right. | |
0.0f, 1.0f, // Top left. | |
1.0f, 1.0f // Top right. | |
}); | |
private GlShader oesShader; | |
private GlShader yuvShader; | |
private GlShader currentShader; | |
private float[] currentTexMatrix; | |
private int texMatrixLocation; | |
private volatile int currentPass = 0; | |
private void initGeometry(GlShader shader) { | |
shader.setVertexAttribArray("in_pos", 2, FULL_RECTANGLE_BUF); | |
shader.setVertexAttribArray("in_tc", 2, FULL_RECTANGLE_TEX_BUF); | |
} | |
/** | |
* Draw an OES texture frame with specified texture transformation matrix. Required resources are | |
* allocated at the first call to this function. | |
*/ | |
@Override | |
public void drawOes(int oesTextureId, float[] texMatrix, int frameWidth, int frameHeight, int viewportX, int viewportY, int viewportWidth, int viewportHeight) { | |
GLES20.glViewport(viewportX, viewportY, viewportWidth, viewportHeight); | |
// Lazy allocation. | |
if (oesShader == null) { | |
oesShader = new GlShader(VERTEX_SHADER_STRING, OES_FRAGMENT_SHADER_STRING); | |
oesShader.useProgram(); | |
GLES20.glUniform1f(oesShader.getUniformLocation("blurSize"), 7); | |
GLES20.glUniform1f(oesShader.getUniformLocation("width"), viewportWidth); | |
GLES20.glUniform1f(oesShader.getUniformLocation("height"), viewportHeight); | |
initGeometry(oesShader); | |
} | |
// Set GLES state to OES. | |
if (currentShader != oesShader) { | |
currentShader = oesShader; | |
oesShader.useProgram(); | |
GLES20.glActiveTexture(GLES20.GL_TEXTURE0); | |
currentTexMatrix = null; | |
texMatrixLocation = oesShader.getUniformLocation("texMatrix"); | |
} | |
// updateTexImage() may be called from another thread in another EGL context, so we need to | |
// bind/unbind the texture in each draw call so that GLES understads it's a new texture. | |
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, oesTextureId); | |
drawRectangle(texMatrix); | |
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0); | |
} | |
@Override | |
public void drawRgb(int textureId, float[] texMatrix, int frameWidth, int frameHeight, int viewportX, int viewportY, int viewportWidth, int viewportHeight) { | |
} | |
@Override | |
public void drawYuv(int[] yuvTextures, float[] texMatrix, int frameWidth, int frameHeight, int viewportX, int viewportY, int viewportWidth, int viewportHeight) { | |
GLES20.glViewport(viewportX, viewportY, viewportWidth, viewportHeight); | |
// Lazy allocation. | |
if (yuvShader == null) { | |
yuvShader = new GlShader(VERTEX_SHADER_STRING, YUV_FRAGMENT_SHADER_STRING); | |
yuvShader.useProgram(); | |
// Set texture samplers. | |
GLES20.glUniform1i(yuvShader.getUniformLocation("y_tex"), 0); | |
GLES20.glUniform1i(yuvShader.getUniformLocation("u_tex"), 1); | |
GLES20.glUniform1i(yuvShader.getUniformLocation("v_tex"), 2); | |
GlUtil.checkNoGLES2Error("y/u/v_tex glGetUniformLocation"); | |
initGeometry(yuvShader); | |
} | |
// Set GLES state to YUV. | |
if (currentShader != yuvShader) { | |
currentShader = yuvShader; | |
yuvShader.useProgram(); | |
currentTexMatrix = null; | |
texMatrixLocation = yuvShader.getUniformLocation("texMatrix"); | |
} | |
// Bind the textures. | |
for (int i = 0; i < 3; ++i) { | |
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i); | |
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, yuvTextures[i]); | |
} | |
drawRectangle(texMatrix); | |
} | |
/** | |
* Draw a YUV frame with specified texture transformation matrix. Required resources are | |
* allocated at the first call to this function. | |
*/ | |
private void drawRectangle(float[] texMatrix) { | |
// Try avoid uploading the texture if possible. | |
if (!Arrays.equals(currentTexMatrix, texMatrix)) { | |
currentTexMatrix = texMatrix.clone(); | |
// Copy the texture transformation matrix over. | |
GLES20.glUniformMatrix4fv(texMatrixLocation, 1, false, texMatrix, 0); | |
} | |
// Draw quad. | |
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); | |
} | |
/** | |
* Release all GLES resources. This needs to be done manually, otherwise the resources are leaked. | |
*/ | |
public void release() { | |
if (oesShader != null) { | |
oesShader.release(); | |
oesShader = null; | |
} | |
if (yuvShader != null) { | |
yuvShader.release(); | |
yuvShader = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment