我在iOS中遇到过opengl着色器的奇怪行为

时间:2017-03-17 06:38:47

标签: ios opengl-es

我在iOS中编写opengl着色器以应用图像效果。我需要使用地图来查找图像中的像素。以下是我的着色器的代码:

precision lowp float;
uniform sampler2D u_Texture;
uniform sampler2D u_Map; //map

varying highp vec2 v_TexCoordinate;

void main()
{
     //get the pixel
     vec3 texel = texture2D(u_Map, v_TexCoordinate).rgb;
     gl_FragColor = vec4(texel, 1.0);
}

上面是一个测试着色器,它应该显示正在使用的地图。

现在,上面是带有两个地图的上述着色器的行为

MAP_1像素大小(256 x 1)

MAP_1 (256x1)

以下是使用上面着色器的输出:

Output with MAP_1

MAP_2像素大小(256 x 3) MAP_2

这是输出:

enter image description here

因此,在使用256 x 1像素的地图时,它可以正常工作,但在使用256 x 3像素的地图时,它会显示黑色图像。我已经用其他地图测试了这个,并且遇到了这是因为地图的像素高度。

以下是我如何加载地图的代码:

+ (GLuint)loadImage:(UIImage *)image{
//Convert Image to Data
GLubyte* imageData = malloc(image.size.width * image.size.height * 4);
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();

CGContextRef imageContext = CGBitmapContextCreate(imageData, image.size.width, image.size.height, 8, image.size.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, image.size.width, image.size.height), image.CGImage);

//Release Objects
CGContextRelease(imageContext);
CGColorSpaceRelease(genericRGBColorspace);

//load into texture
GLuint textureHandle;
glGenTextures(1, &textureHandle);
glBindTexture(GL_TEXTURE_2D, textureHandle);
[GLToolbox checkGLError:@"glTextureHandle"];
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.size.width, image.size.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
[GLToolbox checkGLError:@"glTexImage2D"];

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

//Free Image Data
free(imageData);

return textureHandle;}

我不确定为什么会这样。可能是,我在加载大小为256x3的Map时出错了。有人,请告诉我解决上述问题的方法。

提前致谢。

1 个答案:

答案 0 :(得分:2)

在OpenGLES2中,非二次幂纹理需要没有mipmap(你很好)并使用GL_CLAMP_TO_EDGE(我认为这是你的问题)。来自This is my table structure

  

同样,如果纹理图像的宽度或高度不是2的幂,并且GL_TEXTURE_MIN_FILTER设置为需要mipmaps的其中一个函数,或GL_TEXTURE_WRAP_S或GL_TEXTURE_WRAP_T未设置为GL_CLAMP_TO_EDGE,则纹理图像单元将return(R,G,B,A)=(0,0,0,1)。

您不设置环绕模式,而是设置相同的文档:

  

最初,GL_TEXTURE_WRAP_S设置为GL_REPEAT。

要修复,请将环绕模式设置为GL_CLAMP_TO_EDGE,或者使用256x4纹理而不是256x3(除非有一些障碍,否则我会倾向于后者,GPU会喜欢两个人​​的力量!)。