gpt4 book ai didi

android - Android 上的 OpenGL ES 2 : how to use VBOs

转载 作者:行者123 更新时间:2023-11-29 16:00:18 26 4
gpt4 key购买 nike

这个问题类似于我在这里问的问题 Android OpenGL ES 2: Introduction to VBOs但是从那以后我尝试了多种方法但我仍然没有成功,所以我认为发布另一个问题我提供额外的细节将是一个更好的方法。

我是 Android 上 OpenGL ES 2 的新手(我从未使用过其他 OpenGL,我只需要为我正在为 Android 开发的应用程序绘制一些东西)并且我非常想了解如何使用 VBO。我试图修改这个 OpenGL ES 2 for Android tutorial绘制三角形时使用 VBO。我尝试使用 this step by step guidethis tutorial但我仍然不了解所有这些事情,我对所有这些事情都很陌生。我的应用程序目前在启动时崩溃。这是我拥有的:

public class Triangle {

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;" +
"}";

private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";

private final FloatBuffer vertexBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private final int buffer[] = new int[1];

// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = {
// in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex

float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };

/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());

// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);

// First, generate as many buffers as we need.
// This will give us the OpenGL handles for these buffers.

GLES20.glGenBuffers(1, buffer, 0);

// prepare shaders and OpenGL program
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables

}

/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
* @param mvpMatrix - The Model View Project matrix in which to draw
* this shape.
*/
public void draw(float[] mvpMatrix) {


// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");

// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);

// get handle to shape's transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");

// get handle to vertex shader's vPosition member
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");



//these I don't fully understand
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffer[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,vertexBuffer.capacity() * 4,vertexBuffer,GLES20.GL_STATIC_DRAW);

// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);


// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);

// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, 0);




// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");

// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);

// //is this still necesary? or do i have to use glDeleteBuffers?
// GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}

}

当我在 glVertexAttribPointer() 中放置 0 而不是 vertexBuffer 时,我收到一条错误消息,提示我没有提供必要的参数:expected parameter: ptr: java.nio.缓冲区;实参:0(int)

最佳答案

由于数据指针的使用,到 VBO 的转换可能有点奇怪。

通过快速检查,您的主要问题在于

GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);

应该是这样

 GLES20.glVertexAttribPointer(
mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, 0);

关于缓冲区:VBO 是 GPU 上的自定义缓冲区,通常用于和优化以将顶点数据直接存储到 GPU。这样做获得的性能是顶点数据不需要在每次绘制调用时都复制到 GPU。

这些缓冲区仍然是自定义的,在生成它们时,您需要设置的只是它们的大小。我看到您在假设浮点值的大小为 4 字节的情况下在顶点计数上使用因子 *4,这不是最好的主意,因为这可能并不总是正确的。如果可能,总是尝试使用某种形式的“sizeOf”。无论如何,您的缓冲区已正确创建并且数据已发送到它。

数据发送到 IBO 后,您应该将它们保存在那里直到您需要它们。这意味着您通常为每个唯一对象(例如一个正方形)创建一个 VBO,然后只保存它的 ID。每当你想绘制它时,你只需简单地绑定(bind)缓冲区并像你所做的那样绘制。换句话说,缓冲区不应该在 draw 方法中创建。你在那里所做的也有内存泄漏,因为你负责在不再需要缓冲区时通过调用 delete 来释放缓冲区。

关于 glVertexAttribPointer 上的指针问题:有两种方法可以使用此方法。如果没有 VBO,最后一个参数是指向 CPU 上数据的指针。使用 VBO,您需要将其设置为 VBO 内的相对指针。这意味着当 VBO 被绑定(bind)时,缓冲区的开头将为 NULL (0),您甚至可能需要对该值进行类型转换。对于缓冲区中的其他位置,您需要手动计算它们。

以及您具体发布的代码:

    // First, generate as many buffers as we need.
// This will give us the OpenGL handles for these buffers.
final int buffer[] = new int[1];
GLES20.glGenBuffers(1, buffer, 0);

//these I don't fully understand
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffer[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,vertexBuffer.capacity() * 4,vertexBuffer,GLES20.GL_STATIC_DRAW);

这一切都会进入一些加载时间并引用 buffer[] 除了你应该添加 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 什么此调用的作用是解除绑定(bind) 缓冲区。这不是您需要做的事情,但您最好这样做,这样您就不会混淆绑定(bind)的缓冲区(如果有的话)。

在调用 glVertexAttribPointer 之前,您需要绑定(bind)缓冲区。然后如上所述设置最后一个参数。

在你使用完这个缓冲区(完成绘图)后,你应该(同样没有必要)解除绑定(bind)缓冲区。

关于android - Android 上的 OpenGL ES 2 : how to use VBOs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25053786/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com