Opengl - 实例化属性
Opengl - instanced attributes
我使用 oglplus - 它是 OpenGL 的 c++ 包装器。
我在为我的粒子渲染器定义实例化数据时遇到问题 - 位置工作正常,但当我想从同一个 VBO 实例化一堆整数时出现问题。
我将跳过一些实现细节,以免使这个问题变得更复杂。假设我在描述的操作之前绑定了 VAO 和 VBO。
我有一个结构数组(称为 "Particle"),我是这样上传的:
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle) * numInstances, newData, GL_DYNAMIC_DRAW);
结构定义:
struct Particle
{
float3 position;
//some more attributes, 9 floats in total
//(...)
int fluidID;
};
我使用辅助函数来定义 OpenGL 属性,如下所示:
void addInstancedAttrib(const InstancedAttribDescriptor& attribDesc, GLSLProgram& program, int offset=0)
{
//binding and some implementation details
//(...)
oglplus::VertexArrayAttrib attrib(program, attribDesc.getName().c_str());
attrib.Pointer(attribDesc.getPerVertVals(), attribDesc.getType(), false, sizeof(Particle), (void*)offset);
attrib.Divisor(1);
attrib.Enable();
}
我像这样为位置和流体添加属性:
InstancedAttribDescriptor posDesc(3, "InstanceTranslation", oglplus::DataType::Float);
this->instancedData.addInstancedAttrib(posDesc, this->program);
InstancedAttribDescriptor fluidDesc(1, "FluidID", oglplus::DataType::Int);
this->instancedData.addInstancedAttrib(fluidDesc, this->program, (int)offsetof(Particle,fluidID));
顶点着色器代码:
uniform vec3 FluidColors[2];
in vec3 InstanceTranslation;
in vec3 VertexPosition;
in vec3 n;
in int FluidID;
out float lightIntensity;
out vec3 sphereColor;
void main()
{
//some typical MVP transformations
//(...)
sphereColor = FluidColors[FluidID];
gl_Position = projection * vertexPosEye;
}
此代码整体产生此输出:
如您所见,粒子按照我希望的方式排列,这意味着 "InstanceTranslation" 属性 设置正确。左侧粒子组的 FluidID 值为 0,右侧粒子组的 FluidID 值为 1。第二组粒子具有正确的位置,但在 FluidColors 数组中的索引不正确。
我知道的:
我设置 FluidColors 制服的方式没有问题。如果我像这样在着色器中硬编码颜色选择:
sphereColor = FluidID == 0?流体颜色[0]:流体颜色1;
我得到:
- OpenGL returns GL_NO_ERROR 来自 glGetError 所以我提供的 enums/values 没有问题
- 不是offsetof宏的问题。我尝试使用硬编码值,但它们也不起作用。
- 这不是与 GLint 的兼容性问题,我使用简单的 32 位整数(用 sizeof(int) 检查过)
- 我需要使用 FluidID 作为索引到颜色数组的实例化属性,否则,如果我要将粒子组的颜色设置为简单的 vec3 制服,我将不得不对相同的粒子类型进行批处理(具有相同的 FluidID)首先放在一起,这意味着对它们进行排序并且操作成本太高。
对我来说,这似乎是您如何设置 fluidID
属性指针的问题。因为你在shader中使用了类型int
,所以你必须使用glVertexAttribIPointer()
来设置属性指针。您使用普通 glVertexAttribPointer()
函数设置的属性仅适用于基于浮点数的属性类型。它们接受整数输入,但当着色器访问它们时,数据将被转换为浮点数。
在 oglplus 中,如果您想使用整数属性,显然必须使用 VertexArrayAttrib::IPointer()
而不是 VertexArrayAttrib::Pointer()
。
我使用 oglplus - 它是 OpenGL 的 c++ 包装器。
我在为我的粒子渲染器定义实例化数据时遇到问题 - 位置工作正常,但当我想从同一个 VBO 实例化一堆整数时出现问题。
我将跳过一些实现细节,以免使这个问题变得更复杂。假设我在描述的操作之前绑定了 VAO 和 VBO。
我有一个结构数组(称为 "Particle"),我是这样上传的:
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle) * numInstances, newData, GL_DYNAMIC_DRAW);
结构定义:
struct Particle
{
float3 position;
//some more attributes, 9 floats in total
//(...)
int fluidID;
};
我使用辅助函数来定义 OpenGL 属性,如下所示:
void addInstancedAttrib(const InstancedAttribDescriptor& attribDesc, GLSLProgram& program, int offset=0)
{
//binding and some implementation details
//(...)
oglplus::VertexArrayAttrib attrib(program, attribDesc.getName().c_str());
attrib.Pointer(attribDesc.getPerVertVals(), attribDesc.getType(), false, sizeof(Particle), (void*)offset);
attrib.Divisor(1);
attrib.Enable();
}
我像这样为位置和流体添加属性:
InstancedAttribDescriptor posDesc(3, "InstanceTranslation", oglplus::DataType::Float);
this->instancedData.addInstancedAttrib(posDesc, this->program);
InstancedAttribDescriptor fluidDesc(1, "FluidID", oglplus::DataType::Int);
this->instancedData.addInstancedAttrib(fluidDesc, this->program, (int)offsetof(Particle,fluidID));
顶点着色器代码:
uniform vec3 FluidColors[2];
in vec3 InstanceTranslation;
in vec3 VertexPosition;
in vec3 n;
in int FluidID;
out float lightIntensity;
out vec3 sphereColor;
void main()
{
//some typical MVP transformations
//(...)
sphereColor = FluidColors[FluidID];
gl_Position = projection * vertexPosEye;
}
此代码整体产生此输出:
如您所见,粒子按照我希望的方式排列,这意味着 "InstanceTranslation" 属性 设置正确。左侧粒子组的 FluidID 值为 0,右侧粒子组的 FluidID 值为 1。第二组粒子具有正确的位置,但在 FluidColors 数组中的索引不正确。
我知道的:
我设置 FluidColors 制服的方式没有问题。如果我像这样在着色器中硬编码颜色选择:
sphereColor = FluidID == 0?流体颜色[0]:流体颜色1;
我得到:
- OpenGL returns GL_NO_ERROR 来自 glGetError 所以我提供的 enums/values 没有问题
- 不是offsetof宏的问题。我尝试使用硬编码值,但它们也不起作用。
- 这不是与 GLint 的兼容性问题,我使用简单的 32 位整数(用 sizeof(int) 检查过)
- 我需要使用 FluidID 作为索引到颜色数组的实例化属性,否则,如果我要将粒子组的颜色设置为简单的 vec3 制服,我将不得不对相同的粒子类型进行批处理(具有相同的 FluidID)首先放在一起,这意味着对它们进行排序并且操作成本太高。
对我来说,这似乎是您如何设置 fluidID
属性指针的问题。因为你在shader中使用了类型int
,所以你必须使用glVertexAttribIPointer()
来设置属性指针。您使用普通 glVertexAttribPointer()
函数设置的属性仅适用于基于浮点数的属性类型。它们接受整数输入,但当着色器访问它们时,数据将被转换为浮点数。
在 oglplus 中,如果您想使用整数属性,显然必须使用 VertexArrayAttrib::IPointer()
而不是 VertexArrayAttrib::Pointer()
。