android developers! I'm in trouble. My android app has to draw a few lines using OpenGL. I started off with this as example and rewrote it. It throws up the IllegalArgumentException: must use a native order direct Buffer when calling GLES20.glVertexAttribPointer. I don't understand why, since I set it to the nativeorder, like in the example I used. Here's my complete OpenGLRenderer class: (I use the second constructor with the float[] parameter when creating an instance of this class)
public class OpenGLRenderer implements GLSurfaceView.Renderer {
final int COORDS_PER_VERTEX = 3;
final int NR_OF_LINES;
final int NR_OF_VERTECES;
final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
final int NR_OF_VERTECES_PER_LINE = 2;
final int BYTES_PER_VERTEX = 4;
private FloatBuffer bufferVertecesLines;
private float[] arrayVertecesLines;
//private FloatBuffer ColorBuffer;
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.3f, 0.7f, 0.2f, 1.0f };
private int GlProgram;
private int PositionHandle;
private int ColorHandle;
//SHADERS----------------------------------------------------------------------------------------------------------------------------
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
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String FragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
//CONSTRUCTOR----------------------------------------------------------------------------------------------------------------------------
public OpenGLRenderer(FloatBuffer thisLineVertexBuffer, int numberoflines)
{
bufferVertecesLines = thisLineVertexBuffer;
NR_OF_VERTECES = numberoflines * 2;
NR_OF_LINES = numberoflines;
Log.v("Leen","mijn eigen logje - OpenGLRenderer - Constructor");
}
public OpenGLRenderer(float[] thisLineVertexArray)
{
arrayVertecesLines = thisLineVertexArray;
NR_OF_VERTECES = thisLineVertexArray.length / COORDS_PER_VERTEX;
NR_OF_LINES = thisLineVertexArray.length / COORDS_PER_VERTEX / NR_OF_VERTECES_PER_LINE;
}
private void convertArrayToBuffer()
{
int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
// in voorbeeld:
// NrOfBytes = 2 * 2 * 3 * 4 = 48
ByteBuffer bb = ByteBuffer.allocate(NrOfBytes);
bb.order(ByteOrder.nativeOrder());
bufferVertecesLines = bb.asFloatBuffer();
bufferVertecesLines.put(arrayVertecesLines);
}
//---------------------------------------------------------------------------------------------------------------------------------------
@Override
public void onSurfaceChanged(GL10 unused, int width, int height)
{
// Adjust the viewport based on geometry changes,
// such as screen rotation
GLES20.glViewport(0, 0, width, height);
}
//---------------------------------------------------------------------------------------------------------------------------------------
@Override
public void onDrawFrame(GL10 arg0)
{
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
GlProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(GlProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(GlProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(GlProgram); // creates OpenGL ES program executables
this.drawAllLines();
}
//---------------------------------------------------------------------------------------------------------------------------------------
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config)
{
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
//---------------------------------------------------------------------------------------------------------------------------------------
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 drawAllLines()
{
// Add program to OpenGL ES environment
GLES20.glUseProgram(GlProgram);
// get handle to vertex shader's vPosition member
PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(PositionHandle);
// Prepare the Line coordinate data
// vertexstride = offset. 3 coordinaten per vertex * 4 bytes per vertex = 12
this.convertArrayToBuffer();
GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
VertexStride, bufferVertecesLines);
// get handle to fragment shader's vColor member
ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(ColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_LINES, 0, NR_OF_VERTECES);
// Disable vertex array
GLES20.glDisableVertexAttribArray(PositionHandle);
}
}
OK, found it. I didn't use the ByteBuffer.allocate()
method, but the ByteBuffer.allocateDirect()
- method. This piece is throwing no exceptions:
private void convertArrayToBuffer()
{
int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
// in voorbeeld:
// NrOfBytes = 2 * 2 * 3 * 4 = 48
ByteBuffer bb = ByteBuffer.allocateDirect(NrOfBytes); //!!!!!!!!!!
bb.order(ByteOrder.nativeOrder());
bufferVertecesLines = bb.asFloatBuffer();
bufferVertecesLines.put(arrayVertecesLines);
bb.position(0);
bufferVertecesLines.position(0);
}
private void convertArrayToBuffer()
{
int NrOfBytes = NR_OF_LINES * NR_OF_VERTECES_PER_LINE * COORDS_PER_VERTEX * BYTES_PER_VERTEX;
// in voorbeeld:
// NrOfBytes = 2 * 2 * 3 * 4 = 48
ByteBuffer bb = ByteBuffer.allocate(NrOfBytes);
bb.order(ByteOrder.nativeOrder());
bufferVertecesLines = bb.asFloatBuffer();
bufferVertecesLines.put(arrayVertecesLines);
bb.position(0); //!!!!!!!!!!!!!
bufferVertecesLines.position(0);//!!!!!!!!!!!!!
}
I have encountered the same problem, and I find the answer at enter link description here. use allocateDirect instead of allocate, the bb needs to be direct so it isn't move around the memeory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With