Opengl 传递给片段着色器的纹理坐标均为0

Opengl 传递给片段着色器的纹理坐标均为0,opengl,glsl,shader,fragment-shader,Opengl,Glsl,Shader,Fragment Shader,我已经为我正在开发的一个小型openGL 2.0应用程序编写了自己的顶点和片段着色器。 除了一件事之外,所有的东西看起来都很好,每个顶点的纹理坐标都是(0,0) 当我不使用自己的着色器时,也就是说,当我使用openGL的默认着色器时,所有内容都被绘制精细 当我激活自己的着色器时,形状仍然正常,顶点位置正确。但是纹理坐标都变为(0,0) 以下是顶点着色器的代码: in vec2 position; in vec2 texcoord; out vec2 coord; void main(void

我已经为我正在开发的一个小型openGL 2.0应用程序编写了自己的顶点和片段着色器。 除了一件事之外,所有的东西看起来都很好,每个顶点的纹理坐标都是(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)  

编辑:顺便问一下,此编辑器中的换行符有什么问题?

听起来您需要为纹理坐标启用客户端状态,因此请务必调用
GlenableVertexAttributeArray​

有关详细信息:

但若你们使用的是顶点数组,从你们的问题来看,你们似乎是

就我个人而言,我在调用
glDraw*()
之前启用我正在使用的所有数组,然后在draw调用之后禁用除positions数组之外的所有数组

要了解用于
GlenableVertexAttributeArray
的索引,您可以对您的职位使用
0
,对您的texcoords使用
1

一个更可靠的答案是,在编译程序并链接程序后,使用
glUseProgram()
使其成为当前程序,然后

GLuint位置指数=0
GLuint-texcoordIndex=1
glUseProgram(programmaid)
GLBindAttriblLocation(程序ID,位置索引,“位置”)
glBindAttribLocation(programmaid,texcoordIndex,“texcoord”)

然后在您的
glDraw*()

GlenableVertexAttributeArray(位置索引)
GlenableVertexAttributeArray(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);        
}
glUseProgram(programmaid);
int属性计数;
glGetProgramiv(程序ID、GL\u活动属性和属性计数);
GLuint attribLoc[]=新GLuint[attribCount];

对于(int attrib=0;attrib如果使用的是直接向上的顶点数组指针、texcoord数组指针等)API调用,则需要在着色器中使用相应的数组

更准确地说,当您想要访问着色器中纹理单元0的纹理坐标时,您可以使用
gl_texcoord[0]
,而不是在vec2 texcoord
中使用
(用于通用顶点属性)

这里的基本问题是,您将不推荐的API功能(
glTexCoordPointer
)与新的GLSL构造(
in
out
)混合在一起。nVIDIA驱动程序实际上会别名调用,如
glTexCoordPointer(…)
添加到特定的顶点属性槽,但这是非标准行为,通常不应将两者混合和匹配

OpenGL规范保证将别名化为特定属性槽的唯一数组指针是顶点指针,它将别名化为属性槽0


最后,您将希望切换到vertex attrib数组,因为它们更灵活,而且实际上受到核心OpenGL的支持:)

如果这是您的意思,换行符是用两个空格完成的。您的
#version
指令在哪里<代码>输入
/
输出
110
中无效。着色器编译/链接日志中有什么内容吗?我对更通用的方法感兴趣。我不太喜欢只为绘制调用启用和禁用顶点数组状态。创建顶点数组对象是为了持久存储顶点数组设置,而不依赖于顶点缓冲区。实际上,可能会对单个VBO使用2+个不同的VAO,具体取决于材质(着色器)所需的顶点属性以及它们所需的位置。然后,您只需绑定一个VAO,每当绘制批时,该VAO都会适当地排列VBO的数据。纹理设置也是如此,现在你应该绑定采样器对象,而你真正想做的就是修改纹理过滤器的状态。从论坛帖子中,人们给我的印象是,VAO的使用速度很慢,因为VAO改变了多少状态。在寻找支持这一说法的信息时,我发现VAO的速度并不是可以预测的慢或快,所以使用VAO将是一种更优雅的方法。我明白了。这很有道理。因此,如果我想保持旧版本(因为我已经以这种方式设置了所有渲染代码),我需要删除In/Out变量,并使用gl_Vertex和gl_TexCoord来代替?正确,如果使用旧的glVertexPointer、glTexCoordPointer等。。。调用以设置顶点数组,然后应使用gl_vertex、gl_TexCoord等来访问着色器中的顶点数据。如果/当您转换到使用顶点属性数组时,您将在变量中使用。顺便说一句,着色器排序现在工作的唯一原因是glVertexPointer将自身别名为attrib slot 0(换句话说,着色器中的第一个属性)。在任何情况下,变量实际上都是为顶点属性保留的,或者从上一个着色器阶段获取输出(例如vs将数据传递给fs),您应该
for (int attrib=0; attrib<attribCount; ++attrib) {
    glEnableVertexAttribArray(attribLoc[attrib]);
}

glDraw*();

for (int attrib=0; attrib<attribCount; ++attrib) {
    glDisableVertexAttribArray(attribLoc[attrib]);
}