Opengl 传递给片段着色器的纹理坐标均为0
我已经为我正在开发的一个小型openGL 2.0应用程序编写了自己的顶点和片段着色器。 除了一件事之外,所有的东西看起来都很好,每个顶点的纹理坐标都是(0,0) 当我不使用自己的着色器时,也就是说,当我使用openGL的默认着色器时,所有内容都被绘制精细 当我激活自己的着色器时,形状仍然正常,顶点位置正确。但是纹理坐标都变为(0,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
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]);
}