我无法找到有关在JOGL中渲染交错顶点数组(而不是VBO)的正确方法的任何信息。具体来说,使用glVertexAttribPointer()似乎不允许在交错数据(FloatBuffer)中指定偏移量。在C,C ++或Objective-C中,我确切地知道如何做到这一点,但在Java中似乎没有明确的胜利之路。
我尝试过的唯一可能有效的方法是在使用glVertexAttribPointer()之前设置缓冲区的位置,但这没有效果。
为清楚起见,这里是渲染函数中的代码示例:
gl.glEnableVertexAttribArray( POSITION_ATTRIB );
gl.glEnableVertexAttribArray( NORMAL_ATTRIB );
gl.glVertexAttribPointer( POSITION_ATTRIB, 4, GL.GL_FLOAT, false, 32, vertexBuffer );
// vertexBuffer.position( 4 ); if I try to specify an offset
gl.glVertexAttribPointer( NORMAL_ATTRIB, 4, GL.GL_FLOAT, false, 32, vertexBuffer );
gl.glDrawArrays( GL.GL_TRIANGLES, 0, nummy );
gl.glDisableVertexAttribArray( NORMAL_ATTRIB );
gl.glDisableVertexAttribArray( POSITION_ATTRIB );
我为每个属性使用4个浮点数。我选择了基于
的32步每个浮点数4个字节*每个属性4个浮点数*每个顶点2个属性。
答案 0 :(得分:2)
我怀疑设置FloatBuffer位置的原因并不能为您提供所需的行为,因为您通过引用传递了FloatBuffer。您可能想要创建另一个FloatBuffer,它基本上只是相同数据的不同视图(例如,包装一个float [])并将此其他 FloatBuffer中的位置设置为4 ...
例如:
// Somewhere in your class
private float [] verts;
// You can fill this with actual data yourself, I did the hard part :P
verts = new float [] { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
// ^^^^^^^^^ POS ^^^^^^^^ ^^^^^^^ NORMAL ^^^^^^^
//
// When it comes time to supply the vertex pointers, use this:
//
FloatBuffer vtx_base = FloatBuffer.wrap (verts);
FloatBuffer norm_base = FloatBuffer.wrap (verts, 4, verts.length () - 4);
gl.glVertexAttribPointer (POSITION_ATTRIB, 4, GL.GL_FLOAT, false, 32, vtx_base);
gl.glVertexAttribPointer (NORMAL_ATTRIB, 4, GL.GL_FLOAT, false, 32, norm_base);
免责声明:我多年没有使用过Java,所以不要指望它可以直接编译。基本理论应该是合理的。 子>
我不得不怀疑你是否真的需要4D顶点位置和法线? w
有非常实际的用途,但如果你实际上不需要它,可以节省一些存储/带宽并使用3D。我提出这个问题是因为当你使用客户端内存而不是VBO时,会有更多的CPU-> GPU内存传输正在进行,并且每一点尺寸的减小都会有所帮助。
答案 1 :(得分:1)
我有点卡住,所以使用直接缓冲区共享另一个解决方案,如Nathan所提到的OpenGL所需。另外,在这个例子中,我用浮点数和字节/整数交错(颜色表示为4个字节):
// vertex position: 3 floats; vertex color: 4 bytes
static final int COORDS_PER_VERTEX = 4;
static final int VERTS_PER_SPRITE = 4;
static final int MAX_NUM_SPRITES = 1000;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private FloatBuffer vertexBuffer;
private ByteBuffer colorBuffer;
public void init() {
ByteBuffer bb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
COORDS_PER_VERTEX * VERTS_PER_SPRITE * 4 * MAX_NUM_SPRITES);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
bb.position(3 * 4);
colorBuffer = bb.slice();
}
现在,在绘制顶点时,只需执行
public void draw() {
GLES20.glUseProgram(myProgram);
// Enable a handle to the sprite vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glEnableVertexAttribArray(mColorHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GLES20.glVertexAttribPointer(mColorHandle, 4,
GLES20.GL_UNSIGNED_BYTE, false, vertexStride, colorBuffer);
// Draw the sprites GL_SHORT DOES NOT WORK!!!! Use UNSIGNED_SHORT
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6 * numSprites, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
}
当我需要更新缓冲区时,我只准备一个浮点缓冲区,然后将4色字节转换为浮点数,
private void updateSpriteBuffer() {
float[] vData = new float[COORDS_PER_VERTEX * VERTS_PER_SPRITE * MAX_NUM_SPRITES];
for (int i = 0; i<numSprites; i++) {
// ... x, y, z
byte[] colorBytes = sprite.getColorBytes(); // {r, g, b, 1}
float colorAsFloat = ByteBuffer.wrap(colorBytes).order(ByteOrder.nativeOrder()).getFloat();
for (int k = 0; k < 4; k++) {
int j = COORDS_PER_VERTEX * 4 * i + COORDS_PER_VERTEX * k;
vData[j] = x[k];
vData[j + 1] = y[k];
vData[j + 2] = z[k];
vData[j + 3] = colorAsFloat;
}
}
vertexBuffer.put(vData);
vertexBuffer.position(0);
}
我希望这有助于其他人尝试这样做。