2013-10-04 44 views
4

您好我正在尝试使用glDrawArraysInstanced()渲染大量的轴对齐的多维数据集。每个固定尺寸的立方体只能在其中心位置和颜色上有所不同。而且每个立方体只需要几种不同的颜色。所以我想可能使数以百万计的立方体,每个实例的数据如下:OpenGL实例渲染每个实例的颜色和偏移量

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_label值介于1到4之间。这是我的问题。我在做什么错误在上面的着色器中**?**

我初始化立方体信息vbo与1-4之间的随机labelIds。因此,我期待看到一个丰富多彩的产量比以下: enter image description here

这是我的渲染代码,这使得使用Qt的QGLShaderProgramQGLBuffer包装的:

// Enable back face culling 
    glEnable(GL_CULL_FACE); 
    cubeShaderProgram_.bind(); 

    // Set the vertexbuffer stuff (Simply 36 vertices for cube) 
    cubeVertexBuffer_.bind(); 
    cubeShaderProgram_.setAttributeBuffer("vertex_position", GL_FLOAT, 0, 3, 0); 
    cubeShaderProgram_.enableAttributeArray("vertex_position"); 
    cubeVertexBuffer_.release(); 

    // Set the per instance buffer stuff 
    cubeInstanceBuffer_.bind(); 

    cubeShaderProgram_.setAttributeBuffer("cube_center", GL_FLOAT, offsetof(CubeInfo,center), 3, sizeof(CubeInfo)); 
    cubeShaderProgram_.enableAttributeArray("cube_center"); 
    int center_location = cubeShaderProgram_.attributeLocation("cube_center"); 
    glVertexAttribDivisor(center_location, 1); 

    cubeShaderProgram_.setAttributeBuffer("cube_label", GL_INT, offsetof(CubeInfo,labelId), 1, sizeof(CubeInfo)); 
    cubeShaderProgram_.enableAttributeArray("cube_label"); 
    int label_location = cubeShaderProgram_.attributeLocation("cube_label"); 
    glVertexAttribDivisor(label_location, 1); 

    cubeInstanceBuffer_.release(); 

    // Do Instanced Renering 
    glDrawArraysInstanced(GL_TRIANGLES, 0, 36, displayed_num_cubes_); 

    cubeShaderProgram_.disableAttributeArray("vertex_position"); 
    cubeShaderProgram_.disableAttributeArray("cube_center"); 
    cubeShaderProgram_.disableAttributeArray("cube_label"); 

    cubeShaderProgram_.release(); 

除了我上面的首要问题(色差问题),这是做Minecraft的好方法吗?

更新 如果我改变我的CubeInfo.labelId属性从intfloat,以及相应的顶点着色器变量cube_labelfloat,它工作 !!。为什么这样? This page说GLSL suppoers int类型。对于我来说,我更喜欢labelId/cube_label是一些int/short。

UPDATE2:

即使我只是改变GL_FLOAT,而不是在GL_INT下面一行我的渲染代码,我得到应有的颜色。

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

它没有Qt的工作吗?我会指出这个问题... – lpapp

+0

我认为问题是cube_label和CubeInfo.labelId的int类型。查看我的更新。为什么int类型不起作用? – iNFINITEi

回答

1

您的标签属性的问题是,它是一个整数属性,但您不要将其设置为整数属性。 Qt的setAttributeBuffer函数并不知道任何关于整数属性的内容,它们全都使用glVertexAttribPointer,它将顶点数据转换为任意格式并将其转换为float,以将其传递给in float属性,该属性与in int之间不匹配你的着色器(所以该属性可能会保持在某个随机默认值,或获得一些未定义的值)。

要实际传递数据变成一个真正的整数顶点属性(这是一件好事,从一个浮动的属性完全不同,并没有出台,直到GL 3+),你需要的功能glVertexAttribIPointer(注意在那里I和类似D对于in double属性,仅使用GL_DOUBLE在这种情况下也不起作用)。但令人遗憾的是,Qt并没有真正适合GL 3+,但似乎没有包装。所以,你将不得不做手工用:

glVertexAttribIPointer(cubeShaderProgram_.attributeLocation("cube_label"), 
         1, GL_INT, sizeof(CubeInfo), 
         static_cast<const char*>(0)+offsetof(CubeInfo,labelId)); 

代替cubeShaderProgram_.setAttributeBuffer呼叫,或使用in float属性来代替。

0

如果你想使用顶点着色器指定的颜色,你至少应该写一个平凡的片段着色器,如:

void main() 
{ 
    gl_FragColor = color_out; 
} 

更新

我认为,要么你可以不会将cube_label传递给顶点着色器,或者您没有将它们放在第一位(在结构中)。后者更可能,但您可以用以下行替换您的开关盒以查看传递的实际值。

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

UPDATE2

我曾有过一个类似的问题与英特尔的GPU(驱动程序)。无论我尝试过什么都不能传递整数值。然而,相同的着色器在NVIDIA上运行得非常完美,所以在我将int转换为float的情况下。

+0

我已经有一个片段着色器。我更新了我的问题。 – iNFINITEi

+0

它总是让我全红,所以cube_label被设置为一个很高的值,我想。当我使用float而不是int来表示立方体标签时,我的问题得到了解决。查看我的问题的更新。 – iNFINITEi