C 在OpenGL中使用顶点缓冲区对象为原语着色
我正在用C语言编写一个程序,使用OpenGL绘制一些基本体(直线、圆等)。我已经成功地使用缓冲区对象来存储基本体的顶点,从而绘制它们。但我现在似乎被卡住了,因为我不知道如何设置它们的颜色。我的老师给了我一部分程序,因此我知道必须使用以下结构指定颜色属性:C 在OpenGL中使用顶点缓冲区对象为原语着色,c,opengl,shader,C,Opengl,Shader,我正在用C语言编写一个程序,使用OpenGL绘制一些基本体(直线、圆等)。我已经成功地使用缓冲区对象来存储基本体的顶点,从而绘制它们。但我现在似乎被卡住了,因为我不知道如何设置它们的颜色。我的老师给了我一部分程序,因此我知道必须使用以下结构指定颜色属性: typedef struct { float r; float g; float b; float a; } vec4; 我知道我应该使用vec4数组来存储颜色值,所以我声明了一个这样的变量。第一个是用于存储基
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;
}
如您所见,我已将顶点缓冲区大小初始化为“顶点”和“颜色”的组合大小
我还了解到片段着色器在着色过程中起着重要作用。看起来是这样的:
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;
}
有人能告诉我怎样才能给我的原语着色吗?我希望我提供的信息足够了。一种方法是使用颜色数组。您可以使用与调用
glvertexinter()
相同的方法调用
另外,我不知道这是否只是一个打字错误,或者你是否真的有这个错误,但你写道:
glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);
但是,顶点数组的名称为“顶点”而不是“顶点”(至少根据前面的语句)。如果它编译正常,则可能意味着您有另一个名为vertex的变量或数据结构,但它并没有按照您的想法执行
由于您的数据不是交错的(您有单独的顶点和颜色数据),我认为您应该为它们使用单独的缓冲区。如果它们在一个结构中,您可以使用单个数组,并适当地设置步幅,但由于它们不是交错的,我不确定您尝试执行的操作是否有效。一种方法是使用颜色数组。您可以使用与调用
glvertexinter()
相同的方法调用
另外,我不知道这是否只是一个打字错误,或者你是否真的有这个错误,但你写道:
glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)+sizeof(colours), NULL,GL_STATIC_DRAW);
但是,顶点数组的名称为“顶点”而不是“顶点”(至少根据前面的语句)。如果它编译正常,则可能意味着您有另一个名为vertex的变量或数据结构,但它并没有按照您的想法执行
由于您的数据不是交错的(您有单独的顶点和颜色数据),我认为您应该为它们使用单独的缓冲区。如果它们在一个结构中,您可以使用单个数组,并适当设置步长,但由于它们不是交错的,我不确定您尝试执行的操作是否有效。首先,您没有显示顶点着色器,它负责接收逐顶点颜色,并将其输出到基本体上进行插值,然后发送到片段着色器。我猜它看起来(或应该看起来)像:
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个顶点的颜色
vec2 vertices[10000];
vec4 colours[10000];
但正如user1118321已经指出的,将单个顶点的坐标和颜色存储在一起,从而交错属性可能是一个更好的主意(即使不是唯一可能的主意)。在这种情况下,您将拥有如下结构:
typedef struct {
vec2 coords;
vec4 color;
} vertex;
以及以下各项的单个阵列:
vertex vertices[10000];
但在这种情况下,我们必须告诉OpenGL,我们的数据是通过使用glVertexAttributePointer
的步幅和偏移参数进行交错的:
//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(顶点)
bytes(很可能是sizeof(vec2)+sizeof(vec4)=24
),同样地,对于颜色也是如此
此外,我们告诉GL,我们的顶点数据从第一个顶点的coords成员的偏移量开始(很可能
0
),我们的颜色数据从第一个顶点的颜色成员的偏移量开始(很可能sizeof(vec2)=8
)。首先,您没有显示顶点着色器,它负责接收逐顶点颜色,并将其输出到基本体上进行插值,然后发送到片段着色器。我猜它看起来(或应该看起来)像:
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个顶点的颜色
vec2 vertices[10000];
vec4 colours[10000];
但正如user1118321已经指出的,将单个顶点的坐标和颜色存储在一起,从而交错属性可能是一个更好的主意(即使不是唯一可能的主意)。在这种情况下,您将拥有如下结构:
typedef struct {
vec2 coords;
vec4 color;
} vertex;
以及以下各项的单个阵列:
vertex vertices[10000];
但在这种情况下,我们必须告诉OpenGL,我们的数据是通过使用glVertexAttributePointer
的步幅和偏移参数进行交错的:
//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(顶点)
bytes(很可能是sizeof(vec2)+sizeof(vec4)=24
),同样地,对于颜色也是如此
此外,我们告诉GL,我们的顶点数据从的coords成员的偏移量开始