如何在TextureView Android中绘制立方体[关闭]

Posted

技术标签:

【中文标题】如何在TextureView Android中绘制立方体[关闭]【英文标题】:How to draw cube in TextureView Android [closed] 【发布时间】:2015-01-07 09:52:45 【问题描述】:

我是 opengl ES 的新手,我想在 TextureView 上渲染 open gl 视图。

这里是立方体绘图的示例 open-gl 示例https://gist.github.com/ybakos/4151696 但 当我尝试使用 TextureView 绘制同一个立方体时,

我无法绘制那个立方体。 指导我如何使用 TextureView 绘制 opengl 立方体。

这里是示例代码::

public class DemoGraphicGlctivity extends Activity implements TextureView.SurfaceTextureListener 
    private RenderThread mRenderThread;
    private TextureView mTextureView;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);
        setContentView(mTextureView, new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, 400));
    
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) 
        mRenderThread = new RenderThread(getResources(), surface, DemoGraphicGlctivity.this);
        mRenderThread.start();
    

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) 
    
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) 
        mRenderThread.finish();
        try 
            mRenderThread.join();
         catch (InterruptedException e) 
            Log.e(RenderThread.LOG_TAG, "Could not wait for render thread");
        
        return true;
    
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) 
    
    private static class RenderThread extends Thread 
        private static final String LOG_TAG = "GLTextureView";
        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
        static final int EGL_OPENGL_ES2_BIT = 4;
        private volatile boolean mFinished;
        private final Resources mResources;
        private final SurfaceTexture mSurface;

        private EGL10 mEgl;
        private EGLDisplay mEglDisplay;
        private EGLConfig mEglConfig;
        private EGLContext mEglContext;
        private EGLSurface mEglSurface;
        private GL mGL;
        Context context;

        RenderThread(Resources resources, SurfaceTexture surface, Context mContext) 
            mResources = resources;
            mSurface = surface;
            context = mContext;
        

        @Override
        public void run() 
            initGL();

         // vertices
            FloatBuffer vertexBuffer = ByteBuffer
                    .allocateDirect(CubeConstant.vertices.length * 4)
                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
            vertexBuffer.put(CubeConstant.vertices);
            vertexBuffer.position(0);

            // texture map
            FloatBuffer textureBuffer = ByteBuffer
                    .allocateDirect(CubeConstant.texture.length * 4)
                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
            textureBuffer.put(CubeConstant.texture);
            textureBuffer.position(0);

            // indices
            ByteBuffer indexBuffer = ByteBuffer.allocateDirect(CubeConstant.indices.length);
            indexBuffer.put(CubeConstant.indices);
            indexBuffer.position(0);


            int texture = loadTexture(R.drawable.receipt_bg);

            //int program = buildProgram(sSimpleVS, sSimpleFS);
            int program = ShaderHelper
                    .linkProgram(ShaderHelper
                            .compileVertexShader(TextResourceReader
                                    .readTextFileFromResource(context,
                                            R.raw.cube_vertex)), ShaderHelper
                            .compileFragmentShader(TextResourceReader
                                    .readTextFileFromResource(context,
                                            R.raw.cube_fragment)));



            int aPositionLocation = glGetAttribLocation(program, "a_Position");
            checkGlError();

            int aTextureCoordinatesLocation = glGetAttribLocation(program, "a_TextureCoordinates");
            checkGlError();



            glBindTexture(GL_TEXTURE_2D, texture);
            checkGlError();

            glUseProgram(program);
            checkGlError();

            glVertexAttribPointer(aPositionLocation, 3 , GL_FLOAT, false , 0, vertexBuffer);
            checkGlError();

            vertexBuffer.position(0);   
            glVertexAttribPointer(aPositionLocation, 3 , GL_FLOAT, false , 0, vertexBuffer);
            glEnableVertexAttribArray(aPositionLocation);
            textureBuffer.position(0);
            glVertexAttribPointer(aTextureCoordinatesLocation, 2, GL_FLOAT, false, 0, textureBuffer);
            glEnableVertexAttribArray(aTextureCoordinatesLocation);
            checkGlError();


            glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            checkGlError();

            while (!mFinished) 
                checkCurrent();
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                checkGlError();

                glBindTexture(GL_TEXTURE_2D, texture);
                glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indexBuffer);

                if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) 
                    throw new RuntimeException("Cannot swap buffers");
                
                checkEglError();
                try 
                    Thread.sleep(2000);
                 catch (InterruptedException e) 
                    // Ignore
                
            
            finishGL();
        
        private int loadTexture(int resource) 
            int[] textures = new int[1];
            glActiveTexture(GL_TEXTURE0);
            glGenTextures(1, textures, 0);
            checkGlError();
            int texture = textures[0];
            glBindTexture(GL_TEXTURE_2D, texture);
            checkGlError();

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
            checkGlError();
            bitmap.recycle();
            return texture;
        


        private void checkEglError() 
            int error = mEgl.eglGetError();
            if (error != EGL10.EGL_SUCCESS) 
                Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error));
            
        
        private static void checkGlError() 
            int error = glGetError();
            if (error != GL_NO_ERROR) 
                Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
            
        
        private void finishGL() 
            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
        
        private void checkCurrent() 
            if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
                    !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) 
                if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) 
                    throw new RuntimeException("eglMakeCurrent failed "
                            + GLUtils.getEGLErrorString(mEgl.eglGetError()));
                
            
        

        private void initGL() 
            mEgl = (EGL10) EGLContext.getEGL();
            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) 
                throw new RuntimeException("eglGetDisplay failed "
                        + GLUtils.getEGLErrorString(mEgl.eglGetError()));
            

            int[] version = new int[2];
            if (!mEgl.eglInitialize(mEglDisplay, version)) 
                throw new RuntimeException("eglInitialize failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
            
            mEglConfig = chooseEglConfig();
            if (mEglConfig == null) 
                throw new RuntimeException("eglConfig not initialized");
            

            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);
            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) 
                int error = mEgl.eglGetError();
                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) 
                    Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
                    return;
                
                throw new RuntimeException("createWindowSurface failed "
                        + GLUtils.getEGLErrorString(error));
            
            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) 
                throw new RuntimeException("eglMakeCurrent failed "
                        + GLUtils.getEGLErrorString(mEgl.eglGetError()));
            
            mGL = mEglContext.getGL();
        

        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) 
            int[] attrib_list =  EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE ;
            return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);            
        
        private EGLConfig chooseEglConfig() 
            int[] configsCount = new int[1];
            EGLConfig[] configs = new EGLConfig[1];
            int[] configSpec = getConfig();
            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) 
                throw new IllegalArgumentException("eglChooseConfig failed " +
                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
             else if (configsCount[0] > 0) 
                return configs[0];
            
            return null;
        

        private static int[] getConfig() 
            return new int[] 
                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                    EGL10.EGL_RED_SIZE, 8,
                    EGL10.EGL_GREEN_SIZE, 8,
                    EGL10.EGL_BLUE_SIZE, 8,
                    EGL10.EGL_ALPHA_SIZE, 8,
                    EGL10.EGL_DEPTH_SIZE, 0,
                    EGL10.EGL_STENCIL_SIZE, 0,
                    EGL10.EGL_NONE
            ;
        
        void finish() 
            mFinished = true;
        
    

请让我知道我哪里出错了......

【问题讨论】:

我遇到了同样的问题。我想用纹理视图绘制一个立方体。请提供上述问题的解决方案 【参考方案1】:

我知道的不多,但我认为你必须对此有罗马人的说明: 创建 OpenGL 上下文

    生成 OpenGL 纹理名称。 使用纹理名称创建 SurfaceTexture。 将 SurfaceTexture 传递给相机。 收听更新。 在 SurfaceTexture 更新时,使用 OpenGL 绘制纹理 你想要的着色器。

【讨论】:

以上是关于如何在TextureView Android中绘制立方体[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

SurfaceView和TextureView的区别

使用 lockCanvas() 的 Android TextureView 硬件加速

android: View, SurfaceView, GLSurfaceView, TextureView 区别与联系

TextureView SurfaceView 简介 案例

旋转 90 时如何将 TextureView 大小调整为全屏?

Android 中Textureview和SurfaceView使用问题总结