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.
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 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);
I am having trouble rendering a quad in Android with OpenGL ES 2.0 using VBOs.
For some reason when I run the program, it crashes the emulator. I am using Andy for the emulator. I have tried using the default emulator that comes with android, and in this case the app simply won't run. I am using eclipse as my ide.
I have managed to narrow down the problem to the render method of the Quad class.
I guess I am wondering is there a problem with the way I am setting up the VBOs and rendering them?
Here is my code:
Quad render method:
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
public void render()
{
mat.useMaterial();
GLES20.glFrontFace(GLES20.GL_CW);
//Generate VBO Buffer Handles and assign it to 'buffers'
GLES20.glGenBuffers(4, buffers, 0);
GLES20.glGenBuffers(1, ibo, 0);
//Positions
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glEnableVertexAttribArray(0);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
//GLES10.glVertexPointer(3, GLES10.GL_FLOAT, 0, vertexBuffer);
//Normals
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[1]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, normalBuffer.capacity() * 4, normalBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glEnableVertexAttribArray(1);
GLES20.glVertexAttribPointer(1, 3, GLES20.GL_FLOAT, false, 0, normalBuffer);
//GLES10.glNormalPointer(GLES10.GL_FLOAT, 0, normalBuffer);
//Texcoords
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[2]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, texcoordBuffer.capacity() * 4, texcoordBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glEnableVertexAttribArray(2);
GLES20.glVertexAttribPointer(2, 2, GLES20.GL_FLOAT, false, 0, texcoordBuffer);
//GLES10.glTexCoordPointer(2, GLES10.GL_FLOAT, 0, texcoordBuffer);
//Colors
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[3]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, colorBuffer.capacity() * 4, colorBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glEnableVertexAttribArray(3);
GLES20.glVertexAttribPointer(3, 4, GLES20.GL_FLOAT, false, 0, colorBuffer);
//GLES10.glColorPointer(4, GLES10.GL_FLOAT, 0, colorBuffer);
//Indices
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * 4, indexBuffer, GLES20.GL_STATIC_DRAW);
//Draw
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexBuffer.capacity(), GLES20.GL_UNSIGNED_INT, indexBuffer);
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertices.length / 3);
//Unbind buffers
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
Also here is the Material class:
package com.game.shading;
import android.opengl.GLES20;
public class Material
{
private final String vertexShaderCode =
"attribute vec3 vPosition;" +
"attribute vec3 vNormal;" +
"attribute vec2 vTexcoord" +
"" +
"void main()" +
"{" +
" gl_Position = vec4(vPosition, 0);" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"" +
"void main()" +
"{" +
" gl_FragColor = vColor;" +
"}";
private int vertShader;
private int fragShader;
private int shaderProgram;
public Material()
{
vertShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
fragShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
shaderProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(shaderProgram, vertShader);
GLES20.glAttachShader(shaderProgram, fragShader);
GLES20.glLinkProgram(shaderProgram);
}
public void useMaterial()
{
GLES20.glUseProgram(shaderProgram);
}
public void cleanupMaterial()
{
GLES20.glDetachShader(shaderProgram, vertShader);
GLES20.glDetachShader(shaderProgram, fragShader);
GLES20.glDeleteShader(vertShader);
GLES20.glDeleteShader(fragShader);
GLES20.glDeleteProgram(shaderProgram);
}
private int loadShader(int type, String source)
{
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
return shader;
}
}
You have a problem with the way you set up the attributes. Taking one of them as an example (the same thing applies to all of them, as well as the index buffer):
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer.capacity() * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
In ES 2.0, there are two variations of the glVertexAttribPointer() call. They have different signatures in the Java bindings:
One of them takes a Buffer as the last argument. It is used to specify that the vertex data should be pulled directly from the memory of the buffer passed in. This is commonly called a "client side vertex array".
The other one takes an int as the last argument. It is used for attribute values stored in a VBO. The argument is then an offset relative to the start of the VBO.
You're using the first version of the call, while you have in fact a VBO bound. In this case, you need to use the second version. Since your attribute data starts at the beginning of the VBO, the offset value is 0:
GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, 0);
Then correct the same problem for the other attributes and the indices.
I also don't see code that associates the vertex attribute locations with the attributes in the vertex shader. One option to add that is to use glBindAttribLocation() calls before linking the program.
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;
}