使用顶点缓冲对象为OpenGL中的图元赋予颜色

时间:2012-04-19 01:13:51

标签: c opengl graphics fragment shader

我正在用C语言编写程序,使用OpenGL绘制一些基元(线条,圆圈等)。我成功地使用缓冲区对象来存储基元的顶点,因此,在绘制它们时。但我现在似乎陷入困境,因为我不知道如何设置它们的颜色。部分程序由我的老师提供给我,所以我知道必须使用这种结构指定颜色属性:

typedef struct {
    float r;
    float g;
    float b;
    float a;
} vec4;

我知道我应该使用vec4数组存储颜色值,所以我声明了一个这样的变量。第一个是vec2数组,用于存储基本顶点。

vec2 vertices[10000];
vec4 colours[10000];

用于设置顶点缓冲区限制的函数(据我所知)如下所示:

void initShaders(void) 
{
    GLuint buffer;
    GLuint loc;
    GLuint vao;

    /*Create and initialize a program object with shaders */ 
  idProgram = initProgram("ass1vshader.glsl", "ass1fshader.glsl");

    /*installs the program object as part of current rendering state */ 
   glUseProgram(idProgram);

   /*Creat a vertex array object */ 
   glGenVertexArrays(1, &vao);
   glBindVertexArray(vao);

    /*Create buffer in the shared display list space and */ 
     /* bind it as GL_ARRAY_BUFFER */ 
    glGenBuffers( 1, &buffer);
    glBindBuffer( GL_ARRAY_BUFFER, buffer);
    glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);

    /*Initialize attribute vPosition in program */ 
    loc = glGetAttribLocation( idProgram, "vPosition");
    glEnableVertexAttribArray(loc);
    glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)BUFFER_OFFSET(0));

    /*Get location of the uniform attribute 'u_proj_matrix' */ 
    idProjection = glGetUniformLocation(idProgram, "u_proj_matrix");

    /*Set graphics attributes */ 
    glLineWidth(3.0);
    glPointSize(1.0);
    glClearColor(1.0, 1.0, 1.0, 1.0);

}

如您所见,我已将顶点缓冲区大小初始化为“顶点”和“颜色”的组合大小。

我也了解片段着色器在着色过程中起着重要作用。它看起来像这样:

#version 140

in vec4 color;
out vec4  fColor;

void
main()
{    
    fColor = color;
}

有人可以告诉我如何为我的原语提供颜色吗?我希望我提供的信息足够。

2 个答案:

答案 0 :(得分:0)

一种方法是使用颜色数组。您可以通过与glVertexPointer()相同的方式致电glColorPointer()来完成此操作。

另外,我不知道这只是一个错字,或者你是否真的有这个错误,但你写道:

glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);

但是,您的顶点数组被命名为“顶点”而不是“顶点”(至少根据您之前的语句)。如果它编译好,那么它可能意味着你有另一个名为vertex的变量或数据结构,但它没有按你的想法做。

由于你的数据没有交错(你有不同的顶点和颜色数据),我想你会想为它们使用单​​独的缓冲区。如果它们在一个结构中,你可以使用一个数组,并适当地设置步幅,但由于它们没有交错,我不确定你试图做的是否会起作用。

答案 1 :(得分:0)

首先,您没有向您展示顶点着色器,它负责接收每个顶点颜色并将其放置在基元上进行插值并发送到片段着色器。我想它看起来(或应该看起来像):

uniform mat4 u_proj_matrix;

in vec4 vPosition;
in vec4 vColor;

out color;

void main()
{
    gl_Position = u_proj_matrix * vPosition;
    color = vColor;
}

所以我们有一个名为vColor的额外每个顶点属性,我们需要为其指定一个源,就像我们对vPosition属性所做的那样:

loc = glGetAttribLocation(idProgram, "vColor");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 0, 
                      (GLvoid*)BUFFER_OFFSET(sizeof(vertices)));

这指定了在所有10000个顶点的坐标之后存储在缓冲区中的所有10000个顶点的颜色。


但是正如user1118321已经指出的那样,将单个顶点的坐标和颜色存储在一起并因此交错属性可能是更好的想法(即使不是唯一可能的)。在这种情况下,您将拥有类似这样的结构:

typedef struct {
    vec2 coords;
    vec4 color;
} vertex;

和单个数组:

vertex vertices[10000];

但在这种情况下,我们必须通过使用glVertexAttribPointer的步幅和偏移参数来告诉OpenGL我们的数据是交错的:

//for position:
glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 
                      sizeof(vertex), (GLvoid*)offsetof(vertex, coords));

//for color:
glVertexAttribPointer(loc, 4, GL_FLOAT, GL_FALSE, 
                      sizeof(vertex), (GLvoid*)offsetof(vertex, color));

这告诉OpenGL,两个连续顶点的属性值之间的步幅(从一个到下一个的偏移)是我们自定义结构的大小。从一个顶点的坐标数据的开头到下一个顶点的坐标数据的开头的意思我们必须“跳过”sizeof(vertex)个字节(最可能是sizeof(vec2)+sizeof(vec4) = 24),同样也要跳过颜色。

此外,我们告诉GL我们的顶点数据从第一个顶点的coords成员的偏移开始(很可能是0),我们的颜色数据从第一个顶点的颜色成员的偏移处开始(最有可能是sizeof(vec2) = 8)。