1

我正在用 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;
}

有人可以告诉我如何为我的图元赋予颜色吗?我希望我提供的信息是足够的。

4

2 回答 2

1

一种方法是使用颜色数组。glColorPointer()您可以通过调用glVertexPointer().

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

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

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

而且由于您的数据没有交错(您有单独的顶点和颜色数据),我认为您需要为它们使用单​​独的缓冲区。如果它们在一个结构中,您可以使用单个数组,并适当地设置步幅,但由于它们没有交错,我不确定您尝试做的事情是否有效。

于 2012-04-19T04:42:50.157 回答
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];

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

//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)。

于 2012-04-19T08:37:24.470 回答