具有浮点和字节的交错式 VBO
Posted
技术标签:
【中文标题】具有浮点和字节的交错式 VBO【英文标题】:Interleaved VBO with Float and Byte 【发布时间】:2019-05-21 17:35:39 【问题描述】:我想在交错的 OpenGL vbo 中存储三个浮点值和两个字节值。 不幸的是,渲染的数据显然是不正确的。 当我用两个不同的 VBO 渲染相同的数据时,一切正常,所以我不认为我的着色器有问题。
/*
* 20^3 blocks per chunk, 6 faces per block, 3 vertices per face
* max. every second face can be visible
*/
private static final int MAX_FLOAT_AMOUNT = 20 * 20 * 20 * 6 * 3 / 2;
/*
* 20^3 blocks per chunk, 6 faces per block, 2 bytes per face
* max. every second face can be visible
*/
private static final int MAX_BYTE_AMOUNT = 20 * 20 * 20 * 6 * 2 / 2;
private int dataVboIndex;
protected int vaoId;
protected int indicesCount;
protected boolean isInitialized = false;
public static ByteBuffer dataFloatBuffer = BufferUtils.createByteBuffer(4 * MAX_FLOAT_AMOUNT + MAX_BYTE_AMOUNT);
DefaultChunkVao(int indiciesVboId)
init();
DefaultChunkVao(boolean initialize)
if(initialize) init();
private void init()
isInitialized = true;
// bind vao
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
//create vbo
dataVboIndex = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, dataVboIndex);
dataFloatBuffer.clear();
dataFloatBuffer.position(4 * MAX_FLOAT_AMOUNT + MAX_BYTE_AMOUNT);
dataFloatBuffer.flip();
// allocate memory
glBufferData(GL_ARRAY_BUFFER, dataFloatBuffer, GL_STREAM_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4 + 2, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_UNSIGNED_BYTE, false, 3 * 4 + 2, 3 * 4);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_UNSIGNED_BYTE, false, 3 * 4 + 2, 3 * 4 + 1);
// unbind vao
glBindVertexArray(0);
public void updateData(float[] data)
if(!isInitialized) init();
dataFloatBuffer.clear();
for(int counter = 0; counter < data.length; counter+=0)
dataFloatBuffer.putFloat(data[counter++]);
dataFloatBuffer.putFloat(data[counter++]);
dataFloatBuffer.putFloat(data[counter++]);
dataFloatBuffer.put((byte) data[counter++]);
dataFloatBuffer.put((byte) data[counter++]);
dataFloatBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, dataVboIndex);
glBufferSubData(GL_ARRAY_BUFFER, 0, dataFloatBuffer);
glBindBuffer(GL_ARRAY_BUFFER, 0);
this.indicesCount = data.length / 5;
MAX_FLOAT_AMOUNT
和 MAX_BYTE_AMOUNT
常量分别包含浮点数。每个 VBO 的字节数。当我确定ByteBuffer
的容量时,我是否假设我必须将浮点数乘以 4,因为每个浮点数都有 4 个字节?
在着色器中我的字节值始终为 0,我做错了什么?
编辑:我能够通过一个更简单的示例重现该问题。这里我想在 VBO 中存储位置和两个字节。在片段着色器中,我检查是否正确传递了 byte1 值。如果是这样,着色器将形状渲染为绿色,否则为蓝色。不幸的是,我的形状呈现为蓝色,因此我假设 byte1 值未正确传递。
顶点着色器
#version 400 core
in vec3 position;
in int byte1;
in int byte2;
flat out int p_byte1;
flat out int p_byte2;
void main(void)
gl_Position = vec4(position, 1);
p_byte1 = byte1;
p_byte2 = byte2;
fragmentShader:
#version 400 core
flat in int p_byte1;
flat in int p_byte2;
out vec3 out_color;
void main(void)
if(p_byte1 == 45)
out_color = vec3(0, 1, 0);
else out_color = vec3(0, 0, 1);
创建 VAO:
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
final int vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
float[] data = 0, 0, 0, 20f, 20f, 1, 1, 1, 20f, 20f, 1, 0, 1, 20f, 20f, 0, 1, 1, 20f, 20f;
ByteBuffer dataBuffer = BufferUtils.createByteBuffer(4 * (3 * 4) + 1 * (2 * 4));
for(int counter = 0; counter < data.length; counter+=0)
dataBuffer.putFloat(data[counter++]);
dataBuffer.putFloat(data[counter++]);
dataBuffer.putFloat(data[counter++]);
dataBuffer.put((byte) data[counter++]);
dataBuffer.put((byte) data[counter++]);
dataBuffer.flip();
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STREAM_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4 + 2, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_UNSIGNED_BYTE, false, 3 * 4 + 2, 3 * 4);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_UNSIGNED_BYTE, false, 3 * 4 + 2, 3 * 4 + 1);
glBindVertexArray(0);
【问题讨论】:
显示float[] data
数组中的数据示例。您将浮点值转换为字节,这将导致开区间 [0, 1) 中的所有浮点值成为字节 0。同时显示着色器。
***.com/questions/26316179/… 这个答案有很多关于在字节缓冲区中使用浮点数的有用信息
@httpdigest 演员表不是问题,因为当我用counter++; .put((byte) 45);
替换.put((byte) data[counter++]);
时,问题仍然存在。但是,当我在顶点着色器中将 VAO 的值替换为 45 时,问题不会发生。
那么顶点着色器看起来如何?您没有在着色器中使用整数 inout 属性类型,对吗?
我在我的问题中发布了一个示例。
【参考方案1】:
我能够找到我的问题的解决方案。对于整数数据类型,必须使用glVertexAttribIPointer
而不是glVertexAttribPointer
。
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4 + 2, 0);
glEnableVertexAttribArray(1);
glVertexAttribIPointer(1, 1, GL_UNSIGNED_BYTE, 3 * 4 + 2, 3 * 4);
glEnableVertexAttribArray(2);
glVertexAttribIPointer(2, 1, GL_UNSIGNED_BYTE, 3 * 4 + 2, 3 * 4 + 1);
【讨论】:
以上是关于具有浮点和字节的交错式 VBO的主要内容,如果未能解决你的问题,请参考以下文章