【问题标题】:Trouble Displaying Textures OpenGL ES 1.1无法显示纹理 OpenGL ES 1.1
【发布时间】:2011-11-08 08:49:34
【问题描述】:

我正在为 iPhone 开发一个简单的小游戏,我想使用纹理,但我似乎无法让它工作......

经过一番研究,我发现了this pagethis site。两者都是很好的参考资料,并教会了我一些关于纹理的知识,但是,在使用任一函数加载纹理后,我无法显示纹理,这是我的代码的样子:

非常简单的纹理显示功能(不工作)

void drawTexture(GLuint texture, float x, float y, float w, float h)
{
   glBindTexture(GL_TEXTURE_2D,texture);

   GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
   GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};

   glEnableClientState(GL_VERTEX_ARRAY);
   glEnableClientState(GL_TEXTURE_COORD_ARRAY);

   glVertexPointer(2, GL_FLOAT, 0,box);
   glTexCoordPointer(2, GL_FLOAT, 0, tex);

   glDrawArrays(GL_TRIANGLE_STRIP,0,4);

   glDisableClientState(GL_VERTEX_ARRAY);
   glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

通常,我不会为了显示图像而在每一帧都创建一个数组,但这只是一个示例。当我运行这个函数时,我什么也得不到。空白 - 没有图像,什么都没有(当然,除非我之前启用了一个颜色数组并且之后没有禁用它)

第二个简单的显示函数(这个使用了一个快速的小类)

void draw_rect(RectObject* robj){
    glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
    glEnableClientState(GL_VERTEX_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
    glEnableClientState(GL_COLOR_ARRAY);

    if ([robj texture] != -1){
        glEnable(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_TEXTURE_2D);
        glClientActiveTexture([robj texture]);

        glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
        glBindTexture(GL_TEXTURE_2D, [robj texture]);
    }

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_TEXTURE_COORD_ARRAY);
}

另一方面,这个函数确实改变了显示,而不是输出纹理,而是输出一个黑色方块......

设置背景

在我的 init 函数中,我正在调用

glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);

两个 LONG 纹理加载函数

struct Texture2D LoadImage(NSString* path)
{
    struct Texture2D tex;
    tex.texture = -1;

    // Id for texture 
    GLuint texture;
    // Generate textures
    glGenTextures(1, &texture);
    // Bind it
    glBindTexture(GL_TEXTURE_2D, texture);
    // Set a few parameters to handle drawing the image
    // at lower and higher sizes than original
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

    //NSString *path = [[NSString alloc] initWithUTF8String:imagefile.c_str()];
    path = [[NSBundle mainBundle] pathForResource:path ofType:@""];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:texData];
    if (image == nil)
        return tex;
    // Get Image size
    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    // Allocate memory for image
    void *imageData = malloc( height * width * 4 );
    CGContextRef imgcontext = CGBitmapContextCreate(
                                                imageData, width, height, 8, 4 * width, colorSpace,
                                                kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
    CGColorSpaceRelease( colorSpace );
    CGContextClearRect( imgcontext,
                   CGRectMake( 0, 0, width, height ) );
    CGContextTranslateCTM( imgcontext, 0, height - height );
    CGContextDrawImage( imgcontext,
                   CGRectMake( 0, 0, width, height ), image.CGImage );

    // Generate texture in opengl
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
             0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
    // Release context
    CGContextRelease(imgcontext);
    // Free Stuff
    free(imageData);
    [image release];
    [texData release];

    // Create and return texture

    tex.texture=texture;
    tex.width=width;
    tex.height=height;
    return tex;
}



GLuint makeTexture(NSString* path){
    GLuint texture[1]={-1};
    glGenTextures(1, texture);
    glBindTexture(GL_TEXTURE_2D, texture[0]);

    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);



    path = [[NSBundle mainBundle] pathForResource:path ofType:@"png"];
    NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:texData];
    if (image == nil)
        NSLog(@"Do real error checking here");

    GLuint width = CGImageGetWidth(image.CGImage);
    GLuint height = CGImageGetHeight(image.CGImage);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    void *imageData = malloc( height * width * 4 );
    CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
    CGColorSpaceRelease( colorSpace );
    CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
    CGContextTranslateCTM( context, 0, height - height );
    CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    CGContextRelease(context);

    free(imageData);
    [image release];
    [texData release];

    return texture[0];
}

如果您能指出正确的方向,将不胜感激。

【问题讨论】:

    标签: ios opengl-es textures


    【解决方案1】:

    首先,您的draw_rect 函数有错误。不要调用glClientActiveTexture,它是用于多重纹理的,你不需要它。用纹理对象调用它会绑定一些非常奇怪的纹理单元,或者很可能会导致错误。

    drawTexture 函数中,您实际上是按顺时针顺序绘制三角形。假设您没有翻转投影矩阵中的 y 方向或类似的东西,如果您启用了背面剔除,您的整个几何图形将被剔除。尝试调用glDisable(GL_CULL_FACE),尽管默认情况下应该禁用背面剔除。或者更好的是,将顶点更改为逆时针顺序:

    box[] = { x,y+h, x,y, x+w,y+h, x+w,y };
    

    您的drawTexture 函数中的顶点的纹理坐标也不匹配,但这不应该导致纹理不被绘制,而只是看起来有点奇怪。考虑到最后一段逆时针排序的变化,纹理坐标应该是:

    tex[] = { 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f };
    

    编辑:您的draw_rect 函数也弄乱了状态,因为您启用了顶点和颜色数组,但在完成渲染后不要再次禁用它们。当您现在想要在没有颜色数组的情况下绘制不同的东西时(例如在drawTexture 中),颜色数组仍然处于启用状态并使用一些任意数据。所以你应该添加

    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    

    紧接着

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    

    draw_rect.

    编辑:您还应该将 drawTexture 函数包装在一对glEnable(GL_TEXTURE_2D)glDisable(GL_TEXTURE_2D) 中。您在初始化代码中启用纹理,这是错误的。您应该在渲染之前设置所有必要的状态,尤其是像纹理这样高度依赖对象的状态。例如,一旦您在drawTexture 之前调用draw_rect,您最终会禁用纹理,尽管您在初始化代码中启用了它并认为它始终处于启用状态。您认为这不是一个好主意吗?

    编辑:我刚刚发现另一个错误。在draw_rect 中,您使用GL_TEXTURE_COORD_ARRAY 调用glEnableglDisable,这是错误的。您必须使用 glEnableClientStateglDisableClientState 来启用/禁用顶点数组,就像您使用 int drawTexture 一样。

    因此,作为一个中途结论,您的函数实际上应该如下所示:

    void drawTexture(GLuint texture, float x, float y, float w, float h)
    {
        glBindTexture(GL_TEXTURE_2D,texture);
        glEnable(GL_TEXTURE_2D);
    
        GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
        GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
    
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, box);
        glEnableClientState(GL_VERTEX_ARRAY);
    
        glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    
        glDisable(GL_TEXTURE_2D);
    }
    
    void draw_rect(RectObject* robj)
    {
        if ([robj texture] != -1)
        {
            glBindTexture(GL_TEXTURE_2D, [robj texture]);
            glEnable(GL_TEXTURE_2D);
    
            glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        }
    
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
        glEnableClientState(GL_COLOR_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
        glEnableClientState(GL_VERTEX_ARRAY);
    
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
    
        if ([robj texture] != -1)
        {
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glDisable(GL_TEXTURE_2D);
        }
    }
    

    【讨论】:

    • 非常感谢您的回复-我将顶点更改为逆时针顺序,但没有骰子...禁用背面剔除似乎也没有影响问题..所以在我看来,问题不在于现在的绘图功能,而在于我的代码中的其他地方,你也会朝那个方向倾斜吗?
    • @ultifinitus 您是否也对draw_rect 进行了建议更改(删除对glClientActiveTexture 的调用?这会绘制纹理吗?您是否确保矩形在当前视图中实际可见?和投影设置?
    • 是的,是的——有趣的是,我从 draw_rect 函数中删除了 glEnable(GL_TEXTURE_COORD_ARRAY);(并禁用)并将 glEnable(GL_TEXTURE_2D); 添加到 drawTexture 函数中。现在第二个功能按预期工作,实际显示图像!但另一个不是。非常感谢您的帮助,如果您将这些发现包含在您的答案中,那就太好了!
    • @ultifinitus 为什么要删除 texCoord 数组的启用/禁用?这不应该工作,因为现在您没有有效的纹理坐标,或者您现在不小心使用了来自drawTexture 函数的坐标,这是更错误的。
    • @ultifinitus 你还应该在从draw_rect返回之前禁用顶点和颜色数组。
    【解决方案2】:

    如果其中一个纹理有效而另一个无效,是否是纹理文件的问题? 尺寸有时会欺骗您,请尝试在两种纹理上使用相同的文件(一个有效的文件),看看是否解决了。如果是这样,那就是纹理文件有问题。

    【讨论】:

    • 确实如此,它的尺寸恰好是 2 的幂(或者至少这些是迄今为止唯一有效的)
    【解决方案3】:

    乐趣确实有效。

    void drawTexture(GLuint texture, float x, float y, float w, float h)
    {
        glBindTexture(GL_TEXTURE_2D,texture);
        glEnable(GL_TEXTURE_2D);
    
        GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
        GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
    
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, 0, box);
        glEnableClientState(GL_VERTEX_ARRAY);
    
        glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    
        glDisable(GL_TEXTURE_2D);
    }
    

    但我们应该关联到纹理的正确坐标。我应该改变代码

    表格

    GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
    GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
    

    GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
    GLfloat tex[] = { 0.0f,1.0f,  1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f };
    

    感谢堆栈溢出。谢谢你的帮助。 祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      相关资源
      最近更新 更多