android开发者!我有麻烦了。我的Android应用程序必须使用OpenGL绘制几行。我以this为例开始重写。它抛出了IllegalArgumentException:在调用GLES20.glVertexAttribPointer时必须使用本机命令直接缓冲区。我不明白为什么,因为我把它设置为本机顺序,就像我使用的例子。这是我完整的OpenGLRenderer类:(在创建此类的实例时,我使用带有float []参数的第二个构造函数)
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);
}
}
好的,找到了。我没有使用ByteBuffer.allocate()
方法,而是使用ByteBuffer.allocateDirect()
方法。这篇文章没有例外:
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);//!!!!!!!!!!!!!
}
我遇到了同样的问题,我在enter link description here找到答案。使用allocateDirect而不是allocate,bb需要是直接的,所以它不会在memeory周围移动。