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