I'm trying to draw a sphere in OpenGL ES 2.0+ on Android, and I'm seeing the following error in Logcat:
glDrawElements is called with VERTEX_ARRAY client state disabled!
I looked at the documentation for this call and I can't see anything I might be doing wrong. From the error it sounds like I'm missing some setup somewhere.
Here's my VertexBuffer class where I'm doing the setup:
public class VertexBuffer {
private final int mBufferId;
public VertexBuffer(float[] vertexData) {
// Allocate a buffer
final int[] buffers = new int[1];
glGenBuffers(buffers.length, buffers, 0);
if (buffers[0] == 0) {
throw new RuntimeException("Could not create a new VBO");
}
mBufferId = buffers[0];
// Bind to the buffer
glBindBuffer(GL_ARRAY_BUFFER, mBufferId);
// Transfer data to native memory
FloatBuffer vertexArray = ByteBuffer
.allocateDirect(vertexData.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexArray.position(0);
// Transfer data from native memory to the GPU buffer
glBufferData(GL_ARRAY_BUFFER, vertexArray.capacity() * BYTES_PER_FLOAT, vertexArray, GL_STATIC_DRAW);
// IMPORTANT: Unbind from the buffer when we are done with it
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void setVertexAttribPointer(int dataOffset, int attributeLocation, int componentCount, int stride) {
glBindBuffer(GL_ARRAY_BUFFER, mBufferId);
glVertexAttribPointer(attributeLocation, componentCount, GL_FLOAT, false, stride, dataOffset);
glEnableVertexAttribArray(attributeLocation);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
Add:
setEGLContextClientVersion(2);
Related
I just started programming opengl-es 2.0 and I'm currently struggling to find an issue concerned with setting the color of a wavefront object im drawing (https://pastebin.com/cEvpj8rt). The drawing is working just fine until I start to manipulate the color at which point im being confronted with opengl error 1281 and I'm unable to pinpoint the cause in my code. I've broken down the shader code to what I believe is the bare minimum required for the fragment shader to work:
void main() {
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
To eliminate any additional source of error I am setting the color with a constant value as can be seen above. I doubt the error lies with the simple code above but is concerned with the code in my adapted renderer implementation. (it is based on the renderer that came with a sample from the ar-core github repo. The full code of the initial renderer can be found here: https://github.com/google-ar/arcore-android-sdk/blob/master/samples/java_arcore_hello_ar/app/src/main/java/com/google/ar/core/examples/java/helloar/rendering/ObjectRenderer.java while the adapted version can be seen here: https://pastebin.com/9cmKVnLV) Below you can find an excerpt of the code responsible for setting up and drawing the object. I reckoned the issue to be connected to the texturing which is why I removed the code.
I know its a bit much to ask for help given my lack of understanding on the matter at hand but I'd be glad for any hint/advice at this point. The error occurs after the first draw in the following method:
public void draw(float[] cameraView, float[] cameraPerspective) {
multiplyMM(mModelViewMatrix, 0, cameraView, 0, mModelMatrix, 0);
multiplyMM(mModelViewProjectionMatrix, 0, cameraPerspective, 0, mModelViewMatrix, 0);
glUseProgram(mProgram);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
glVertexAttribPointer(mPositionAttribute, COORDS_PER_VERTEX,
GL_FLOAT, false, 0, mVerticesBaseAddress);
glVertexAttribPointer(mNormalAttribute, 3,
GL_FLOAT, false, 0, mNormalsBaseAddress);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Set the ModelViewProjection matrix in the shader.
glUniformMatrix4fv(mModelViewUniform, 1,
false, mModelViewMatrix, 0);
glUniformMatrix4fv(mModelViewProjectionUniform, 1,
false, mModelViewProjectionMatrix, 0);
glEnableVertexAttribArray(mPositionAttribute);
glEnableVertexAttribArray(mNormalAttribute);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
glDrawElements(GL_TRIANGLES, mIndexCount, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(mPositionAttribute);
glDisableVertexAttribArray(mNormalAttribute);
// this is where the error is detected
OpenGlHelper.checkGLError(TAG, "After draw");
}
Here the method which is used for initialization:
public void createOnGlThread(Context context) throws IOException {
InputStream objInputStream = context.getAssets()
.open(OBJ_ASSET_NAME);
Obj obj = ObjReader.read(objInputStream);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer wideIndices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
FloatBuffer normals = ObjData.getNormals(obj);
ShortBuffer indices = ByteBuffer.allocateDirect(2 * wideIndices.limit())
.order(ByteOrder.nativeOrder()).asShortBuffer();
while (wideIndices.hasRemaining()) {
indices.put((short) wideIndices.get());
}
indices.rewind();
int[] buffers = new int[2];
glGenBuffers(2, buffers, 0);
mVertexBufferId = buffers[0];
mIndexBufferId = buffers[1];
// Load vertex buffer
mVerticesBaseAddress = 0;
mTexCoordsBaseAddress = mVerticesBaseAddress + 4 * vertices.limit();
mNormalsBaseAddress = mTexCoordsBaseAddress + 4 * texCoords.limit();
final int totalBytes = mNormalsBaseAddress + 4 * normals.limit();
glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId);
glBufferData(GL_ARRAY_BUFFER, totalBytes, null, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, mVerticesBaseAddress,
4 * vertices.limit(), vertices);
glBufferSubData(GL_ARRAY_BUFFER, mTexCoordsBaseAddress,
4 * texCoords.limit(), texCoords);
glBufferSubData(GL_ARRAY_BUFFER, mNormalsBaseAddress,
4 * normals.limit(), normals);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Load index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBufferId);
mIndexCount = indices.limit();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 2 * mIndexCount,
indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
OpenGlHelper.checkGLError(TAG, "OBJ buffer load");
mProgram = glCreateProgram();
glAttachShader(mProgram, OpenGlHelper.loadGLShader(TAG, context,
GL_VERTEX_SHADER, R.raw.sphere_vertex));
glAttachShader(mProgram, OpenGlHelper.loadGLShader(TAG, context,
GL_FRAGMENT_SHADER, R.raw.sphere_fragment));
glLinkProgram(mProgram);
glUseProgram(mProgram);
OpenGlHelper.checkGLError(TAG, "Program creation");
mModelViewUniform = glGetUniformLocation(mProgram, "u_ModelView");
mModelViewProjectionUniform =
glGetUniformLocation(mProgram, "u_ModelViewProjection");
mPositionAttribute = glGetAttribLocation(mProgram, "a_Position");
mNormalAttribute = glGetAttribLocation(mProgram, "a_Normal");
OpenGlHelper.checkGLError(TAG, "Program parameters");
setIdentityM(mModelMatrix, 0);
}
I am trying to create a triangle in OpenGL ES. But app is crashing for line gl.glDrawElements(GL10.GL_TRIANGLES, pIndex.length, GL10.GL_UNSIGNED_SHORT, pBuff); in below code inside draw method.
public class GLTriangleEx {
private float vertices[] = {
0f, 1f, // point 0
1f, -1f, // point 1
-1f, -1f // point 2
};
private FloatBuffer vertBuff;
private short[] pIndex = {0, 1, 2};
private ShortBuffer pBuff;
public GLTriangleEx() {
ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length * 4);
bBuff.order(ByteOrder.nativeOrder());
vertBuff = bBuff.asFloatBuffer();
vertBuff.put(vertices);
vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
pBuff = pbBuff.asShortBuffer();
pBuff.put(pIndex);
pbBuff.position(0);
}
public void draw(GL10 gl){
gl.glFrontFace(GL10.GL_CW);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertBuff);
// app crashes here.
gl.glDrawElements(GL10.GL_TRIANGLES, pIndex.length, GL10.GL_UNSIGNED_SHORT, pBuff);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
Crash log cat is
java.lang.ArrayIndexOutOfBoundsException: remaining() < count < needed
at com.google.android.gles_jni.GLImpl.glDrawElements(Native Method)
at com.mobility.opengleslearning.GLTriangleEx.draw(GLTriangleEx.java:45)
at com.mobility.opengleslearning.GLRenderer.onDrawFrame(GLRenderer.java:38)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
I have checked below links for help but of no use for my case:
Android OpenGL error: "remaining() < needed" and Android 4.4
Beginning to learn OpenGL ES. Drawing quad
You need to rewind the ShortBuffer you use for the indices. In this code:
ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
pBuff = pbBuff.asShortBuffer();
pBuff.put(pIndex);
pbBuff.position(0);
you're rewinding pbBuff, which is the underlying ByteBuffer.
asShortBuffer() returns a view buffer that shares the underlying data with the original buffer. From the documentation (emphasis added by me):
A view buffer is simply another buffer whose content is backed by the byte buffer. Changes to the byte buffer's content will be visible in the view buffer, and vice versa; the two buffers' position, limit, and mark values are independent.
So pBuff, which is your view buffer, has its own position. You need to rewind the view buffer, which is the buffer you use later:
pBuff.position(0);
I'm using gstreamer to retrieve a video feed (sent from a RaspPi), and I need to display it into Google Cardboard.
I based my work on the tutorial-3 example of gstreamer. I managed to display my video into a SurfaceView, by giving my Surface (retrieved from SurfaceView.SurfaceHolder.getSurface(), but I now need to connect it with the Google Cardboard.
If I do not mistake, Google Cardboard relies on some SurfaceTexture. So I thought it would be easy to simply get the Surface from the SurfaceTexture using the Surface(SurfaceTexture) constructor.
The problem is that it simply doesn't work. My Google cardboard application Cardboard Pasthrough example, and I haven't touched the OpenGL code, since I don't know anything about it.
While debugging, I found out that there is (at least) one problem with the code I'm using. It seems that the line
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
are causing me some trouble since GL_TEXTURE_EXTERNAL_OES isn't in the required range for the glActiveTexture methods (which requires a GL from 0 to GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS).
Here are my logs :
GLConsumer W [unnamed-12520-0] bindTextureImage: clearing GL error: 0x500
Adreno-ES20 W <core_glActiveTexture:348>: GL_INVALID_ENUM
So what's working right now ?
It seems that the video feed is received by gstreamer, that tries to update the Surface (I get some notifications about the onFrameAvailable of the SurfaceTexture that are being updated, and the error logs are only sent since there). However, the screens stays black, as if nothing is updated.
Here are the most interesting parts of my code :
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CardboardView cardboardView = (CardboardView) findViewById(R.id.cardboard_view);
cardboardView.setRenderer(this);
setCardboardView(cardboardView);
// Initialize GStreamer and warn if it fails
try {
GStreamer.init(this);
} catch (Exception e) {
//Catch e...
}
mCamera = new float[16];
mView = new float[16];
mHeadView = new float[16];
//gstreamer stuff
nativeInit();
}
#Override
public void onSurfaceCreated(EGLConfig eglConfig) {
Log.d(TAG, "onSurfaceCreated start");
GLES20.glClearColor(0.5f, 0.1f, 0.1f, 0.5f);
ByteBuffer bb = ByteBuffer.allocateDirect(squareVertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareVertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
ByteBuffer bb2 = ByteBuffer.allocateDirect(textureVertices.length * 4);
bb2.order(ByteOrder.nativeOrder());
textureVerticesBuffer = bb2.asFloatBuffer();
textureVerticesBuffer.put(textureVertices);
textureVerticesBuffer.position(0);
int vertexShader = loadGLShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadGLShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram);
checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
Log.d(TAG, "Surface created");
texture = createTexture();
initSurface(texture);
}
static private int createTexture()
{
Log.d(TAG + "_cardboard", "createTexture");
int[] texture = new int[1];
GLES20.glGenTextures(1,texture, 0);
checkGLError("GenTextures Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture[0]);
checkGLError("BindTextures Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
return texture[0];
}
//Give the surface to gstreamer.
private void initSurface(int texture) {
mSurface = new SurfaceTexture(texture);
mSurface.setOnFrameAvailableListener(this);
Log.d(TAG, "OnFrameAvailableListener set");
Surface toto = new Surface(mSurface);
nativeSurfaceInit(toto);
toto.release();
}
//When we need to render
#Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
Log.d(TAG, "onFrameAvailable");
this.getCardboardView().requestRender();
}
//Display to cardboard
#Override
public void onNewFrame(HeadTransform headTransform) {
headTransform.getHeadView(mHeadView, 0);
// Build the camera matrix and apply it to the ModelView.
Matrix.setLookAtM(mCamera, 0, 0.0f, 0.0f, 0.01f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
float[] mtx = new float[16];
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
mSurface.updateTexImage();
mSurface.getTransformMatrix(mtx);
float[] test = new float[3];
headTransform.getEulerAngles(test, 0);
//if(networkThread != null){
// networkThread.setRegValue(test);
//}
}
#Override
public void onDrawEye(Eye eye) {
// Log.d(TAG, "onDrawEye");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
Log.d(TAG, "trying to access " + GL_TEXTURE_EXTERNAL_OES +" out of " + GLES20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
GLES20.glActiveTexture(GL_TEXTURE_EXTERNAL_OES);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "position");
GLES20.glEnableVertexAttribArray(mPositionHandle);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, vertexStride, vertexBuffer);
// checkGLError("Problem on line "+new Throwable().getStackTrace()[0].getLineNumber());
mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "inputTextureCoordinate");
GLES20.glEnableVertexAttribArray(mTextureCoordHandle);
GLES20.glVertexAttribPointer(mTextureCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
false, vertexStride, textureVerticesBuffer);
mColorHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTextureCoordHandle);
Matrix.multiplyMM(mView, 0, eye.getEyeView(), 0, mCamera, 0);
}
For more code, here is a gist with the main two files : https://gist.github.com/MagicMicky/4caa3ac669215652e40f
edit: When trying to work with the camera app on gstreamer, the same errors are shown in the logcat as the one I described earlier. So this might be nothing of importance...
My program does:
Load texture to GPU.
Load VBO of uv coordinates to GPU.
Load VBO of mode coordinates to GPU.
Load VBO of indeces to GPU.
Bind to texture.
Bind to uv coordinates VBO.
Bind to model coordinates VBO.
Bind to index coordiantes VBO.
DRAW
But only part of each texture is actually drawn. If I use all of the same arrays and draw without VBO's (move from client side each draw) it draws fine.....
Any ideas? Been scratching me head for a couple hours now.
I have posted relevant code below:
LOAD TO GPU:
this.texture = new int[1];
GLES20.glGenTextures(1, this.texture, 0);
//GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texture[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
// Generate VBOs for UV data and model data. My indece VBO is done elswhere
this.vbo = new int[2];
GLES20.glGenBuffers(2,vbo,0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[0] );
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, uvsBuff.capacity() * FH_Utilities.SHORT_SIZE,
uvsBuff, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, posBuff.capacity() * FH_Utilities.SHORT_SIZE,
posBuff, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
DRAWING:
GLES20.glUseProgram(this.terrainShader.mProgram);
int mtrxhandle = GLES20.glGetUniformLocation(this.terrainShader.mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, mvpMatrix, 0);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texture[0]);
int mSamplerLoc = GLES20.glGetUniformLocation (this.terrainShader.mProgram, "s_texture" );
GLES20.glUniform1i ( mSamplerLoc, 0);
int mTexCoordLoc = GLES20.glGetAttribLocation(this.terrainShader.mProgram, "a_texCoord");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[0]);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
GLES20.glVertexAttribPointer(mTexCoordLoc, 2,
GLES20.GL_SHORT, false,
0, 0);
int mPositionHandle = GLES20.glGetAttribLocation(this.terrainShader.mProgram, "vPosition");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.vbo[1]);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_SHORT, false, 0, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, this.drawHandles[0][0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, this.drawHandles[0][1], GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
GENERATE INDECES:
private int[][] genIndeces(int tileSize, int Nindexes){
int[][] indeceHandles = new int[Nindexes][2];
int indMaxLen = ((tileSize-1) * ((tileSize*2) +2))-2;
int indMaxBytes = indMaxLen * FH_Utilities.SHORT_SIZE;
short[][] index = new short[tileSize][tileSize];
short[] IDA = new short[indMaxLen];
ByteBuffer bInd;
int nIndeces;
int x,y;
/* Build an Indece Buffer for course triangle strips */
nIndeces = 0;
for(y=0;y<tileSize;y++){
for(x=0;x<tileSize;x++){
index[y][x] = (short)nIndeces;
nIndeces++;
}
}
/*Run through however many resolutions desired */
bInd = ByteBuffer.allocateDirect(indMaxBytes).order(ByteOrder.nativeOrder());
ShortBuffer sInd = bInd.asShortBuffer();
nIndeces=0;
for(y=0;y<tileSize-1;y++){
for(x=0;x<tileSize;x++){
IDA[nIndeces] = index[y+1][x];
nIndeces++;
IDA[nIndeces] = index[y][x];
nIndeces++;
if(x==tileSize-1 && y != tileSize -2) {
IDA[nIndeces] = index[y][x];
nIndeces++;
IDA[nIndeces] = index[y+2][0];
nIndeces++;
}
}
}
sInd.clear();
sInd.put(IDA, 0, nIndeces);
sInd.position(0);
int tempHandle[] = new int[1];
GLES20.glGenBuffers(1,tempHandle,0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, tempHandle[0]);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, sInd.capacity() * FH_Utilities.SHORT_SIZE, sInd, GLES20.GL_STATIC_DRAW);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if(GLES20.glGetError()!=GLES20.GL_NO_ERROR){
System.out.println("FH_ERROR- "+GLES20.glGetError());
System.exit(1);
}
indeceHandles[0][0] = tempHandle[0];
indeceHandles[0][1] = nIndeces;
bInd.limit(0);
sInd.limit(0);
bInd=null;
sInd=null;
IDA=null;
index=null;
System.gc();
return indeceHandles;
}
Currently I am working on a 3D Game Engine for Android. The Project is just at the beginning, but there is a problem I cant' solve.
I want to use VertexBufferObjects for rendering the models loaded form an .obj file.
Here is the code
public class Mesh {
private final int mBytesPerFloat = 4;
private FloatBuffer vertices;
private FloatBuffer normals;
private IntBuffer faces;
private int vertexBuffer;
private int normalBuffer;
private int indexBuffer;
public Mesh(float[] vertices, float[] normals, int[] faces, int shaderProgram) {
this.normals = ByteBuffer.allocateDirect(normals.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
this.normals.put(normals).position(0);
this.faces = ByteBuffer.allocateDirect(faces.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asIntBuffer();
this.faces.put(faces).position(0);
this.vertices = ByteBuffer.allocateDirect(vertices.length * mBytesPerFloat)
.order(ByteOrder.nativeOrder())
.asFloatBuffer();
this.vertices.put(vertices).position(0);
ByteBuffer bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
IntBuffer buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
vertexBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, this.vertices.capacity() * mBytesPerFloat, this.vertices, GLES20.GL_STATIC_DRAW);
bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
normalBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normalBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, this.normals.capacity() * mBytesPerFloat, this.normals, GLES20.GL_STATIC_DRAW);
bb = ByteBuffer.allocateDirect(8);
bb.order(ByteOrder.nativeOrder());
buffer = bb.asIntBuffer();
GLES20.glGenBuffers(1, buffer);
indexBuffer = buffer.get(0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, this.faces.capacity() * mBytesPerFloat, this.faces, GLES20.GL_STATIC_DRAW);
}
public Mesh() {
// TODO Auto-generated constructor stub
}
public void render(int shaderProgram) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBuffer);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(shaderProgram, "vertex"), 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(shaderProgram, "vertex"));
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normalBuffer);
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(shaderProgram, "normal"), 3, GLES20.GL_FLOAT, false, 0, 0);
GLES20.glEnableVertexAttribArray(GLES20.glGetAttribLocation(shaderProgram, "normal"));
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, vertices.capacity()/3, GLES20.GL_INT, faces);
}
}
The problem is that I do not see anything.
The problem is not the shader i am using (which I know is working correctly) and the modelview matrix and projection matrix are correct, so the object should be visible, if it is rendered which it isn't.
Has anyone an idea what the problem might be?
It doesn't seem like glDrawElements accepts GL_INT as data type, so maybe the glDrawElements call just fails (which could have easily been checking with some simple glGetError calls for the sake of debugging). Just try GL_UNSIGNED_INT instead (and maybe a UIntBuffer for faces or something similar, if that exists).
Maybe it doesn't even have GL_UNSIGNED_INT in ES and you need 2-byte GL_UNSIGNED_SHORTs, but I'm not sure about that. But you definitely need an unsigned type (what sense does a signed type make for indices anyway? But ok, that's Java). Anyway, some glGetErrors might do wonders here.