android opengl美颜功能,Android OpenGL+Camera2渲染(4) —— 美颜功能实现

Android OpenGL+Camera2渲染(1) —— OpenGL简单介绍

Android OpenGL+Camera2渲染(2) —— OpenGL实现Camera2图像预览

Android OpenGL+Camera2渲染(3) —— 大眼,贴纸功能实现

Android OpenGL+Camera2渲染(4) —— 美颜功能实现

Android OpenGL+Camera2渲染(5) —— 录制视频,实现快录慢录

和之前将的逻辑一样,有一个美颜的开关按钮。

public void enableBeauty(final boolean isChecked) {

queueEvent(new Runnable() {

@Override

public void run() {

glRender.enableBeauty(isChecked);

}

});

}

public void enableBeauty(boolean isChecked) {

this.beautyEnable = isChecked;

if (isChecked) {

beaytyFilter = new BeautifyFilter(glRenderView.getContext());

beaytyFilter.prepare(screenSurfaceWid, screenSurfaceHeight, screenX, screenY);

} else {

beaytyFilter.release();

beaytyFilter = null;

}

}

美颜的片元着色器

precision mediump float;

varying mediump vec2 aCoord;

uniform sampler2D vTexture;

uniform int width;

uniform int height;

vec2 blurCoordinates[20];

void main(){

//对于100*100 的像素,1/100 步长为

vec2 singleStepOffset = vec2(1.0/float(width), 1.0/float(height));

blurCoordinates[0] = aCoord.xy + singleStepOffset * vec2(0.0, -10.0);

blurCoordinates[1] = aCoord.xy + singleStepOffset * vec2(0.0, 10.0);

blurCoordinates[2] = aCoord.xy + singleStepOffset * vec2(-10.0, 0.0);

blurCoordinates[3] = aCoord.xy + singleStepOffset * vec2(10.0, 0.0);

blurCoordinates[4] = aCoord.xy + singleStepOffset * vec2(5.0, -8.0);

blurCoordinates[5] = aCoord.xy + singleStepOffset * vec2(5.0, 8.0);

blurCoordinates[6] = aCoord.xy + singleStepOffset * vec2(-5.0, 8.0);

blurCoordinates[7] = aCoord.xy + singleStepOffset * vec2(-5.0, -8.0);

blurCoordinates[8] = aCoord.xy + singleStepOffset * vec2(8.0, -5.0);

blurCoordinates[9] = aCoord.xy + singleStepOffset * vec2(8.0, 5.0);

blurCoordinates[10] = aCoord.xy + singleStepOffset * vec2(-8.0, 5.0);

blurCoordinates[11] = aCoord.xy + singleStepOffset * vec2(-8.0, -5.0);

blurCoordinates[12] = aCoord.xy + singleStepOffset * vec2(0.0, -6.0);

blurCoordinates[13] = aCoord.xy + singleStepOffset * vec2(0.0, 6.0);

blurCoordinates[14] = aCoord.xy + singleStepOffset * vec2(6.0, 0.0);

blurCoordinates[15] = aCoord.xy + singleStepOffset * vec2(-6.0, 0.0);

blurCoordinates[16] = aCoord.xy + singleStepOffset * vec2(-4.0, -4.0);

blurCoordinates[17] = aCoord.xy + singleStepOffset * vec2(-4.0, 4.0);

blurCoordinates[18] = aCoord.xy + singleStepOffset * vec2(4.0, -4.0);

blurCoordinates[19] = aCoord.xy + singleStepOffset * vec2(4.0, 4.0);

//计算平均值

vec4 currentColor = texture2D(vTexture, aCoord);

vec3 rgb = currentColor.rgb;

for (int i=0;i<20; i++){

rgb += texture2D(vTexture, blurCoordinates[i].xy).rgb;

}

//模糊像素 //直接显示就是高斯模糊效果

vec4 blur = vec4(rgb * 1.0/21.0, currentColor.a);

//高反差 边缘(轮廓)高亮

vec4 highPassColor = currentColor - blur;

//highPassColor 强光处理 color = 2 * color1 * color2

//highPassColor 高反差基础上,边缘信息进行彩色 深度高亮效果

highPassColor.r = clamp(2.0 * highPassColor.r * highPassColor.r * 24.0, 0.0, 1.0);

highPassColor.g = clamp(2.0 * highPassColor.g * highPassColor.g * 24.0, 0.0, 1.0);

highPassColor.b = clamp(2.0 * highPassColor.b * highPassColor.b * 24.0, 0.0, 1.0);

// 过滤疤痕

vec4 highPassBlur = vec4(highPassColor.rgb, 1.0);

//3、融合 -> 磨皮

//蓝色通道值

float b = min(currentColor.b, blur.b);

float value = clamp((b - 0.2) * 5.0, 0.0, 1.0);

// RGB的最大值

float maxChannelColor = max(max(highPassBlur.r, highPassBlur.g), highPassBlur.b);

// 磨皮程度

float intensity = 1.0;// 0.0 - 1.0f 再大会很模糊

float currentIntensity = (1.0 - maxChannelColor / (maxChannelColor + 0.2)) * value * intensity;

//gl_FragColor = highPassBlur;

// 一个滤镜

//opengl 内置函数 线性融合

//混合 x*(1−a)+y⋅a

// 第三个值越大,在这里融合的图像 越模糊

vec3 r = mix(currentColor.rgb, blur.rgb, currentIntensity);

//

gl_FragColor = vec4(r, 1.0);

}

首先获取周边20个点,取平均值,实现高斯模糊的效果。计算高反差,强光处理,融合的过程,实现美颜。

前面的几篇文章已经讲过大眼 贴纸的创建过程,美颜也一样,都是继承自BaseFilter 的这里就不多说了,直接看一下

onDrawFrame

@Override

public void onDrawFrame(GL10 gl) {

int textureId;

// 配置屏幕

//清理屏幕 :告诉opengl 需要把屏幕清理成什么颜色

GLES20.glClearColor(0, 0, 0, 0);

//执行上一个:glClearColor配置的屏幕颜色

GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

//更新获取一张图

mSurfaceTexture.updateTexImage();

mSurfaceTexture.getTransformMatrix(mtx);

//cameraFiler需要一个矩阵,是Surface和我们手机屏幕的一个坐标之间的关系

cameraFilter.setMatrix(mtx);

textureId = cameraFilter.onDrawFrame(mTextures[0]);

if (bigEyeEnable) {

bigeyeFilter.setFace(tracker.mFace);

textureId = bigeyeFilter.onDrawFrame(textureId);

}

if (beautyEnable) {

textureId = beaytyFilter.onDrawFrame(textureId);

}

if (stickEnable) {

stickerFilter.setFace(tracker.mFace);

textureId = stickerFilter.onDrawFrame(textureId);

}

int id = screenFilter.onDrawFrame(textureId);

//进行录制

avcRecorder.encodeFrame(id, mSurfaceTexture.getTimestamp());

}

拿到上一层的纹理ID,进行处理。

@Override

public int onDrawFrame(int textureId) {

GLES20.glViewport(0, 0, mOutputWidth, mOutputHeight);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffers[0]);

GLES20.glUseProgram(mProgramId);

GLES20.glUniform1i(width, mOutputWidth);

GLES20.glUniform1i(height, mOutputHeight);

//传递坐标

mGlVertexBuffer.position(0);

GLES20.glVertexAttribPointer(vPosition, 2, GLES20.GL_FLOAT, false, 0, mGlVertexBuffer);

GLES20.glEnableVertexAttribArray(vPosition);

mGlTextureBuffer.position(0);

GLES20.glVertexAttribPointer(vCoord, 2, GLES20.GL_FLOAT, false, 0, mGlTextureBuffer);

GLES20.glEnableVertexAttribArray(vCoord);

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);

GLES20.glUniform1i(vTexture, 0);

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);

return mFBOTextures[0];

}

给传入中传入 width height 等参数,执行 glDrawArrays,经过片元着色器,就把美颜后的效果写入了FBO的纹理中了。

github项目地址:https://github.com/wangchao0837/OpenGlCameraRender

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值