如何解决将旋转应用于 GLSurfaceView
我正在尝试使用 GLSurfaceView 来呈现来自 Camera2 的输出。当设备处于纵向模式时它可以正常工作,但是当旋转到横向时,图片当然是“横向”。
关于如何对输出应用旋转,我已经做了一些环顾四周,但是似乎有多种不同的方法,我希望有一种适合我的简单方法。
这是我的 GLSurfaceView 后代的删节版:
public class DWGLCameraView extends GLSurfaceView implements Renderer,OnFrameAvailableListener {
// Other parts snipped
public void onDrawFrame(GL10 gl) {
mSurfaceTexture.updateTexImage();
float[] mtx = new float[16];
mSurfaceTexture.getTransformMatrix(mtx);
// Can I do something here to apply the rotation?
mDrawer.draw(mtx);
}
}
..还有这个(如果有帮助的话),就是绘图程序 DWGLDrawer 类:
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class DWGLDrawer {
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"attribute vec4 inputTextureCoordinate;" +
"uniform mat4 u_xform;\n" +
"varying vec2 textureCoordinate;" +
"void main()" +
"{"+
"gl_Position = vPosition;"+
"textureCoordinate = (u_xform * inputTextureCoordinate).xy;" +
"}";
private final String fragmentShaderCode =
"#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" +
"}";
private FloatBuffer vertexBuffer,textureVerticesBuffer;
private ShortBuffer drawListBuffer;
private final int mProgram;
private int mPositionHandle;
private int mTextureCoordHandle;
private short drawOrder[] = { 0,1,2,3 }; // order to draw vertices
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 2;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private static float squareCoords[] = {
-1.0f,1.0f,-1.0f,};
private static float textureVertices[] = {
0.0f,0.0f,};
private int texture;
private int mTransformLocation;
public DWGLDrawer(int texture) {
this.texture = texture;
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer bb2 = ByteBuffer.allocateDirect(textureVertices.length * 4);
bb2.order(ByteOrder.nativeOrder());
textureVerticesBuffer = bb2.asFloatBuffer();
textureVerticesBuffer.put(textureVertices);
textureVerticesBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram,vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram,fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
mTransformLocation = GLES20.glGetUniformLocation(mProgram,"u_xform");
}
public void draw(float[] mtx) {
GLES20.glUseProgram(mProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,texture);
GLES20.glUniformMatrix4fv(mTransformLocation,false,mtx,0);
// get handle to vertex shader's vPosition member
int positionHandle = GLES20.glGetAttribLocation(mProgram,"vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepare the <insert shape here> coordinate data
GLES20.glVertexAttribPointer(positionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,vertexStride,vertexBuffer);
int textureCoordHandle = GLES20.glGetAttribLocation(mProgram,"inputTextureCoordinate");
GLES20.glEnableVertexAttribArray(textureCoordHandle);
// textureVerticesBuffer.clear();
// textureVerticesBuffer.put( transformTextureCoordinates( textureVertices,mtx ));
// textureVerticesBuffer.position(0);
GLES20.glVertexAttribPointer(textureCoordHandle,textureVerticesBuffer);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,drawOrder.length,GLES20.GL_UNSIGNED_SHORT,drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisableVertexAttribArray(textureCoordHandle);
}
private int loadShader(int type,String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader,shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private float[] transformTextureCoordinates( float[] coords,float[] matrix) {
float[] result = new float[ coords.length ];
float[] vt = new float[4];
for ( int i = 0 ; i < coords.length ; i += 2 ) {
float[] v = { coords[i],coords[i+1],1 };
Matrix.multiplyMV(vt,matrix,v,0);
result[i] = vt[0];
result[i+1] = vt[1];
}
return result;
}
}
根据我在 onDrawFrame
中的评论,我认为我可以在那里应用轮换。我试过这个:
if (mRotation > 0)
Matrix.rotateM(mtx,mRotation,0f,-1f);
(mRotation 是以度为单位的旋转值)
然而,这导致了一张难以理解的图片,所以我认为这是完全错误的,或者我需要做其他事情
请记住,我使用的是 Camera2,所以 setDisplayOrientation
(来自 Camera)不是一个选项
编辑
我现在已经包含了 DWGLDrawer 的整个声明,并添加到描述中
解决方法
一般来说,您的方法应该是正确的(假设 mRotation 以度为单位,并且基于 Display.getRotation() 之类的东西来确定您的 UI 方向 - 请注意,getRotation 不返回度数,因此必须调整该值) .
但是,这里没有您的着色器代码,因此很难说您是否以与您使用的 rotateM 调用兼容的方式使用 mTransformLocation。因此,您可能只需要调试您看到的矩阵值、rotate 调用的作用等,以找出数学问题在哪里。不幸的是,在处理 EGL(或任何地方,真的)中的转换时很常见。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。