繁体   English   中英

GLSurfaceView交换正在绘制的2D位图

[英]GLSurfaceView swaps 2D bitmaps being drawn

我有一个从数据库接收信息的应用程序,用于将2D位图可视化到GLSurfaceView上。 收到的信息将确定位图的x位置以及要使用的位图图像(在我的res文件夹中有4种不同的位图可供选择)。

下面是正在使用的三个类。 Activity通过将ArrayList传递给GLLayer类来设置需要绘制的Shapes对象。 该ArrayList通过另一个setList方法传递给ShapeStorage类的实例。 该类负责在收到它们时进行绘制。

我遇到的问题如下。 假设我收到一个对象(假设它在x = 1处是一个正方形)。 一段时间过去了,我得到了另一个形状(这次是一个三角形,并且位于x = -1处)。 但是,当这种新形状出现在屏幕上时,旧位图的外观将变为三角形,而新位图将变为正方形。 换句话说,对象本身处于应该位于的正确位置,但是与它们关联的位图已更改。 有谁知道这可能是什么原因? 我仍然是OpenGL-ES的新手,虽然这段代码看起来很复杂,但它只涉及为View设置许多属性。 请帮我,StackOverflow! 你是我唯一的希望。

public class GLLayer extends GLSurfaceView implements Renderer {
    int onDrawFrameCounter=1;
    int[] cameraTexture;
    byte[] glCameraFrame=new byte[256*256]; //size of a texture must be a power of 2
    private Context context;
    FloatBuffer cubeBuff;
    FloatBuffer texBuff;
    ShapeStorage shapes;
    ArrayList<Shapes> shapereceptionbuffer;

    public GLLayer(Context c) {
        super(c);
        this.context=c;
        //Initiate our stars class with the number of stars
        shapes = new ShapeStorage();
        shapereceptionbuffer=new ArrayList<Shapes>();

        this.setEGLConfigChooser(5, 6, 5, 8, 16, 0);
        this.setRenderer(this); //set the following class as a GLSurfaceView renderer
        this.getHolder().setFormat(PixelFormat.TRANSPARENT); //makes the GLSurfaceView translucent

    }

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        try {       
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
            gl.glShadeModel(GL10.GL_SMOOTH);                    //Enable Smooth Shading
            gl.glEnable(GL10.GL_TEXTURE_2D);                    //Enable Texture Mapping
            gl.glEnable(GL10.GL_BLEND);                         //Enable blending
            gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);            //Black Background
            gl.glClearDepthf(1.0f);                             //Depth Buffer Setup
            gl.glDisable(GL10.GL_DEPTH_TEST);                   //Disable depth test
            gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);     //Set The Blending Function For Translucency
            shapes.setTextures(gl,context);



        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d("Created",e.getMessage());
        }
    }//end of surfacecreated    

    public void setList(ArrayList<Shapes> receivedList){
        synchronized(this.shapereceptionbuffer){
            shapereceptionbuffer=receivedList;

        }
    }

    public void onSurfaceChanged(GL10 gl, int width, int height) {  
        try {

            if(height == 0) {                       //Prevent A Divide By Zero By
                height = 1;                         //Making Height Equal One
            }

            gl.glViewport(0, 0, width, height);//specifies transformation from normalized device coordinates to window coordinates
            float ratio = (float) width / height;
            gl.glMatrixMode(GL11.GL_PROJECTION); //Select The Projection Matrix
            gl.glLoadIdentity();//Reset The Projection Matrix
            GLU.gluPerspective(gl, 45.0f, ratio, 0.1f, 100.0f);
            gl.glMatrixMode(GL11.GL_MODELVIEW);//Select The Modelview Matrix
            gl.glLoadIdentity();//Reset The Modelview Matrix
        } catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d("Changed",e.getMessage());
        }
        //GLU.gluLookAt(gl, 0, 0, 4.2f, 0, 0, 0, 0, 1, 0);//eye-point location, center of the scene and an UP vector        
    }//end of surfacechanged

    public void onDrawFrame(GL10 gl) {
        try {
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //Clear Screen And Depth Buffer
            Log.d("Buffer Size", String.valueOf(shapereceptionbuffer.size()));
            synchronized(this.shapereceptionbuffer){

                shapes.setShapes(shapereceptionbuffer);
                shapes.draw(gl, this.context);
            }

        } catch (Exception e) {
            Log.d("Draw",e.getMessage());
        }   
    }//end of ondrawframe
}

此类负责绘制从外部数据库接收的每个形状。

/**
 * This class contains, loads, initiates textures and draws our Shapes
 */
public class ShapeStorage {
    private ArrayList<Shapes> shapestoragebuffer;
    private Random rand = new Random(); // Initiate Random for random values of
                                        // stars

    /** Our texture pointer */
    private int[] textures = new int[4];

    /**
     * Constructor for our holder
     */
    public ShapeStorage() {
        shapestoragebuffer = new ArrayList<Shapes>();
    }

    public void setShapes(ArrayList<Shapes> receivedlist) {
        shapestoragebuffer = receivedList;
    }

    public void setupTextures(GL10 gl, Context context) {
        // Get the texture from the Android resource directory
        InputStream is = null;
        gl.glGenTextures(4, textures, 0);
        for (int i = 2; i < 6; i++) {
            switch (i) {
            case 2:
                is = context.getResources().openRawResource(R.drawable.square);
                break;
            case 3:
                is = context.getResources().openRawResource(R.drawable.circle);
                break;

            case 4:
                is = context.getResources().openRawResource(R.drawable.hexagon);
                break;

            case 5:
                is = context.getResources()
                        .openRawResource(R.drawable.triangle);
                break;
            }

            Bitmap bitmap = null;
            try {
                // BitmapFactory is an Android graphics utility for images
                bitmap = BitmapFactory.decodeStream(is);

            } finally {
                // Always clear and close
                try {
                    is.close();
                    is = null;
                } catch (IOException e) {
                }
            }

            // Generate the texture pointer

            // Create Linear Filtered Texture and bind it to texture
            GLUtils.texImage2D(GL11.GL_TEXTURE_2D, 0, bitmap, 0);
            gl.glBindTexture(GL11.GL_TEXTURE_2D, textures[i - 2]);
            gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
                    GL11.GL_LINEAR);
            gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
                    GL11.GL_LINEAR);

            // Clean up
            bitmap.recycle();
        }
    }

    /**
     * The drawing function.
     * 
     * @param gl
     *            - The GL Context
     * @param twinkle
     *            - Twinkle on or off
     */
    public void draw(GL10 gl, Context context) {
        // Bind the icon texture for all Shapes



        for (int loop = 0; loop < shapestoragebuffer.size(); loop++) {
            // Recover the current star into an object
            Shapes shape = shapestoragebuffer.get(loop);

            gl.glLoadIdentity(); // Reset The Current Modelview Matrix
            // gl.glRotatef(180.0f, -1.0f, 0.0f, 0.0f);
            float x = shape.get_Offset_from_center();
            gl.glTranslatef(x, 0.0f, -40.0f);

            // Draw
            switch (victim.getType()) {
            // green
            case 2:
                shape.draw(gl, textures[0]);
                break;
            // red
            case 3:
                shape.draw(gl, textures[1]);
                break;
            // yellow
            case 4:
                shape.draw(gl, textures[2]);
                break;

            case 5:
                shape.draw(gl, textures[3]);
                break;
            }

        }
    }
}

这是定义要绘制到GLSurfaceView的每个对象的类; 每个正在绘制的形状。

public class Shapes {


    private int _Offset_from_center;
    private int type;

    Context c;
    /** The buffer holding the vertices */
    private FloatBuffer vertexBuffer;
    /** The buffer holding the texture coordinates */
    private FloatBuffer textureBuffer;

    /** The initial vertex definition */
    private float vertices[] = {
                                -1.0f, -1.0f, 0.0f,     //Bottom Left
                                1.0f, -1.0f, 0.0f,      //Bottom Right
                                -1.0f, 1.0f, 0.0f,      //Top Left
                                1.0f, 1.0f, 0.0f        //Top Right
                                                    };

    /** The initial texture coordinates (u, v) */   
    private float texture[] = {
                                0.0f, 0.0f, 
                                1.0f, 0.0f, 
                                0.0f, 1.0f, 
                                1.0f, 1.0f,
                                            };
    public Shapes() {
        //
        ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuf.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

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


    public int get_Offset_from_center() {
        return _Offset_from_center;
    }

    public void set_Offset_from_center(int _Offset_from_center) {
        this._Offset_from_center = _Offset_from_center;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    /**
     * The object own drawing function.
     * Called from the renderer to redraw this instance
     * with possible changes in values.
     * 
     * @param gl - The GL Context
     */
    public void draw(GL10 gl,int texture) {
        gl.glBindTexture(GL11.GL_TEXTURE_2D, texture);
        //Enable the vertex, texture and normal state
        gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

        //Point to our buffers
        gl.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, textureBuffer);

        //Draw the vertices as triangle strip
        gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        //Disable the client state before leaving
        gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);


    }


} 

您正在对纹理进行一些非常奇怪的操作。 为什么要在每个帧上上传每种形状的纹理图像数据,为什么要渲染形状后进行处理?

这是OpenGL中通常使用的纹理流的工作方式:

在应用初始化时:

  1. 使用glGenTextures生成纹理ID。
  2. 使用glBindTexture使该ID为当前纹理。
  3. 设置纹理参数。
  4. 使用texImage2D或类似图像上传图像数据。

然后,每次您需要使用纹理渲染材质时:

  1. 使用与glBindTexture使用的相同ID将纹理与glBindTexture绑定。
  2. 渲染东西,这将使用纹理。

我在这里建议的是:

当您启动活动时(根据Android OpenGL的工作方式,从onCreateonResume间接调用):

  1. 使textures成为5个元素的数组,并将5传递给glGenTextures
  2. 循环浏览,并为您的五个资源中的每一个绑定以上四个资源之一,然后像使用一样使用texImage2D上传图像。

然后,当您实际需要绘制形状时:

  1. 传递一个int作为纹理,而不是一个int []; 根据您想要的形状选择合适的。
  2. 首先,使用该值在绘图函数中调用glBindTexture
  3. 不要让任何电话texImage2D在你的渲染通道。
  4. 调用glDrawArrays绘制使用glBindTexture选择的形状。

还要注意,所有形状可以共享相同的顶点和纹理缓冲区,因为它们的内容相同。 不过,这只是效率问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM