预备知识
默认已经将相机采集的数据通过opengl渲染在安卓的surface上了。渲染需传的主要参数是顶点坐标、纹理坐标和纹理。
既然是想将水印放到相机已经采集的纹理上,肯定需要传递水印转换来的纹理到shader里面去,这一步简单,关键是水印坐标如何转换并传递进去。
我们要知道渲染的大概理解:
surface(如整块黑板)->viewport(如黑板上的显示区域,坐标转换成了中心为(0,0),范围是-1~1的xy轴坐标)->顶点着色器顶点坐标(如在显示区域绘制的图形)->纹理坐标(和顶点坐标一一对应,纹理的左下角为(0,0),范围是0 ~ 1的xy轴坐标)
方案一
最简单的方式,渲染完相机采集的数据后,重新传值水印纹理替换之前的相机纹理的attr值,修改glViewport区域,继续执行glDrawArrays绘制水印(有透明区域)。但是这个时候绘制出来的水印透明区域是黑色的,所以需要用到blend。该方案的最大好处是不需要单独在shader里设置额外属性值,可以直接复用,核心代码片段如下:
glViewport(0,0,width,height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(hVertex);
glEnableVertexAttribArray(hTextureCoord);
glVertexAttribPointer(hVertex,
VERTEX_ATTRIB_POSITION_SIZE,
GL_FLOAT,
false,
0,
vertexBuffer);
glVertexAttribPointer(hTextureCoord,
VERTEX_ATTRIB_TEXTURE_POSITION_SIZE,
GL_FLOAT,
false,
0,
textureCoordBuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, getTextureId()[0]);
glUniform1i(hTexture, 0);
glDrawArrays(GL_TRIANGLE_FAN,0,vertex.length / 3);
//因为相机的纹理坐标考虑了镜像等,所以这里重新传值纹理坐标
glEnableVertexAttribArray(hTextureCoord);
glVertexAttribPointer(hTextureCoord,
VERTEX_ATTRIB_TEXTURE_POSITION_SIZE,
GL_FLOAT,
false,
0,
waterCoordBuffer);
//下面是绘制水印
//直接修改可以绘制的区域,不用再进行复杂的坐标换算
glViewport(0,height - watermarkHeight,watermarkWidth,watermarkHeight);
//使用相机纹理attr赋值水印纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D , watermarkTextureID);
glUniform1i(hTexture , 0);
//混合,使水印透明生效
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glEnable(GLES20.GL_BLEND);
glDrawArrays(GL_TRIANGLE_FAN,0,vertex.length / 3);
方案二
通过矩阵转换,目前没有用到,后续补充。。。