【问题标题】:Why my iPhone OpenGL-ES texture does not cover the viewport?为什么我的 iPhone OpenGL-ES 纹理没有覆盖视口?
【发布时间】:2012-08-16 07:12:04
【问题描述】:

我有一个大小为 320x320 的正方形图像,我从中创建了一个 OpenGL 纹理。我使用最基本的 Vertext 和 Fragment 着色器,我想在整个视图中显示纹理。视图(EAGLView 从 UIView 派生,在许多 OpenGL iOS 示例中都可以找到)大小也是 320x320。

问题是,图像绘制在左上角,仅覆盖整个视图的 50% 左右。它不会覆盖 100% 的视图。不知道为什么?

这是我的代码:

position = glGetAttribLocation(m_shaderProgram, "position");
inputTextureCoordinate = glGetAttribLocation(m_shaderProgram, "inputTextureCoordinate");    
inputImageTexture = glGetUniformLocation(m_shaderProgram, "inputImageTexture");

static const GLfloat textureCoordinates[] = {
    0.0f, 1.0f,
    1.0f, 1.0f,
    0.0f,  0.0f,
    1.0f,  0.0f,
};

static const GLfloat imageVertices[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    -1.0f,  1.0f,
    1.0f,  1.0f,
};

[EAGLContext setCurrentContext:context];

glViewport(0, 0, backingWidth, backingHeight); // These are 320, 320

glUseProgram(m_shaderProgram);

glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);

glActiveTexture(GL_TEXTURE2); 
glBindTexture(GL_TEXTURE_2D, sourceTextureID); // The texture is also of size 320x320

glUniform1i(inputImageTexture, 2);  

glVertexAttribPointer(position, 2, GL_FLOAT, 0, 0, imageVertices);
glVertexAttribPointer(textureCoordinate, 2, GL_FLOAT, 0, 0, textureCoordinates);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);    
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];

垂直着色器。

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 varying vec2 textureCoordinate;

 void main()
 {
    gl_Position = position;
    textureCoordinate = inputTextureCoordinate.xy;
 }

片段着色器。

 varying highp vec2 textureCoordinate;
 uniform sampler2D inputImageTexture;

 void main()
 {
    gl_FragColor = texture2D(inputImageTexture, textureCoordinate);
 }

【问题讨论】:

  • 您是否考虑到 iphone 4 及更高版本具有 2 倍比例因子? (尝试渲染两倍大以弥补视网膜显示)
  • 我尝试了不同的尺寸,除了 320。但结果是一样的。我这里使用 320 只是为了举例。
  • 你的意思是你已经尝试改变视口了吗?因为这应该明确地使它看起来更大或更小
  • 我将 EAGLView 的帧大小和视口大小设置为纹理的大小,在这种情况下为 320x320。但是,我可以通过手动调整视口大小或在纹理坐标中使用小于 1.0 的数字来使纹理绘制适合视图大小。但这没有意义,因为我仍然不明白这里到底是什么问题。或者如何在不硬编码的情况下调整视口大小或纹理坐标。
  • 我想我遇到了问题。纹理的尺寸必须是 2 的幂,例如,如果我使用 1024x1024,问题就会消失。如果我的纹理大小不是 2 的幂,我想我将不得不调整纹理坐标。而不是 1.0 作为纹理的边缘,它将是一个较小的数字,即维度与下一个最接近的 2 的幂的比率。我还没试过这个。我会尽快更新。

标签: iphone opengl-es vertex-shader


【解决方案1】:

所以问题在于纹理的尺寸不是 2 的幂。所以我们需要相应地缩放纹理坐标。插入以下行解决了问题...

GLfloat textureCoordinates[] = {
    0.0f, 1.0f,
    1.0f, 1.0f,
    0.0f,  0.0f,
    1.0f,  0.0f,
};

float nearest2sPower = 2;

if (nearest2sPower < backingWidth) {
    while (nearest2sPower < backingWidth) {
        nearest2sPower *= 2;
    }
}

verticalFlipTextureCoordinates[2] = backingWidth/nearest2sPower;
verticalFlipTextureCoordinates[6] = backingWidth/nearest2sPower;

nearest2sPower = 2;

if (nearest2sPower < backingWidth) {
    while (nearest2sPower < backingWidth) {
        nearest2sPower *= 2;
    }
}

verticalFlipTextureCoordinates[1] = backingHeight/nearest2sPower;
verticalFlipTextureCoordinates[3] = backingHeight/nearest2sPower;

【讨论】:

  • 虽然这几乎肯定是正确的答案,但这取决于海报上传纹理的方式。大多数预打包的解决方案都会四舍五入到最接近的 2 次方,但如果内存服务,那么 ES 2.0 实际上并不需要它。
  • 这真的不应该是必需的,所以我认为这不是问题的真正解决方案。所有支持 OpenGL ES 2.0 的 iOS 设备也支持非二次幂纹理(对钳制模式和 mipmap 的使用有一些轻微限制)。如果这是纹理上传的真正非二次幂错误,您只会得到一张黑色图像(相信我,我不止一次犯过这个错误)。
  • @Tommy 和 Brad,这对我来说是一个愚蠢的错误。实际上我复制了一些从 UIImage 创建纹理的代码。并且该代码在内部将纹理创建为“下一个最接近的 2 次幂”宽度和高度。所以,实际上我用我的代码消除了额外的宽度和高度。抱歉回答错误。该代码不是必需的。
猜你喜欢
  • 1970-01-01
  • 2011-08-23
  • 2012-01-12
  • 1970-01-01
  • 2013-03-06
  • 2010-10-04
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多