OpenGL ES 2.0多个着色器程序-纹理渲染不再工作

3

我的应用程序绘制了一些点精灵和标准的四边形纹理。直到最近,我都是使用单个着色器程序来完成这个任务,但是片段着色器中的一个分支(用于决定是否使用点精灵坐标/颜色)严重地限制了渲染性能。我的片段着色器最初是这样的:

precision highp float;

uniform sampler2D u_textureSprite;
uniform bool u_isSprite;

varying vec4 v_color;
varying vec2 v_textureCoord;

void main()
{    
    vec4 textureColor = texture2D(u_textureSprite, u_isSprite ? gl_PointCoord : v_textureCoord);  
    if (u_isSprite) {
        gl_FragColor = v_color * textureColor;
    }
    else {
        gl_FragColor = textureColor;
    }
}

阅读苹果公司在OpenGL ES编程指南中的建议,似乎使用多个着色器程序是一项简单的工作...只需像往常一样创建另一个程序,在相关绘制代码之前调用glUseProgram()即可。然而,自从这样做后,我无法使纹理渲染正常工作。这两个新的片段着色器如下:

pointSprite.fsh:

precision highp float;

uniform sampler2D s_textureSprite;

varying vec4 v_color;

void main()
{    
    vec4 textureColor = texture2D(s_textureSprite, gl_PointCoord);
    gl_FragColor = v_color * textureColor;
}

texture.fsh:

precision highp float;

uniform sampler2D s_texture;


varying vec2 v_textureCoord;

void main()

{    
    gl_FragColor = texture2D(s_texture, v_textureCoord);
}

我认为这很简单。如果我忽略所有调用绘制纹理的函数,我可以看到点精灵被正确渲染。然而,纹理四边形只会渲染成单一的灰色 - 顺便说一下,这个灰色并不匹配任何glClearColor()中的颜色,我认为它是来自尝试渲染的某个纹理点的颜色。

以下是一个纹理渲染的小样例:

- (void)drawTexture:(GLuint)texture {
    glUseProgram(programs[PROGRAM_TEXTURE]);


    glBindTexture(GL_TEXTURE_2D, texture);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjects[VBO_TEXTURE_VERTICES]);

    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(ISTextureData), (void*)offsetof(ISTextureData, vertex));
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glVertexAttribPointer(ATTRIB_TEXTURE_COORD, 2, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ISTextureData), (void*)offsetof(ISTextureData, textureCoord));
    glEnableVertexAttribArray(ATTRIB_TEXTURE_COORD);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObjects[VBO_TEXTURE_INDICIES]);
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
}

当不涉及多个着色器时,此代码可以正常工作。或者我是不是太粗心了,纹理片段着色器代码有问题?

谢谢。

编辑:

经过数个痛苦的小时,令人恼火的是,问题居然不在代码上,而是与项目目录名称有关。

我的Xcode项目目录命名为:"ProjectName (current)"。这就是我遇到问题的项目。后来我发现,将此文件夹更改为任何其他名称都可以使应用程序正常工作,并正确渲染背景纹理。只是为了澄清一下 - 应用程序以前可以正常工作,只是OpenGL中的背景纹理无法渲染,在重命名项目文件夹后一切正常。

有任何想法吗?

2个回答

2

您在哪里为着色器设置纹理 uniform?您需要使用以下代码为纹理 uniform 分配适当的纹理单元号码,以用于纹理 uniform:

glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, sphereDepthMappingTexture);
glUniform1i(sphereDepthPrecalculatedDepthTextureUniform, 2);
glUniform1i()中的第二个参数是从哪个纹理单元中获取纹理的编号。
默认情况下,这个uniform的值是0,对应于GL_TEXTURE0,因此它可能在第一次使用时就起作用了,但如果您将活动的纹理单元切换到其他位置,您将无法在着色器中读取纹理。

@Brad 你好,感谢你的帮助。你提到这个很有趣,因为我之前在浏览一些编程指南时就有过类似的代码,但是因为我显然设置不正确,并且没有任何效果,所以我将其删除了。我已经在我的问题中编辑了一些更多的细节。 - Stuart
1
@StuDev - 针对您的更新,用于纹理的纹理单元是您在glActiveTexture()中指定的,如果您随后使用glBindTexture()将其绑定到该单元。 在上面的示例中,0是正确的值,就像我的示例中的2一样正确。 您的统一标识符仅由glUniform1i()用于寻址正确的统一变量,并且与纹理单元值无关。 - Brad Larson
1
@StuDev - 很遗憾,我不认为我这里提供的样例应用程序中有任何一个在同一场景中同时使用多个着色器进行渲染,虽然它们确实使用纹理,所以您可以针对此进行检查。下一个版本的 Molecules 会这样做,我会发布其源代码,但该应用程序还没有准备好。我使用多个着色器时没有遇到任何问题,这些问题也与单个着色器使用时相同。 - Brad Larson
@Brad:我觉得我在这方面有些进展了。我回到了一个工作正常的项目,然后逐步重返我的步骤。目前看起来还不错...我只是想找出第一次犯的愚蠢错误!当我找到它时,我会在这里发布回复。 - Stuart
@StuDev - 如果您对更多信息感兴趣,我的课程视频已经上传到iTunes U:http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=407243028,其中包括最近关于OpenGL ES 2.0的课程。我在这个最近的回答中还有一些几何调整技巧:https://dev59.com/XVbTa4cB1Zd3GeqP-F8z#5721102 - Brad Larson
显示剩余3条评论

0
这似乎与项目目录的名称有关。我的Xcode项目目录被命名为“ProjectName(current)”。这就是我遇到问题的项目。将此文件夹名称更改为任何其他名称都可以使应用程序正常工作,并正确呈现背景纹理。非常奇怪。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接