【发布时间】:2014-10-23 15:45:25
【问题描述】:
我正在开展一个项目,该项目需要我“平移”相机预览以找到一个小区域。我通过将预览渲染到 SurfaceTexture 并将变换应用于传递到顶点着色器的顶点来部分工作。用户看到并能够“平移”的“裁剪”区域为 1024x1024,相机预览尺寸为 1920x1080。
我遇到的问题本质上是找到预览的界限。我可以将顶点完全移出屏幕,它会继续移动。我尝试了几种策略来解决这个问题,但我没有任何运气。
我尝试的第一件事是计算形状顶点中的值,以使预览与视图齐平。在没有应用任何比例的情况下,形状顶点的范围应该是 [-1,1]。对于上下左右方向的以下顶点也是如此。但是,我通过反复试验发现右边缘的偏移量为 0.12。这是完全合乎逻辑的,因为相机预览比显示它的视图宽得多。我不确定我应该如何解释这一点以强制执行边界。
/* Initial position of the shape */
{ -1.0 1.0
-1.0 -1.0
1.0 -1.0
1.0 1.0 }
/* Right edge against the screen */
{ -1.12 1.0
-1.12 -1.0
0.88 -1.0
0.88 1.0 }
出于好奇,接下来我尝试使用 glReadPixel 获取屏幕边缘的像素列。我发现如果将形状从屏幕上平移出来,我得到的像素都是相等的。这一切都奏效了,直到我达到上面提到的偏移量。在 [-1,1] 有效地切断最后一部分之后,我拥有的像素都是相等的。这只是我用来试水的东西。
glReadPixel(1023, 0, 1, 1024);
鉴于我使用的是 openGL es 2.0,显然很难解释来自着色器的数据。为了尝试查看发生了什么,我编写了一个小实用函数来应用着色器中的转换并将它们打印出来,这就是上述顶点的来源。
有人对此有任何见解吗?我试图寻找任何可以为我指明正确方向的东西,但我什么也没找到。如果有任何有用的代码,请告诉我,如果可以,我会发布。
public void printFinalShapeCoords(float coords[]) {
float shapeCoords[] = new float[8];
for(int i = 0; i < coords.length; i+=2) {
mScratchVector[0] = coords[i];
mScratchVector[1] = coords[i+1];
mScratchVector[2] = 0;
mScratchVector[3] = 1;
Matrix.multiplyMV(mTempVector, 0, mMVPMatrix, 0, mScratchVector, 0);
shapeCoords[i] = mTempVector[0];
shapeCoords[i+1] = mTempVector[1];
}
Log.e(TAG, "Final shape coords:\n"+Arrays.toString(shapeCoords));
}
顶点着色器:
"uniform mat4 u_MVPMatrix;"+ /* 4x4 MVP matrix */
"attribute vec4 vPosition;" + /* Position vector */
"attribute vec2 inputTextureCoordinate;" + /* Texture coordinates */
"varying vec2 textureCoordinate;" + /* Texture coordinates that are passed to the fragment shader */
"void main()" +
"{"+
"gl_Position = u_MVPMatrix*vPosition;"+ /* Multiply the MVP matrix and the position vector */
"textureCoordinate = inputTextureCoordinate;" +
"}";
片段着色器:
"#extension GL_OES_EGL_image_external : require\n"+
"precision mediump float;" +
"varying vec2 textureCoordinate;\n" +
"uniform samplerExternalOES s_texture;\n" +
"void main() {" +
" gl_FragColor = texture2D( s_texture, textureCoordinate );\n" +
"}";
编辑(2014 年 10 月 24 日下午 3:07 EST)
有评论提到我不太清楚我要完成什么,我想澄清一下。
基本上,我正在尝试显示相机预览的一部分,同时能够在按下按钮时查看剩余的预览。显示的部分为 1024x1024,而相机预览尺寸为 1920x1080。我要进行的行为的一个示例是在 Gallery 应用程序中。在查看图片时,用户可以“缩放”然后“遍历”图片的其余部分。我正在尝试这样做,但使用相机预览而不是静态图像。正如我之前提到的,我的缩放/平移工作正常,但我找不到停止平移的点。
【问题讨论】:
-
你的MVP矩阵是你从getTransformMatrix得到的吗?
-
@mikkokoo 不,不是。我在每个绘制调用的纹理顶点上使用 getTransformMatrix 。我从该函数得到的矩阵几乎是一个单位矩阵,但不是 y 的正 1,而是负 1,它将相机预览翻转到正确的方向。 MVP 矩阵包含应用于形状顶点的其他变换。
-
好的。如果您只是想将纹理blit 到视图(即没有3D 转换),您可以跳过矩阵并直接使用clip space 坐标作为顶点位置。然后移动纹理坐标以平移图像。不过,我认为我不太明白你想要做什么。
-
@mikkokoo 我编辑了问题以尝试澄清一下。
标签: android opengl-es android-camera opengl-es-2.0