android opengl位图图像未使用texImage2D渲染

Posted

技术标签:

【中文标题】android opengl位图图像未使用texImage2D渲染【英文标题】:android opengl bitmap image not rendered with texImage2D 【发布时间】:2017-10-03 02:36:37 【问题描述】:

我想创建一个挥动的旗帜作为动态壁纸,问题是它不绘制图像(没有错误!)但它成功绘制了其他纹理。 我考虑了其他类似的问题和解决方案,但没有成功。

这是实现 GLSurfaceView.Renderer 的 StripesSurfaceView 的代码:

    private final class StripesSurfaceView extends GLSurfaceView implements
            GLSurfaceView.Renderer 


        private Context context;

        private int textures[];

        private OpenGLFlag flag;

        private boolean paused = false;

        public StripesSurfaceView(Context context) 
            super(context);
            this.context = context;
            setRenderer(this);
            setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

        

        @Override
        public final SurfaceHolder getHolder() 
            return WallpaperEngine.this.getSurfaceHolder();
        

        public final void onDestroy() 
            super.onDetachedFromWindow();
        

        @Override
        public final void onDrawFrame(GL10 gl) 
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

            gl.glPushMatrix();

            // rotate
            gl.glRotatef(Constants.FLAG_ROTATION_X, 1.0f, 0.0f, 0.0f);
            gl.glRotatef(Constants.FLAG_ROTATION_Y, 0.0f, 1.0f, 0.0f);
            gl.glRotatef(Constants.FLAG_ROTATION_Z, 0.0f, 0.0f, 1.0f);

            // draw
            flag.draw(gl, paused);

            gl.glPopMatrix();

        

        @Override
        public final void onSurfaceChanged(GL10 gl, int width,
                int height) 
            float ratio = (float) width / height;

            // flag
            flag = new OpenGLFlag(textures[0], 0, 0, 0, ratio * 2, ratio);

            gl.glShadeModel(GL10.GL_SMOOTH);
            GLES20.glClearDepthf(1.0f);
            GLES20.glEnable(GLES20.GL_DEPTH_TEST);
            GLES20.glDepthFunc(GLES20.GL_LEQUAL);
            GLES20.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GLES20.GL_NICEST);
            GLES20.glEnable(GLES20.GL_BLEND);
            GLES20.glEnable(GL10.GL_POINT_SMOOTH);
            GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); // https://www.opengl.org/sdk/docs/man2/xhtml/glBlendFunc.xml

            GLES20.glViewport(0, 0, width, height);
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // https://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml

            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
            GLU.gluLookAt(gl, 0, 0, 3.5f, 0, 0, 0, 0, 1.0f, 0); // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml

        

        @Override
        public final void onSurfaceCreated(GL10 gl, EGLConfig config) 

            // bind texture
            textures = new int[1];
            GLES20.glEnable(GLES20.GL_TEXTURE_2D);
            GLES20.glGenTextures(textures.length, textures, 0);
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
            Log.d("gfd", context.getResources()+" :: "+ Constants.FLAG_TEXTURE);
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.s);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
            bitmap.recycle();



        

    


这里是 StripesSurfaceView 调用的地方:

    private final class WallpaperEngine extends Engine  


    private StripesSurfaceView mGLSurfaceView;

    @Override
    public void onCreate(SurfaceHolder surfaceHolder) 

        super.onCreate(surfaceHolder);
        mGLSurfaceView = new StripesSurfaceView(getApplicationContext());

    
  // ..... etc

这是当前结果:

纹理到波浪:

【问题讨论】:

你能把你的纹理贴在这里吗?此外,最简单的罪魁祸首可能是非方形纹理。 @codetiger 我添加了,它不透明,它有白色背景,我用不同的图片测试,它们都有相同的结果 你尝试过 256x256px 大小的 2 种纹理的力量 @codetiger 尝试但没有成功 唯一的机会是 TextureCoords 和你的渲染方式 【参考方案1】:

使用decodestream 解决的问题:

        private Bitmap getBitmapFromAssets(Context context, String fileName, int width, int height) 
            AssetManager asset = context.getAssets();
            InputStream is;
            try 
                is = asset.open(fileName);
            BitmapFactory.Options options = new BitmapFactory.Options();
            Bitmap bit=BitmapFactory.decodeStream(is, null, options);
            return bit;
             catch (IOException e) 
                e.printStackTrace();
                return null;
            
        

我在这里发布了源代码: https://github.com/ataafarin/android-live-wallpaper-wavingflag

【讨论】:

以上是关于android opengl位图图像未使用texImage2D渲染的主要内容,如果未能解决你的问题,请参考以下文章

位图图像未在viewpager android中显示

为啥在 glfw 窗口上没有使用 opengl 显示位图图像?在 C++ 中读取位图图像文件时出现问题

Android 进阶——性能优化之Bitmap位图内存管理及优化

Android 进阶——性能优化之Bitmap位图内存管理及优化

Android 进阶——性能优化之Bitmap位图内存管理及优化

Android 进阶——性能优化之Bitmap位图内存管理及优化