当前位置: 首页 > 知识库问答 >
问题:

在Objective-C中将纹理绑定到GLSL着色器

漆雕亮
2023-03-14

我在Mac OSX下工作,试图通过GLSL着色器在立方体上映射图像。

我显示立方体(以及图像,当它不通过着色器时)的方法是:

glPushMatrix();
{

    glTranslatef(position.getX(), position.getY(), position.getZ());
    glRotatef(angle, axis.getX(), axis.getY(), axis.getZ());

    if (bodyImage &&
        textureCoords != 0 &&
        [bodyImage lockTextureRepresentationWithColorSpace:CGColorSpaceCreateDeviceRGB() forBounds:[bodyImage imageBounds]]) {

        [bodyImage bindTextureRepresentationToCGLContext:cgl_ctx textureUnit:GL_TEXTURE0 normalizeCoordinates:YES];
        texture = [bodyImage textureName];


        if(shader != nil) {

            glUseProgramObjectARB([shader programObject]);
            glUniform1iARB([shader getUniformLocation:"tex0"], 0);

        } else {

            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glTexCoordPointer(3, GL_FLOAT, sizeof(btVector3), &textureCoords[0].getX());

        }


    }



    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);


    glVertexPointer(3, GL_FLOAT, sizeof(btVector3), &vertices[0].getX());
    glNormalPointer(GL_FLOAT, sizeof(btVector3), &normals[0].getX());


    glDrawElements(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, indices);


    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);




    if (bodyImage) {

        if (shader != nil) {
            glUseProgramObjectARB(NULL);
        } else {
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        }


        [bodyImage unbindTextureRepresentationFromCGLContext:cgl_ctx textureUnit:GL_TEXTURE0];
        [bodyImage unlockTextureRepresentation];

    }


}
glPopMatrix();

正如你所看到的,我正在检查,在这个测试中,是否有一个着色器应用到我的对象上(它是一个包装,效果非常好)

如果没有着色器,我只启用GL_纹理_坐标_数组,如果有,我尝试将图像绑定到着色器中的采样2D均匀。

我使用的着色器非常简单:它只显示纹理。我在Quartz Composer下测试了它,效果很好。

但是,在这里,它只显示黑色。

这是着色器。。。

角顶

varying vec2 texture_coordinate;

void main() {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
texture_coordinate = vec2(gl_MultiTexCoord0);
}

碎片

varying vec2 texture_coordinate;
uniform sampler2D tex0;

void main()
{
gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy);
}

共有1个答案

严承允
2023-03-14

替换只有在着色器为NULL时才应用纹理坐标指针的错误逻辑,改为:

if(shader != nil) {
  glUseProgramObjectARB([shader programObject]);
  glUniform1iARB([shader getUniformLocation:"tex0"], 0);
}

// You need texture coordinates in shaders too!
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, sizeof(btVector3), &textureCoords[0].getX());

稍后,您还需要更正您的清理代码

if (shader != nil) {
  glUseProgramObjectARB(NULL);
}

glDisableClientState(GL_TEXTURE_COORD_ARRAY);

然后,当需要纹理坐标时,在顶点着色器中,使用gl_MultiTexCoord0。。。使用不同的方法将其传递给片段着色器。

当你在画图时,不要每次都设置tex0采样器的值。GLSL程序持续保持统一状态,当您设置采样器时,采样器在整个程序生命周期的大部分时间都引用相同的纹理单元。因此,在链接程序后立即设置采样器制服的值更为合理,并且在该点之后再也不要设置它们。

 类似资料:
  • 如何在平面上滚动纹理?所以我有一个平面有一个纹理,我可以使用一个着色器滚动左从右(无限)的纹理上?

  • 我是OpenGL的新手,在整理如何将纹理和着色器绑定到VBOs时遇到了困难。 我正在使用Cinder的纹理和着色器类。以下是我绘制方法的一部分: 在上面的代码中,如果我注释掉对mShader的调用。bind(),我的球体VBO将显示纹理(myImage)。我的着色器适用于普通(无纹理)形状,但当我在绘制任何带有包裹纹理的形状之前绑定着色器时,它会阻止纹理显示。 这是我使用的着色器的问题,还是我不理

  • 我需要处理许多只共享少数纹理的对象。手动定义和加载纹理一个接一个(如SO上的另一篇文章中所述)感觉不太对劲...尤其是因为WebGL中没有语句。 因此,我想将用于顶点的纹理作为顶点属性传递,并将该数字用作fragement着色器中某些“纹理数组”的索引。但是采样器上的OpenGL wiki(不是WebGL的完美参考,但我找到的那个)说: 取样器的变量只能用两种方式之一来定义。它可以定义为函数参数或

  • 我正在努力发送多个纹理到一个单一的着色器,并有一个奇怪的问题,在着色器中的两个采样器似乎得到相同的纹理数据。我知道还有很多其他的多纹理问题和答案(这里有一些我已经读过很多次了1,2,3),但一些bug正在逃避我,我开始失去我的弹珠。我很有信心我已经把一切都安排好了,但显然还是有一些问题。 所以,目前我有形状,材料,纹理,和着色器类。我的shape类是执行实际绘制的父类。它有一个具有着色器和纹理数组

  • 我一直在尝试渲染到一个FBO,并将两个FBO渲染到屏幕上,但在合并两个FBO时进行深度测试失败。我尝试使用计算着色器合并纹理,但无法读取深度纹理的值(所有值都是值1,但渲染到FBO时深度测试有效)。有人知道我做错了什么,或者知道其他方法来合并两个FBO吗? 以下是我创建FBO的方式: 以下是我向FBO渲染的方式: 我尝试用glBindTexture绑定纹理(所有值均为1): 计算着色器: 我已尝试

  • 我希望能够在GLSL片段着色器中组合两种纹理。我目前正在使用PyOpenGL,到目前为止我使用着色器所做的一切都很好。 当我尝试从片段着色器访问多个纹理时遇到困难,例如,以下着色器显示正确的纹理减去蓝色像素: 但是 导致空白屏幕。 我有一种感觉,问题可能在于我如何将纹理制服传递给着色器,但我一辈子都无法弄清楚为什么第一个纹理有效,而第二个纹理无效。下面是完整的程序。