修改使用表面纹理和OpenGL摄像机输出纹理、摄像机、表面、OpenGL

由网友(北栀)分享简介:我试图通过经由openGL的过滤器运行它,然后在一个GLSurfaceView显示它来过滤从相机硬件传来的流。当openGL的去渲染帧时,LogCat中反复吐出一个错误:[无名的-3314-0] updateTexImage:清除GL错误:0x502 0x502是一个通用的openGL的错误,并没有真正帮助我跟踪问题。...

我试图通过经由openGL的过滤器运行它,然后在一个GLSurfaceView显示它来过滤从相机硬件传来的流。当openGL的去渲染帧时,LogCat中反复吐出一个错误:

  

[无名的-3314-0] updateTexImage:清除GL错误:0x502

0x502是一个通用的openGL的错误,并没有真正帮助我跟踪问题。这是一个怎样的code工作(或至少应工作在我的头上看到)的顺序,我已经复制低于我的code。我希望别人能看到我的问题是。

     创建新MyGLSurfaceView。这在内部创建,以及新的MyGL20Renderer对象。此MyGLSurfaceView设置为内容图。   一旦MyGLSurfaceView完成充气/初始化,完成这个事件触发渲染器来创建一个DirectVideo绘制对象,它编译/链接的着色器定义,并将它们添加到一个OpenGL程序。然后创建一个新的OpenGL纹理对象,然后调用回用纹理对象ID MainActivity。   当从渲染器调用MainActivity方法,它将使用通过OpenGL的纹理对象的新对象,表面纹理。然后它自己设置为表面的onFrameListener。然后创建/打开相机对象,设置创建作为表面纹理视频流的目标,并启动摄像头的饲料。   当一帧是可从进料,所述onFrameAvailable发送呈现请求来渲染。这是拿起了OpenGL线程,它调用的表面纹理的updateTexImage(),它加载帧存储器到OpenGL的纹理。然后,它调用DirectVideo的抽签对象,且OpenGL程序运行序列。 如果我注释掉这.​​draw()线,提到的错误上面消失了,所以这很可能是问题的关键在于某处在这里,但我不排除这个可能性,不会引起不当链接/创建质感。   

MainActivity.java

 公共类MainActivity扩展活动实现SurfaceTexture.OnFrameAvailableListener
{
    私人相机mCamera;
    私人MyGLSurfaceView glSurfaceView;
    私人表面表面纹理;
    MyGL20Renderer渲染器;

    @覆盖
    公共无效的onCreate(包savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        glSurfaceView =新MyGLSurfaceView(本);
        渲染= glSurfaceView.getRenderer();
        的setContentView(glSurfaceView);
    }

    公共无效startCamera(INT纹理)
    {
        表面=新的表面纹理(纹理);
        surface.setOnFrameAvailableListener(本);
        renderer.setSurface(面);

        mCamera = Camera.open();

        尝试
        {
            mCamera.set previewTexture(面);
            mCamera.start preVIEW();
        }
        赶上(IOException异常IOE)
        {
            Log.w(MainActivity,CAM发射失败);
        }
    }

    公共无效onFrameAvailable(表面纹理表面纹理)
    {
        glSurfaceView.requestRender();
    }

    @覆盖
    公共无效的onPause()
    {
        mCamera.stop preVIEW();
        mCamera.release();
        System.exit(0);
    }
 

MyGLSurfaceView.java

 类MyGLSurfaceView扩展GLSurfaceView
{
    MyGL20Renderer渲染器;
    公共MyGLSurfaceView(上下文的背景下)
    {
        超(上下文);

        setEGLContextClientVersion(2);

        渲染器=新MyGL20Renderer((MainActivity)上下文);
        setRenderer(渲染);
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    }
    公共MyGL20Renderer getRenderer()
    {
        返回渲染器;
    }
}
 

MyGL20Renderer.java

 公共类MyGL20Renderer实现GLSurfaceView.Renderer
{

    DirectVideo mDirectVideo;
    INT质感;
    私人表面表面纹理;
    MainActivity代表;

    公共MyGL20Renderer(MainActivity _delegate)
    {
        委托= _delegate;
    }

    公共无效onSurfaceCreated(GL10未使用的,EGLConfig配置)
    {
        mDirectVideo =新DirectVideo(纹理);
        质地= createTexture();
        GLES20.glClearColor(0.5F,0.5F,0.5F,1.0F);
        delegate.startCamera(纹理);
    }

    公共无效onDrawFrame(GL10未使用)
    {
            浮动[] MTX =新的浮动[16];
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            surface.updateTexImage();
            surface.getTransformMatrix(MTX);

            mDirectVideo.draw();
    }

    公共无效onSurfaceChanged(GL10未使用的,诠释的宽度,高度INT)
    {
        GLES20.glViewport(0,0,宽度,高度);
    }

    静态公众诠释loadShader(整型,字符串着色器code)
    {
        INT着色器= GLES20.glCreateShader(类型);

        GLES20.glShaderSource(着色,着色器code);
        GLES20.glCompileShader(着色);

        返回着色器;
    }

    静态私人诠释createTexture()
    {
        INT []质地=新INT [1];

        GLES20.glGenTextures(1,纹理,0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,纹理[0]);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_S,GL10.GL_CLAMP_TO_EDGE);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_T,GL10.GL_CLAMP_TO_EDGE);

        返回质地[0];
    }

    公共无效setSurface(表面纹理_surface)
    {
        表面= _surface;
    }
}
 
Text文本组件的一些操作

DirectVideo.java

 公共类DirectVideo {


    私人最终字符串vertexShader code =
            #extension GL_OES_EGL_image_external:需要的 n+
            属性vec4地位; +
            属性vec4 inputTextureCoordinate; +
            不同的TextureCoordinate VEC2; +
            无效的主要()+
            {+
                GL_POSITION =地位;+
                的TextureCoordinate = inputTextureCoordinate.xy; +
            };

        私人最终字符串fragmentShader code =
            #extension GL_OES_EGL_image_external:需要的 n+
            precision mediump浮动; +
            统一vec4 vColor; +
            无效的主要(){+
            gl_FragColor = vColor; +
            };

        私人FloatBuffer vertexBuffer,textureVerticesBuffer;
        私人ShortBuffer drawListBuffer;
         私人最终诠释mProgram;
            私人诠释mPositionHandle;
            私人诠释mColorHandle;
            私人诠释mTextureCoordHandle;


    //此数组中每个顶点的坐标数量
    静态最终诠释COORDS_PER_VERTEX = 2;
    静浮squareVertices逆时针顺序[] = {//:
         -1.0F,1.0F,
         -1.0F,-1.0F,
         1.0F,-1.0F,
         1.0F,1.0F
    };

    私人短DRAWORDER [] = {0,1,2,0,2,3}; //为了绘制顶点

    静浮textureVertices逆时针顺序[] = {//:
        1.0F,1.0F,
        1.0F,0.0,
        0.0,1.0F,
        0.0,0.0
   };

    私人最终诠释vertexStride = COORDS_PER_VERTEX * 4;每个顶点// 4字节

    私人诠释质感;

    公共DirectVideo(INT _texture)
    {
        纹理= _texture;

        ByteBuffer的BB = ByteBuffer.allocateDirect(squareVertices.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareVertices);
        vertexBuffer.position(0);

        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 = MyGL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER,vertexShader code);
        INT fragmentShader = MyGL20Renderer.loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentShader code);

        mProgram = GLES20.glCreateProgram(); //创建空的OpenGL ES项目
        GLES20.glAttachShader(mProgram,vertexShader); //添加顶点着色器程序
        GLES20.glAttachShader(mProgram,fragmentShader); //添加片段着色器进行编程
        GLES20.glLinkProgram(mProgram);
    }

    公共无效平局()
    {
        GLES20.glUseProgram(mProgram);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,质地);

        mPositionHandle = GLES20.glGetAttribLocation(mProgram,位置);
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,假的,vertexStride,vertexBuffer);

        mTextureCoordHandle = GLES20.glGetAttribLocation(mPrograminputTextureCoordinate);
        GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
        GLES20.glVertexAttribPointer(mTextureCoordHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,假的,vertexStride,textureVerticesBuffer);

        mColorHandle = GLES20.glGetUniformLocation(mProgramvColor);

        GLES20.glDrawElements(GLES20.GL_TRIANGLES,drawOrder.length,
        GLES20.GL_UNSIGNED_SHORT,drawListBuffer);

        //禁用顶点数组
        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
    }
}
 

解决方案

  mDirectVideo =新DirectVideo(纹理);
质地= createTexture();
 

 纹理= createTexture();
mDirectVideo =新DirectVideo(纹理);
 

着色

 私有最终字符串vertexShader code =
        属性vec4地位; +
        属性VEC2 inputTextureCoordinate; +
        不同的TextureCoordinate VEC2; +
        无效的主要()+
        {+
            GL_POSITION =地位;+
            的TextureCoordinate = inputTextureCoordinate; +
        };

    私人最终字符串fragmentShader code =
        #extension GL_OES_EGL_image_external:需要的 n+
        precision mediump浮动; +
        不同的TextureCoordinate VEC2;  N+
        统一samplerExternalOES s_texture;  N+
        无效的主要(){+
        gl_FragColor =的Texture2D(s_texture,的TextureCoordinate);  N+
        };
 

mColorHandle = GLES20.glGetUniformLocation(mProgram,vColor);

mColorHandle = GLES20.glGetAttribLocation(mProgram,s_texture);

从DirectVideo draw.glVertexAttribPointer删除初始化的东西等放入一些初始化函数。

 公共无效平局()
{
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,质地);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES,drawOrder.length,
            GLES20.GL_UNSIGNED_SHORT,drawListBuffer);
}
 

I am trying to filter the stream coming from the camera hardware by running it through an openGL filter, then displaying it in a GLSurfaceView. When openGL goes to render the frame, the LogCat repeatedly spits out an error:

[unnamed-3314-0] updateTexImage: clearing GL error: 0x502

0x502 is a generic openGL error, and doesn't really help me track down the problem. This is a sequence of how the code works (or atleast should be working as seen in my head), and I've copied my code below that. I am hoping that somebody else can see what my problem is.

Create new MyGLSurfaceView. This internally creates the new MyGL20Renderer object as well. This MyGLSurfaceView is set as the content view. Once the MyGLSurfaceView is done inflating/initializing, this completion event triggers the renderer to create a DirectVideo draw object, which compiles/links the shaders defined and adds them to an openGL program. It then creates a new openGL texture object, and then calls back to the MainActivity with the texture object ID. When the MainActivity method is invoked from the renderer, it creates a new SurfaceTexture object using the openGL texture object passed. It then sets itself as the surface's onFrameListener. It then creates/opens the camera object, sets the created SurfaceTexture as the video stream's target, and starts the camera feed. When a frame is available from the feed, the onFrameAvailable sends a render request to the renderer. This is picked up on the openGL thread, which calls the SurfaceTexture's updateTexImage(), which loads the frame memory into the openGL texture. It then calls the DirectVideo's draw object, and the openGL program sequence is run. If I comment out this .draw() line, the mentioned error above disappears, so it seems likely that the problem lies somewhere inside here, but I am not ruling it out being caused by an improperly linked/created texture.

MainActivity.java

public class MainActivity extends Activity implements SurfaceTexture.OnFrameAvailableListener
{
    private Camera mCamera;
    private MyGLSurfaceView glSurfaceView;
    private SurfaceTexture surface;
    MyGL20Renderer renderer;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        glSurfaceView = new MyGLSurfaceView(this);
        renderer = glSurfaceView.getRenderer();
        setContentView(glSurfaceView);
    }

    public void startCamera(int texture)
    {
        surface = new SurfaceTexture(texture);
        surface.setOnFrameAvailableListener(this);
        renderer.setSurface(surface);

        mCamera = Camera.open();

        try
        {
            mCamera.setPreviewTexture(surface);
            mCamera.startPreview();
        }
        catch (IOException ioe)
        {
            Log.w("MainActivity","CAM LAUNCH FAILED");
        }
    }

    public void onFrameAvailable(SurfaceTexture surfaceTexture)
    {
        glSurfaceView.requestRender();
    }

    @Override
    public void onPause()
    {
        mCamera.stopPreview();
        mCamera.release();
        System.exit(0);
    }

MyGLSurfaceView.java

class MyGLSurfaceView extends GLSurfaceView
{
    MyGL20Renderer renderer;
    public MyGLSurfaceView(Context context)
    {
        super(context);

        setEGLContextClientVersion(2);

        renderer = new MyGL20Renderer((MainActivity)context);
        setRenderer(renderer);
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    }
    public MyGL20Renderer getRenderer()
    {
        return renderer;
    }
}

MyGL20Renderer.java

public class MyGL20Renderer implements GLSurfaceView.Renderer
{

    DirectVideo mDirectVideo;
    int texture;
    private SurfaceTexture surface;
    MainActivity delegate;

    public MyGL20Renderer(MainActivity _delegate)
    {
        delegate = _delegate;
    }

    public void onSurfaceCreated(GL10 unused, EGLConfig config)
    {
        mDirectVideo = new DirectVideo(texture);
        texture = createTexture();
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        delegate.startCamera(texture);
    }

    public void onDrawFrame(GL10 unused)
    {
            float[] mtx = new float[16];
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
            surface.updateTexImage();
            surface.getTransformMatrix(mtx); 

            mDirectVideo.draw();
    }

    public void onSurfaceChanged(GL10 unused, int width, int height)
    {
        GLES20.glViewport(0, 0, width, height);
    }

    static public int loadShader(int type, String shaderCode)
    {
        int shader = GLES20.glCreateShader(type);

        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);

        return shader;
    }

    static private int createTexture()
    {
        int[] texture = new int[1];

        GLES20.glGenTextures(1,texture, 0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture[0]);
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);        
        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
     GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
             GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

        return texture[0];
    }

    public void setSurface(SurfaceTexture _surface)
    {
        surface = _surface;
    }
}

DirectVideo.java

public class DirectVideo {


    private final String vertexShaderCode =
            "#extension GL_OES_EGL_image_external : requiren"+
            "attribute vec4 position;" +
            "attribute vec4 inputTextureCoordinate;" +
            "varying vec2 textureCoordinate;" +
            "void main()" +
            "{"+
                "gl_Position = position;"+
                "textureCoordinate = inputTextureCoordinate.xy;" +
            "}";

        private final String fragmentShaderCode =
            "#extension GL_OES_EGL_image_external : requiren"+
            "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}";

        private FloatBuffer vertexBuffer, textureVerticesBuffer;
        private ShortBuffer drawListBuffer;
         private final int mProgram;
            private int mPositionHandle;
            private int mColorHandle;
            private int mTextureCoordHandle;


    // number of coordinates per vertex in this array
    static final int COORDS_PER_VERTEX = 2;
    static float squareVertices[] = { // in counterclockwise order:
         -1.0f,  1.0f,
         -1.0f,  -1.0f,
         1.0f,  -1.0f,
         1.0f,  1.0f
    };

    private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices

    static float textureVertices[] = { // in counterclockwise order:
        1.0f,  1.0f,
        1.0f,  0.0f,
        0.0f,  1.0f,
        0.0f,  0.0f
   };

    private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

    private int texture;

    public DirectVideo(int _texture)
    {
        texture = _texture;

        ByteBuffer bb = ByteBuffer.allocateDirect(squareVertices.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(squareVertices);
        vertexBuffer.position(0);

        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 = MyGL20Renderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = MyGL20Renderer.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);          
    }

    public void draw()
    {
        GLES20.glUseProgram(mProgram);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture);

        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,vertexStride, vertexBuffer);

        mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
        GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
        GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,vertexStride, textureVerticesBuffer);

        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
        GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

        // Disable vertex array
        GLES20.glDisableVertexAttribArray(mPositionHandle);
        GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
    }
}

解决方案

mDirectVideo = new DirectVideo(texture);
texture = createTexture();

should be

texture = createTexture();
mDirectVideo = new DirectVideo(texture);

Shader

private final String vertexShaderCode =
        "attribute vec4 position;" +
        "attribute vec2 inputTextureCoordinate;" +
        "varying vec2 textureCoordinate;" +
        "void main()" +
        "{"+
            "gl_Position = position;"+
            "textureCoordinate = inputTextureCoordinate;" +
        "}";

    private final String fragmentShaderCode =
        "#extension GL_OES_EGL_image_external : requiren"+
        "precision mediump float;" +
        "varying vec2 textureCoordinate;                            n" +
        "uniform samplerExternalOES s_texture;               n" +
        "void main() {" +
        "  gl_FragColor = texture2D( s_texture, textureCoordinate );n" +
        "}";

mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

should be

mColorHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");

remove initialization stuff from DirectVideo draw.glVertexAttribPointer etc. Put it in some init function.

public void draw()
{
    GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texture);
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
            GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
}

阅读全文

相关推荐

最新文章