我为自己正在研究的一些openGL 2.0应用程序编写了自己的Vertex和Fragment着色器。 一切似乎都很好,除了一件事,每个顶点的纹理坐标似乎都是(0,0)。
当我不使用自己的着色器时,即当我使用openGL的默认着色器时,则绘制所有内容 精细 。
当我激活自己的着色器时,形状仍然正常,顶点位置正确。但纹理坐标都变为(0,0)。
以下是顶点着色器的代码:
in vec2 position;
in vec2 texcoord;
out vec2 coord;
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 0, 1);
coord = vec2(gl_TextureMatrix[0] * vec4(texcoord, 1, 1));
}
这是片段着色器:
uniform sampler2D texture;
uniform float redFactor;
uniform float greenFactor;
uniform float blueFactor;
in vec2 coord;
void main(void) {
vec4 color = texture2D(texture, coord);
float grey = (color.r * redFactor + color.g * greenFactor + color.b * blueFactor);
gl_FragColor = vec4(grey, grey, grey, color.a);
}
同样,它没有我自己的着色器 ,可以正常运行 。所以VBO的设置正确。
顺便说一句,texcoords正确地从顶点着色器传递到片段着色器。 例如,当我更改行
时coord = vec2(gl_TextureMatrix[0] * vec4(texcoord, 1, 1));
在顶点着色器中:
coord = vec2(0.5, 0.5);
我得到了正确的结果。
以下是我的VBO内容的样子:
[0.0,0.0,
0.0,0.0,
0.0,1.0,
0.0,1.0,
1.0,1.0,
1.0,1.0,
1.0,0.0,
1.0,0.0]
以下是图纸的IBO:
[0, 1, 2, 2, 3, 0]
以下是指示:
VERTEX_ARRAY_POINTER(size = 2, stride = 16, offset = 0),
TEXCOORD_ARRAY_POINTER(size = 2, stride = 16, offset = 8)
编辑:顺便说一句,这个编辑器中的换行符有什么问题?
答案 0 :(得分:2)
听起来您需要为纹理坐标启用客户端状态,因此请务必为位置和纹理坐标调用glEnableVertexAttribArray
了解更多详情:http://www.opengl.org/wiki/Vertex_Specification#Vertex_Array_Object
但是如果你正在使用顶点数组,并且从你的问题看起来就像你一样。
就个人而言,我在调用glDraw*()
之前启用了我正在使用的所有数组,然后在绘制调用之后禁用除数组之外的所有数组。
要了解用于glEnableVertexAttribArray
的索引,您可以使用0
作为您的位置,1
作为您的texcoords。
更强大的答案是,在您编制程序并将其链接到程序后,请使用glUseProgram()
然后
GLuint positionIndex = 0;
GLuint texcoordIndex = 1;
glUseProgram(programId);
glBindAttribLocation(programId,positionIndex,“position”);
glBindAttribLocation(programId,texcoordIndex,“texcoord”);
然后在glDraw*()
glEnableVertexAttribArray(positionIndex);
glEnableVertexAttribArray(texcoordIndex);
这仍然是一种相当硬编码的处理方式,如果你想要一个更通用的方法,请发表评论。
因为这里要求的是了解着色器使用的顶点属性的通用方法
glUseProgram(programId);
int attribCount;
glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTES, &attribCount);
GLuint attribLoc[] = new GLuint[attribCount];
for (int attrib=0; attrib<attribCount; ++attrib) {
char szName[32];
int size;
GLenum vecType;
glGetActiveAttrib(programId, attrib, sizeof(szName), 0, &size, &vecType, szName);
attribLoc[attrib] = glGetAttribLocation(programId, szName);
glBindAttribLocation(programId, attribLoc[attrib], szName);
}
然后当你去画画
for (int attrib=0; attrib<attribCount; ++attrib) {
glEnableVertexAttribArray(attribLoc[attrib]);
}
glDraw*();
for (int attrib=0; attrib<attribCount; ++attrib) {
glDisableVertexAttribArray(attribLoc[attrib]);
}
答案 1 :(得分:2)
如果您使用直线向上顶点数组指针,texcoord数组指针等... API调用,那么您将需要在着色器中使用相应的数组。
更准确地说,不是使用in vec2 texcoord
(用于通用顶点属性),只要您想在着色器中访问纹理单元0的纹理坐标,就可以使用gl_TexCoord [0]
。
这里的根本问题是您将已弃用的API功能(glTexCoordPointer
)与新的GLSL结构(in
和out
)混合在一起。 nVIDIA驱动程序实际上会将glTexCoordPointer (...)
之类的调用别名替换为特定的顶点属性槽,但这是非标准的行为,您通常不应该混合和匹配这两个。
唯一保证由OpenGL规范别名到特定属性槽的数组指针。是顶点指针,它别名为插槽0。
最后,您需要切换到顶点属性数组,因为它们更灵活,并且实际上由核心OpenGL支持:)