OpenGL ES 2.0 only draws the object once

限于喜欢 提交于 2019-12-10 18:59:23

问题


First, let me say I'm sorry for asking so many questions today. So, I have a class for a circle. And I have an arraylist with 3 circle instance, each with a different x coordinate to draw. For whatever reason, OpenGL ES 2.0 is only drawing one of them, even though I call all of them to be drawn. I looked over my code for hours and tried many different things, but to no avail. So, my question is: Is there anything special I have to do to get OpenGL ES 2.0 to draw more than one object? Here is my code(I know its a mess. I will fix that later :) ): Here is my GLCircle class:

package com.background.gl.objects;
import static android.opengl.GLES20.GL_TRIANGLE_FAN;
import static android.opengl.GLES20.glDrawArrays;
import static android.opengl.Matrix.multiplyMM;
import static android.opengl.Matrix.setIdentityM;
import static android.opengl.Matrix.translateM;
import static com.background.gl.glcirclebackgroundanimation.Constants.BYTES_PER_FLOAT;

import java.util.Random;

import android.opengl.Matrix;

import com.background.gl.data.VertexArray;
import com.background.gl.helper.TextureShaderProgram;

public class GLCircle {
    private static final int POSITION_COMPONENT_COUNT = 2;
    private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
    private static final int STRIDE = (POSITION_COMPONENT_COUNT
    + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;

    public  float x;
    public  float y;
    protected  float[] wallBounds;
    protected  boolean positiveX, positiveY;
    public  boolean nullify;
    protected  float xCounter = 0f;
    protected  float yCounter = 0f;
    public  float[] bounds;
    protected Random ran;

    private float[] VERTEX_DATA = {
        // Order of coordinates: X, Y, S, T
        // Triangle Fan
        0f, 0f, 0.5f, 0.5f,
        -0.25f, -0.25f, 0f, 0.9f,
        0.25f, -0.25f, 1f, 0.9f,
        0.25f, 0.25f, 1f, 0.1f,
        -0.25f, 0.25f, 0f, 0.1f,
        -0.25f, -0.25f, 0f, 0.9f };

    private final VertexArray vertexArray;

    public GLCircle(float x, float y) {
        vertexArray = new VertexArray(VERTEX_DATA);
        ran = new Random();
        wallBounds = new float[4];
        nullify = false;
        this.x = x;
        this.y = y;
    }

    public void bindData(TextureShaderProgram textureProgram) {
        //Bind the position data to the shader attribute
        vertexArray.setVertexAttribPointer(
            0,
            textureProgram.getPositionAttributeLocation(),
            POSITION_COMPONENT_COUNT,
            STRIDE);
        //Bind the texture coordinate data to the shader attribute
        vertexArray.setVertexAttribPointer(
                POSITION_COMPONENT_COUNT,
                textureProgram.getTextureCoordinatesAttributeLocation(),
                TEXTURE_COORDINATES_COMPONENT_COUNT,
                STRIDE);
        }

    public void drawCircle() {
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
    }


    public float getX() {
        return this.x;
    }

    public float getY() {
        return this.y;
    }



    public  boolean isPositiveX() {
        return positiveX;
    }



    public  boolean isPositiveY() {
        return positiveY;
    }


    public float[] getBounds(float ranX, float ranY) {
        if(!positiveX) {
            /*if(ranX >= 0f) {
                wallBounds[0] = 1.05f + ranX;
            } else {*/
                this.wallBounds[0] = 1.05f + ranX;
            //}
        } else {
            /*
            if(ranX >= 0f) {
                wallBounds[0] = 1.05f - ranX;
            } else {*/
                this.wallBounds[1] = 1.05f - ranX;
            //}
        }
        if(!positiveY) {
            this.wallBounds[2] = 1.75f + ranY;
        } else {
            this.wallBounds[3] = 1.75f - ranY;
        }

        return this.wallBounds;
    }

    public void setPos(float[] modelMatrix, 
            float[] projectionMatrix, TextureShaderProgram textureProgram,
            int texture, float x, float y) {
        setIdentityM(modelMatrix, 0);
        translateM(modelMatrix, 0, 0f, 0.01f, 0f);
        final float[] temp = new float[16];
        multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
        System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);

        textureProgram.useProgram();
        textureProgram.setUniforms(projectionMatrix, texture);
        bindData(textureProgram);

        drawCircle();
    }

public void scaleCircle(float[] modelMatrix, float x, float y, float z) {
        Matrix.scaleM(modelMatrix, 0, x, y, z);
    }


    public void translateCircle(float x, float[] modelMatrix) {
        translateM(modelMatrix, 0, /*-0.001f*/ x, -3f, -2f);
    }

}

}

So in my renderer class, this is what I do in the onSurfaceCreated() to instantiate these objects(I'm aware I call the generateRanFloats twice and waste memory by doing this):

for(int i = 0; i < 3; i++) {
            GLCircle circle = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]);
            circles.add(circle);
}

So I create my three objects. Now, I translate each of these circles into their x position in the onSurfaceChanged method:

for(int i = 0; i < circles.size(); i++) {
            circles.get(i).translateCircle(circles.get(i).x, modelMatrix);
}

And then I update them in the onDrawFrame() method:

circles.get(i).setPos(modelMatrix, projectionMatrix, textureProgram, texture, circles.get(i).x, circles.get(i).y);

Now, the issue is I only see one of my circles being translated up the screen, when I should have three. As far as I know, I should be able to draw more than one object on the screen. So why is only one being drawn? I also tried to add a separate GLCircle object named circle2 and did the same with this one as well, but it didn't show up either. Is the something I have to do to draw more than one object on the screen? Any help is appreciated, and if you need to see more code, let me know. :)

Edit: Entire renderer class

package com.background.gl.glcirclebackgroundanimation;

import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glViewport;
import static android.opengl.Matrix.multiplyMM;
import static android.opengl.Matrix.setIdentityM;
import static android.opengl.Matrix.translateM;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.util.Log;

import com.background.gl.helper.TextureShaderProgram;
import com.background.gl.objects.GLCircle;
import com.background.gl.objects.Mallet;
import com.background.gl.objects.Table;
import com.background.gl.util.MatrixHelper;
import com.background.gl.util.TextureHelper;

public class CircleDynamicBackgroundRenderer implements Renderer {
private final Context context;

    private final float[] projectionMatrix = new float[16];
    private final float[] modelMatrix = new float[16];
    protected static float ranX, ranY, ranSignX, ranSignY, ranSignVeloX, ranSignVeloY;

    private Table table;
    private Mallet mallet;
    private List<GLCircle> circles;
    private GLCircle circle2;
    float xPos, yPos;
    int x = 1;
    float[] bounds;
    Random ran;

    private TextureShaderProgram textureProgram;

    private int texture;


    public CircleDynamicBackgroundRenderer(Context context) {
        this.context = context;
        circles = new ArrayList<GLCircle>();
        xPos = 0.1f;
        ran = new Random();
    }

    @Override
    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        glViewport(0, 0, width, height);
        Log.w("Width and height", Integer.toString(width) + ", " + Integer.toString(height));
        MatrixHelper.perspectiveM(projectionMatrix, 90, (float) width
                / (float) height, 1f, 10f);

        setIdentityM(modelMatrix, 0);
        for(int i = 0; i < circles.size(); i++) {
            circles.get(i).translateCircle(circles.get(i).x, modelMatrix);
        }
        circle2.translateCircle(circle2.x, modelMatrix);
        final float[] temp = new float[16];
        multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
        System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
    }

    @Override
    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
        glClearColor(0.0f, 0.0f, 1.0f, 0.0f);

        table = new Table();
        mallet = new Mallet();

        textureProgram = new TextureShaderProgram(context);

        texture = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface);
        //texture2 = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface_2);
        for(int i = 0; i < 3; i++) {
            GLCircle circle = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]);
            circles.add(circle);
            /*circle[i].x = circle[i].getX();
            circle[i].y = circle[i].getY();
            circle[i].bounds = circle[i].getBounds();*/
        }
            circle2 = new GLCircle(generateRanFloats()[0], generateRanFloats()[1]);
        Log.d("Circles size", Integer.toString(circles.size()));
        Log.d("circles", Float.toString(circles.get(1).getX()) + " " + Float.toString(circles.get(2).getX()));
    }

    @Override
    public void onDrawFrame(GL10 glUnused) {
        //Clear the rendering surface
        glClear(GL_COLOR_BUFFER_BIT);
        for(int i = 0; i < circles.size(); i++) {
        circles.get(i).setPos(modelMatrix, projectionMatrix, textureProgram, texture, circles.get(i).x, circles.get(i).y);
        Log.d("Circles", Float.toString(circles.get(i).x));
        }

        circle2.setPos(modelMatrix, projectionMatrix, textureProgram, texture, ranSignVeloX, circle2.x);
        Log.d("Circle2", Float.toString(circle2.x));


        //Pass data into our shaders(u_matrix) and enable/bind the texture
        //textureProgram.setUniforms2(projectionMatrix, texture, texture2);
        //Bind our [vertex array] data to our shaders(attribute data)
        //Draw it
        /*
        // Draw the mallets.
        colorProgram.useProgram();
        colorProgram.setUniforms(projectionMatrix);
        mallet.bindData(colorProgram);
        mallet.draw();*/
    }

    public float[] generateRanFloats() {
        ranSignX = ran.nextFloat();
        ranSignY = ran.nextFloat();
        ranSignX = ranSignX > 0.5f? -1:1;
        ranSignY = ranSignY > 0.5f? -1:1;
        ranSignVeloX = ran.nextFloat();
        ranSignVeloY = ran.nextFloat();
        ranX = ran.nextFloat() * 1.05f;
        ranY = ran.nextFloat() * 1.75f;  
        ranX = ranSignX > 0.5? -ranX:ranX;
        ranY = ranSignY > 0.5? -ranY:ranY;
        Log.d("Generated", Float.toString(ranX));
        return new float[] {ranX, ranY};
    }

}

回答1:


public void drawCircle() { glDrawArrays(GL_TRIANGLE_FAN, 0, 6); }

The above code draws one fan. Where is the code that draws the rest ?

If you are calling this in a loop, where is the translation happening in setPos() - as x,y do not seem to be used anywhere, and translateM(modelMatrix, 0, 0f, 0.01f, 0f) always translates the same offset.




回答2:


Probably a bit late, but ...

To me it seems that all the circles are being drawn, but they are drawn on top of each other because translateM is not being applied.

You are calling translateCircle from onSurfaceChanged.

But then in OnDrawFrame you are reverting your model matrix by calling setIdentityM.

setIdentityM(modelMatrix, 0);
translateM(modelMatrix, 0, 0f, 0.01f, 0f);
final float[] temp = new float[16];
multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
...

Removing translateCircle and modify

translateM(modelMatrix, 0, 0f, 0.01f, 0f);

to

translateM(modelMatrix, 0, x, 0.01f, 0f);

should work.



来源:https://stackoverflow.com/questions/21978084/opengl-es-2-0-only-draws-the-object-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!