C++ 使用每个实例颜色的OpenGL实例渲染&;抵消

C++ 使用每个实例颜色的OpenGL实例渲染&;抵消,c++,qt,opengl,glsl,shader,C++,Qt,Opengl,Glsl,Shader,您好,我正在尝试使用glDrawArraysInstanced()渲染大量轴对齐的立方体。每个固定大小的立方体只能在其中心位置和颜色上变化。此外,每个立方体只需要几个不同的颜色。因此,我希望使用以下每个实例数据呈现数百万个立方体: struct CubeInfo { Eigen::Vector3f center; // center of the cube (x,y,z) int labelId; // label of the cube which affects its color

您好,我正在尝试使用glDrawArraysInstanced()渲染大量轴对齐的立方体。每个固定大小的立方体只能在其中心位置和颜色上变化。此外,每个立方体只需要几个不同的颜色。因此,我希望使用以下每个实例数据呈现数百万个立方体:

struct CubeInfo {
  Eigen::Vector3f center; // center of the cube (x,y,z)
  int labelId;  // label of the cube which affects its color
};
因此,我使用以下顶点着色器:

#version 330

uniform mat4 mvp_matrix;

//regular vertex attributes
layout(location = 0) in vec3 vertex_position;

// Per Instance variables
layout(location = 1) in vec3 cube_center;
layout(location = 2) in int cube_label;

// color out to frag shader
out vec4 color_out;

void main(void) {
  // Add offset cube_center
  vec4 new_pos = vec4(vertex_position + cube_center, 1);
  // Calculate vertex position in screen space
  gl_Position = mvp_matrix * new_pos;

  // Set color_out based on label
  switch (cube_label) {
  case 1:
    color_out = vec4(0.5, 0.25, 0.5, 1);
    break;
  case 2:
    color_out = vec4(0.75, 0.0, 0.0, 1);
    break;
  case 3:
    color_out = vec4(0.0, 0.0, 0.5, 1);
    break;
  case 4:
    color_out = vec4(0.75, 1.0, 0.0, 1);
    break;
  default:
    color_out = vec4(0.5, 0.5, 0.5, 1); // Grey
    break;
  }
}
以及相应的片段着色器:

#version 330

in vec4 color_out;
out vec4 fragColor;

void main()
{
    // Set fragment color from texture
    fragColor = color_out;
}
然而,color_out始终采用默认的灰色值,即使cube_标签值介于1到4之间。这是我的问题。我是否在上面的着色器中做错了什么**

我用1-4之间的随机标签初始化了cubeInfo vbo。因此,我希望看到比以下内容更丰富多彩的输出:

这是我的渲染代码,它使用了Qt和包装器:

除了我上面的主要问题(颜色问题),这是一个很好的方法来做Minecraft吗

更新 如果我将我的
CubeInfo.labelId
属性从
int
更改为
float
,并且将相应的顶点着色器变量
cube\u label
也更改为
float
,则会起作用!!。为什么会这样?表示GLSL支持int类型。对我来说,我更喜欢labelId/cube\u标签是int/short

更新2:

即使我只是在渲染代码的下一行中更改为GL_FLOAT而不是GL_INT,我也会得到正确的颜色

cubeShaderProgram_.setAttributeBuffer("cube_label", GL_INT, offsetof(CubeInfo,labelId), 1, sizeof(CubeInfo));

如果要使用顶点着色器中指定的颜色,至少应编写一个简单的片段着色器,如:

void main()
{
   gl_FragColor = color_out;
}
更新

我认为要么你不能将cube_标签传递给你的顶点着色器,要么你没有在一开始(在结构中)设置它们。后一种情况更可能发生,但您可以用下面的行替换开关盒,以查看传递的实际值

color_out = vec4(float(cube_label) / 4.0, 0, 0, 1.0); 
更新2


有一次,我在英特尔GPU(驱动程序)上遇到了类似的问题。不管我怎么做都无法传递整数值。但是,同一着色器在NVIDIA上工作得非常完美,因此在您的案例中,我将int转换为float。

标签属性的问题是,它是一个整数属性,但您没有将其设置为整数属性。Qt的
setAttributeBuffer
函数对整数属性一无所知,它们都在引擎盖下使用,它以任意格式获取顶点数据,并将其转换为
float
以将其传递为
in float
属性,该属性与着色器中的
in int
属性不匹配(因此该属性可能只是保持在某个随机的默认值,或者获得一些未定义的值)

要将数据实际传递到实整数顶点属性(这与浮点属性完全不同,直到GL 3+才引入,您需要函数
glVertexAttributeInter
(注意这里的
I
,以及类似的
D
for
in double
属性,在这种情况下仅使用
GL\u double
也不起作用)。但遗憾的是,Qt似乎还没有一个包装器。因此,您必须使用以下方法手动完成:

glVertexAttribIPointer(cubeShaderProgram_.attributeLocation("cube_label"), 
                       1, GL_INT, sizeof(CubeInfo), 
                       static_cast<const char*>(0)+offsetof(CubeInfo,labelId));
glVertexAttribIPointer(立方体领导程序属性位置(“立方体标签”),
1,GL_INT,sizeof(CubeInfo),
静态施法(0)+偏移(立方信息,labelId));

代替
cubeShaderProgram_uu.setAttributeBuffer
调用,或者在float属性中使用

没有Qt它能工作吗?我会解决问题…我确定问题是cube\u label和CubeInfo.labelId的int类型。请参阅我的更新。int类型为什么不能工作?它一直给我全红色,所以t我想cube_标签被设置为某个高值。当我使用float而不是int作为cube标签时,我的问题就解决了。请参阅我问题的更新。
glVertexAttribIPointer(cubeShaderProgram_.attributeLocation("cube_label"), 
                       1, GL_INT, sizeof(CubeInfo), 
                       static_cast<const char*>(0)+offsetof(CubeInfo,labelId));