当图像过大时,使用OpenGL出现黑色纹理

3

在我的应用程序(Tres)中,我正在从图像选择器中加载图像并将其放在纹理上。在所有测试中都正常工作,但现在在线上,使用视网膜显示屏的iPad用户抱怨图像呈黑色。

我正在查看GL_MAX_TEXTURE_SIZE以确保图像不超过该大小。

这里是设置纹理的代码:

texture_aspect = image.size.width / image.size.height;
CGFloat side = image.size.width;

if(side>GL_MAX_TEXTURE_SIZE)
    side = GL_MAX_TEXTURE_SIZE;
UIImage *newImage = [ImageUtils imageWithImage:image scaledToSize:CGSizeMake(side, side)];

image_height = 600.0f;
image_width = image_height * texture_aspect;
if(image_width>600.0f) {
    image_width = 900.0f;
    image_height = image_width / texture_aspect;
}

NSError* error;
GLKTextureInfo * texture = [GLKTextureLoader textureWithCGImage:newImage.CGImage options:nil error:&error];
if (error) {
    NSLog(@"Error loading texture from image: %@",error);
}

这是我绘制图片的方法:

- (void) dibujaFoto {
    self.effect.texture2d0.enabled = GL_TRUE;
    [self.effect prepareToDraw];
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    GLfloat squareVertices[] = {
        -image_width/2, -image_height/2,
        image_width/2,-image_height/2,
        -image_width/2, image_height/2,
        image_width/2,image_height/2,
    };

    const GLfloat squareTextureCoords[] = {
        0.0, 1.0,
        1.0, 1.0,
        0.0, 0.0,
        1.0, 0.0,
    };

    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, squareVertices);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0, squareTextureCoords);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribTexCoord0);
    self.effect.texture2d0.enabled = GL_FALSE;
}

无论图片大小如何,它总是能在我的第二代iPad上正常工作,但这段代码似乎在视网膜显示屏上存在问题。
1个回答

6

首先,你实际上并没有读取最大纹理尺寸。GL_MAX_TEXTURE_SIZE并不代表设备上的最大纹理尺寸,它是在读取最大纹理尺寸时使用的OpenGL ES常量。

要读取实际的最大纹理尺寸,你需要使用类似以下的代码:

static GLint maxTextureSize = 0;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

当然,在设置并使您的EAGLContext当前之后,您需要运行此操作。

旧设备(iPhone 4S之前)的最大纹理尺寸为2048x2048。A5及以上设备(4S及更高版本)的最大4096x4096纹理尺寸。

然而,这里还有其他问题,因为我的SDK上GL_MAX_TEXTURE_SIZE常量翻译成十进制为3379,这应该远远在Retina iPad的4096x4096最大纹理尺寸内(但对于原始iPad型号则太大)。我不明白为什么这会在那些设备上失败而不是旧设备。您的ImageUtils类是否可能以不正确的方式应用了设备比例因子?


很棒的回答。我可能在缩放时做错了什么。我会检查一下并提供更多信息。顺便说一句,能从您那里得到答案是我的荣幸。我所知道的OpenGL和iOS编程都是从您的视频中学到的。 - Odrakir
获取正确的最大纹理尺寸显然解决了问题。不要问我为什么。我很快就会买一个iPad视网膜屏幕,然后试着找出原因。 - Odrakir
1
@Odrakir - 拥有其中之一(特别是第三代iPad,没有第四代的额外处理能力)对于暴露其他设备看不到的填充率瓶颈非常有价值。此外,我发现在着色器中低精度类型的未记录舍入行为存在一些怪癖,在iPad 3和4与旧设备上表现不同。 - Brad Larson
我的错。我最终自己尝试了一下,发现确实与ImageUtils有关。我很傻,我正在使用UIGraphicsBeginImageContextWithOptions并将图像缩放为2.0以适应Retina设备...可能是一些旧代码吧。 - Odrakir
奇怪的是,我得到的图像确实具有正确的大小。 - Odrakir
非常感谢您的回答。它帮了我很多! - AgnosticDev

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