Grüße meine Kolleginnen und Programmierer zu verwenden,Failing VBOs in OpenGl/Android
ich das Web durchsucht habe, geprüft Beispiele online, aber immer noch nicht herausfinden können,. Es tut mir leid, wenn das vorher gefragt wurde, ich bin müde nach einer Woche Debuggen von diesem. Ich hoffe ihr könnt mir helfen.
Grundsätzlich ist das Problem, dass ich versuche, einige Quads (mit Dreiecken) zu zeichnen, aber nichts wird gezeichnet. Zuvor zeichnete ich ohne VBOs wie in "Triangle example" auf der offiziellen Android-Website beschrieben. Alles funktionierte gut, aber ich entschied, dass Eckpunkte/Indizes Puffer in Renderer.OnDrawFrame Aktualisierung() nicht effizient :)
So, hier ist mein Code:
public class FloorPlanRenderer implements GLSurfaceView.Renderer {
public volatile float mAngle;
// mMVPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private GLSurfaceView mGlView;
private GlEngine mGlEngine;
private boolean dataSet = false;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Initialize the accumulated rotation matrix
Matrix.setIdentityM(mRotationMatrix, 0);
// Position the eye in front of the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = -3.0f;
// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = 0.0f; //-5.0f;
// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;
// Set the view matrix. This matrix can be said to represent the camera position.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
mGlEngine = new GlEngine(10);
mGlEngine.registerQuad(new Wall(-0.5f, 0.4f, -0.2f, 0.4f));
mGlEngine.registerQuad(new Wall(0.5f, 0.4f, 0.2f, 0.4f));
mGlEngine.registerQuad(new Wall(0.0f, 0.0f, 0.0f, 0.3f, 0.02f));
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
// Create a new perspective projection matrix. The height will stay the same
// while the width will vary as per aspect ratio.
final float ratio = (float) width/height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 3.0f;
final float far = 7.0f;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}
@Override
public void onDrawFrame(GL10 gl) {
float[] scratch = new float[16];
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f);
// Combine the rotation matrix with the projection and camera view
// Note that the mMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
mGlEngine.render(scratch);
}
}
GlEngine Klasse:
public class GlEngine {
public static final int COORDS_PER_VERTEX = 3;
public static final int ORDER_INDICES_PER_QUAD = 6;
public static final int VERTICES_PER_QUAD = 4;
public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE;
public static final int SIZE_OF_SHORT = Short.SIZE/Byte.SIZE;
private int mQuadsNum = 0;
private int mLastCoordsIndex = 0;
private int mLastOrderIndex = 0;
private final FloatBuffer vertexBuffer;
private final ShortBuffer indexBuffer;
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
// Use to access and set the view transformation
private int mMVPMatrixHandle;
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };
private boolean mDataInitNeeded = true;
public GlEngine(int quadsNum) {
ByteBuffer bb = ByteBuffer.allocateDirect(quadsNum * VERTICES_PER_QUAD *
COORDS_PER_VERTEX * SIZE_OF_FLOAT);
bb.order(ByteOrder.nativeOrder()); // device hardware's native byte order
vertexBuffer = bb.asFloatBuffer();
ByteBuffer bb2 = ByteBuffer.allocateDirect(quadsNum *
ORDER_INDICES_PER_QUAD * SIZE_OF_SHORT);
bb2.order(ByteOrder.nativeOrder());
indexBuffer = bb2.asShortBuffer();
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void registerQuad(Wall quad) {
quad.putCoords(vertexBuffer);
quad.putIndices(indexBuffer);
mQuadsNum++;
}
// This code is dealing with VBO side of things
private final int[] mVerticesBufferId = new int[BUFFERS_COUNT];
private final int[] mIndicesBufferId = new int[BUFFERS_COUNT];
private static final int BUFFERS_COUNT = 1;
public void copyToGpu(FloatBuffer vertices) {
GLES20.glGenBuffers(BUFFERS_COUNT, mVerticesBufferId, 0);
// Copy vertices data into GPU memory
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.capacity() * SIZE_OF_FLOAT, vertices, GLES20.GL_STATIC_DRAW);
// Cleanup buffer
vertices.limit(0);
vertices = null;
}
public void copyToGpu(ShortBuffer indices) {
GLES20.glGenBuffers(BUFFERS_COUNT, mIndicesBufferId, 0);
// Copy vertices data into GPU memory
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, indices.capacity() * SIZE_OF_SHORT, indices, GLES20.GL_STATIC_DRAW);
// Cleanup buffer
indices.limit(0);
indices = null;
}
public void render(float[] mvpMatrix) {
setData();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]);
GLES20.glUseProgram(mProgram);
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]);
// Draw quads
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, mQuadsNum * ORDER_INDICES_PER_QUAD,
GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
// This method is called on gl thread GlSurfaceView.queueEvent(...)
public void setData() {
if (mDataInitNeeded) {
// Reset positions of buffers for consuming in GL
vertexBuffer.position(0);
indexBuffer.position(0);
copyToGpu(vertexBuffer);
copyToGpu(indexBuffer);
mDataInitNeeded = false;
}
}
public void deallocateGlBuffers() {
if (mVerticesBufferId[0] > 0) {
GLES20.glDeleteBuffers(mVerticesBufferId.length, mVerticesBufferId, 0);
mVerticesBufferId[0] = 0;
}
if (mIndicesBufferId[0] > 0) {
GLES20.glDeleteBuffers(mIndicesBufferId.length, mIndicesBufferId, 0);
mIndicesBufferId[0] = 0;
}
}
}
The Wall Klasse, die Rechteck steht für:
public class Wall {
// number of coordinates per vertex in this array
private static final int COORDS_PER_VERTEX = 3;
private static final int VERTICES_NUM = 4; // it's a rect after all
private static final float DEFAULT_WIDTH = 0.05f;
private static final float DEFAULT_COORDS_SOURCE = 0.5f;
private final float mCoords[] = new float[COORDS_PER_VERTEX * VERTICES_NUM];
private final short mDrawOrder[] = { 0, 1, 2, // first triangle
1, 2, 3 }; // second triangle
private int mVertexBufferPosition;
private int mIndexBufferPosition;
private final PointF mA = new PointF(0, 0);
private final PointF mB = new PointF(0, 0);
private float mWidth;
public Wall() {
init(-DEFAULT_COORDS_SOURCE, DEFAULT_COORDS_SOURCE, DEFAULT_COORDS_SOURCE,
-DEFAULT_COORDS_SOURCE, DEFAULT_WIDTH);
}
public Wall(float x1, float y1, float x2, float y2)
{
init(x1, y1, x2, y2, DEFAULT_WIDTH);
}
public Wall(float x1, float y1, float x2, float y2, float width) {
init(x1, y1, x2, y2, width);
}
private void init(float x1, float y1, float x2, float y2, float width) {
mA.x = x1;
mA.y = y1;
mB.x = x2;
mB.y = y2;
mWidth = width;
calcCoords();
}
private void calcCoords() {
float[] vector = {mA.x - mB.x, mA.y - mB.y};
float magnitude = (float) Math.sqrt(vector[0]*vector[0] + vector[1]*vector[1]);
float[] identityVector = {vector[0]/magnitude, vector[1]/magnitude};
float[] orthogonalIdentityVector = {identityVector[1], -identityVector[0]};
mCoords[0] = mA.x + mWidth * orthogonalIdentityVector[0];
mCoords[1] = mA.y + mWidth * orthogonalIdentityVector[1];
mCoords[3] = mA.x - mWidth * orthogonalIdentityVector[0];
mCoords[4] = mA.y - mWidth * orthogonalIdentityVector[1];
mCoords[6] = mB.x + mWidth * orthogonalIdentityVector[0];
mCoords[7] = mB.y + mWidth * orthogonalIdentityVector[1];
mCoords[9] = mB.x - mWidth * orthogonalIdentityVector[0];
mCoords[10] = mB.y - mWidth * orthogonalIdentityVector[1];
}
public void putCoords(FloatBuffer vertexBuffer) {
mVertexBufferPosition = vertexBuffer.position();
for (int i = 0; i < mDrawOrder.length; i++) {
mDrawOrder[i] += mVertexBufferPosition/GlEngine.COORDS_PER_VERTEX;
}
vertexBuffer.put(mCoords);
}
public void putIndices(ShortBuffer indexBuffer) {
mIndexBufferPosition = indexBuffer.position();
indexBuffer.put(mDrawOrder);
}
public float getWidth() {
return mWidth;
}
public void setWidth(float mWidth) {
this.mWidth = mWidth;
}
public PointF getA() {
return mA;
}
public void setA(float x, float y) {
this.mA.x = x;
this.mA.y = y;
}
public PointF getB() {
return mB;
}
public void setB(float x, float y) {
this.mB.x = x;
this.mB.y = y;
}
}
In der Wall-Klasse speichere ich Offset, wo es seine Eckpunkte und Indizes platziert, weil diese Klasse sich in der Zukunft ändern wird und ihre Eckpunkte im Hauptpuffer aktualisieren soll (der Puffer wird nicht für jeden OnDrawFrame neu kompiliert).
Vielen Dank. Ich hoffe mit deiner Hilfe werde ich dieses (andere) Hindernis auf meinem Weg zu OpenGl ES irgendwie überwinden.
Ich würde versuchen, den "nahe" -Wert ein wenig kleiner zu setzen. Im Moment befindet sich Ihre Geometrie genau in der Nähe der Clip-Ebene. –
Könnten Sie bitte mich auf die genaue Zeile im Code hinweisen? –
'final float near = 3.0f;' –