美文网首页openGL
OpenGL ES3.0 实现灵魂出窍效果

OpenGL ES3.0 实现灵魂出窍效果

作者: minyou1314 | 来源:发表于2019-03-05 17:09 被阅读0次

OpenGL ES3.0 实现灵魂出窍效果

分为两步:1使用GLSurfaceView 实现摄像头预览, 2实现具体的效果

  • 用GLSurfaceView实现摄像头预览,刚开始感觉很难,实际上很简单,生成TextureId, 根据TextureId,生成SurfaceTexture,用SurfaceTexture来存储摄像头的预览数据,然后用OpenGl把纹理画出来

生成TextureId代码如下:

//生成纹理Id
fun createTextureObject(): Int {
var tex = IntArray(1)

//生成一个纹理
GLES30.glGenTextures(1, tex, 0)

//将此纹理绑定到外部纹理上
GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0])
//设置纹理过滤参数
GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST.toFloat())
GLES30.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR.toFloat())
GLES30.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_S,
GL10.GL_CLAMP_TO_EDGE.toFloat()
)
GLES30.glTexParameterf(
GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_T,
GL10.GL_CLAMP_TO_EDGE.toFloat()
)

GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0)
return tex[0]
}

根据TextureId生成SurfaceTexture

fun initSurfaceTexture(): Boolean {
if (mCamera == null || mGLSurfaceView == null) {
Log.i(TAG, "mCamera or mGLSurfaceView is null!")
return false
}

mSurfaceTexture = SurfaceTexture(mOESTextureId)
mSurfaceTexture?.let {
it.setOnFrameAvailableListener {
mGLSurfaceView.requestRender()
}
}
//将此SurfaceTexture作为相机预览输出
mCamera?.let {
it.setPreviewTexture(mSurfaceTexture!!)
it.startPreview()
}

return true
}

得到纹理矩阵并且绘制出来

override fun onDrawFrame(gl: GL10?) {
val t1 = System.currentTimeMillis()

mSurfaceTexture?.updateTexImage()
mSurfaceTexture?.getTransformMatrix(transformMatrix)

if (!isPreviewStarted) {
//在onDrawFrame方法中调用此方法initSurfaceTexture();
// 有了外部纹理,现在可以实例化一个SurfaceTexture了,之后即可开启Camera预览
isPreviewStarted = initSurfaceTexture()
isPreviewStarted = true
return
}

GLES30.glClearColor(1.0f, 0.0f, 0.0f, 0.0f)
mCameraEngine?.drawTexture(transformMatrix)

GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)

val t2 = System.currentTimeMillis()
val t = t2 - t1
Log.i("onDrawFrame", "onDrawFrame: time: $t")
}

至此通过OpenGL预览摄像头完成,需要注意的是SurfaceTexture的监听setOnFrameAvailableListener,当摄像头有帧可用时,会不听的回调此方法,之后通过GLSurfaceView的requestRender()方法来请求绘制,此时onDrawFrame()会被会掉,之后SurfaceView刷新并把纹理数据传递到纹理矩阵供OpenGL 绘制画面

  • 实现灵魂出窍效果,代码如下
override fun drawTexture(transformMatrix: FloatArray) {
GLES30.glEnable(GLES30.GL_BLEND)
GLES30.glBlendFunc(GLES30.GL_SRC_ALPHA, GLES30.GL_ONE_MINUS_SRC_ALPHA)
GLES30.glUseProgram(mShaderProgram)
aPositionLocation = GLES30.glGetAttribLocation(mShaderProgram, POSITION_ATTRIBUTE)
aTextureCoordLocation = GLES30.glGetAttribLocation(mShaderProgram, TEXTURE_COORD_ATTRIBUTE)
uTextureMatrixLocation = GLES30.glGetUniformLocation(mShaderProgram, TEXTURE_MATRIX_UNIFORM)
uTextureSamplerLocation = GLES30.glGetUniformLocation(mShaderProgram, TEXTURE_SAMPLER_UNIFORM)
uTextureAlphaLocation = GLES30.glGetUniformLocation(mShaderProgram, TEXTURE_APLHA_UNIFORM)
uMvpMatrixLocation = GLES30.glGetUniformLocation(mShaderProgram, MVP_MATRIX)

mProgress = mFrames.toFloat() / mMaxFrames
if (mProgress > 1f) {
mProgress = 0f
}
mFrames++
if (mFrames > mMaxFrames + mSkipFrames) {
mFrames = 0
}

var backAlpha = 1f
var alpha = 0f
if (mProgress > 0f) {
alpha = 0.2f - mProgress * 0.2f
backAlpha = 1 - alpha
}

GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mOESTextureId)
GLES30.glUniform1i(uTextureSamplerLocation, 0)
GLES30.glUniformMatrix4fv(uTextureMatrixLocation, 1, false, transformMatrix, 0)

Matrix.setIdentityM(mMvpMatrix, 0)
GLES30.glUniformMatrix4fv(uMvpMatrixLocation, 1, false, mMvpMatrix, 0)
GLES30.glUniform1f(uTextureAlphaLocation, backAlpha)
if (mBuffer != null) {
mBuffer!!.position(0)
GLES30.glEnableVertexAttribArray(aPositionLocation)
GLES30.glVertexAttribPointer(aPositionLocation, 2, GLES30.GL_FLOAT, false, 16, mBuffer)

mBuffer!!.position(2)
GLES30.glEnableVertexAttribArray(aTextureCoordLocation)
GLES30.glVertexAttribPointer(aTextureCoordLocation, 2, GLES30.GL_FLOAT, false, 16, mBuffer)

GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6)
}

if (mProgress > 0f) {
GLES30.glUniform1f(uTextureAlphaLocation, alpha)
val scale = 1.0f + 1f * mProgress
Matrix.scaleM(mMvpMatrix, 0, scale, scale, scale)
GLES30.glUniformMatrix4fv(uMvpMatrixLocation, 1, false, mMvpMatrix, 0)
GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 6)
}
GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
GLES30.glDisable(GLES30.GL_BLEND)
}

画两层,第一层是预览的原始画面,第二层是灵魂出窍的效果,灵魂出窍的效果,实际就是把当前帧的不断的放大并且变得透明,代码很简单,需要注意的是混合因子

相关文章

  • OpenGL ES3.0 实现灵魂出窍效果

    OpenGL ES3.0 实现灵魂出窍效果 分为两步:1使用GLSurfaceView 实现摄像头预览, 2实现具...

  • OpenGL ES的滤镜效果 -- 动效

    今天,我们用OpenGL ES分别来实现以下效果:缩放,灵魂出窍,抖动,闪白,毛刺,幻觉。 准备工作 因为涉及到动...

  • Metal每日分享,灵魂出窍滤镜效果

    本案例的目的是理解如何用Metal实现灵魂出窍滤镜,灵魂出窍效果实现原理是通过两个纹理叠加,根据时间上层纹理做缩放...

  • 缩放滤镜

    抖动效果 灵魂出窍效果 毛刺效果

  • OpenGL(五)灵魂出窍和分屏效果

    OpenGL (一)OpenGL ES 绘制基础[https://www.jianshu.com/p/05e131...

  • OpenGL ES3.0实现简单粒子火焰效果

    通过粒子系统来实现火焰效果,基本思想是把一团火焰看成是由一颗颗有其生命期的粒子组成,粒子在不停的产生直至消亡从而产...

  • OpenGL ES 案例13:动效滤镜(6种)

    OpenGL + OpenGL ES +Metal 系列文章汇总 本案例的目的是理解如何用GLSL实现缩放+灵魂出...

  • 灵魂出窍

    不知道大家是否听说过或经历过这样一些事情,在睡觉或生病(尤其是高烧)的过程中,明明没有去过某些地方或经历过...

  • 灵魂出窍

    一 “什么鬼,我死了吗?” 我看到躺在马路上的自己,一动不动,宛如一具坏掉的人偶,被撞到的头部鲜血淋漓。 “真惨呐...

  • 灵魂出窍

    灵魂出窍,悠悠幽幽悬浮在半空,静静伴随,观照这个肉身。 身材矮胖,面容猥琐,看人的目光像陈佩斯演的...

网友评论

    本文标题:OpenGL ES3.0 实现灵魂出窍效果

    本文链接:https://www.haomeiwen.com/subject/ucpouqtx.html