6

我在 iPhone 着色器 GLSL ES 1.1 中使用 3x3 内核执行卷积。目前我只是在做 9 次纹理查找。有更快的方法吗?一些想法:

  • 将输入图像作为缓冲区而不是纹理传递,以避免调用纹理插值。

  • 从顶点着色器传递 9 个不同的 vec2 坐标(而不是像我目前所做的那样),以鼓励处理器有效地预取纹理。

  • 研究可能适用于此的各种 Apple 扩展。

  • (已添加)调查 GLSL shaderOffset 调用的 ES 等效项(在 ES 下不可用,但可能有等效项)

在硬件方面,我特别关注 iPhone 4S。

4

2 回答 2

7

你确定你不是指 OpenGL ES 2.0 吗?您不能使用 OpenGL ES 1.1 进行任何类型的着色器。我假设前者。

根据我的经验,我发现最快的方法是您列出的第二个项目。我在我的GPUImage框架中进行了几种类型的 3x3 卷积(您可以使用它而不是尝试自己滚动),对于那些我输入水平和垂直方向的纹理偏移量并计算顶点内所需的九个纹理坐标的那些着色器。从那里,我将这些作为变量传递给片段着色器。

这(在大多数情况下)避免了片段着色器中的依赖纹理读取,这在 iOS PowerVR GPU 上非常昂贵。我说“大部分情况下”是因为在 iPhone 4 等较旧的设备上,只有 8 个变量用于避免依赖纹理读取。正如我上周了解到的那样,第九个触发了在旧设备上读取的相关纹理,因此会减慢速度。但是,iPhone 4S 没有这个问题,因为它支持以这种方式使用的更多变量。

我将以下内容用于我的顶点着色器:

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 uniform highp float texelWidth; 
 uniform highp float texelHeight; 

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 void main()
 {
     gl_Position = position;

     vec2 widthStep = vec2(texelWidth, 0.0);
     vec2 heightStep = vec2(0.0, texelHeight);
     vec2 widthHeightStep = vec2(texelWidth, texelHeight);
     vec2 widthNegativeHeightStep = vec2(texelWidth, -texelHeight);

     textureCoordinate = inputTextureCoordinate.xy;
     leftTextureCoordinate = inputTextureCoordinate.xy - widthStep;
     rightTextureCoordinate = inputTextureCoordinate.xy + widthStep;

     topTextureCoordinate = inputTextureCoordinate.xy - heightStep;
     topLeftTextureCoordinate = inputTextureCoordinate.xy - widthHeightStep;
     topRightTextureCoordinate = inputTextureCoordinate.xy + widthNegativeHeightStep;

     bottomTextureCoordinate = inputTextureCoordinate.xy + heightStep;
     bottomLeftTextureCoordinate = inputTextureCoordinate.xy - widthNegativeHeightStep;
     bottomRightTextureCoordinate = inputTextureCoordinate.xy + widthHeightStep;
 }

和片段着色器:

 precision highp float;

 uniform sampler2D inputImageTexture;

 uniform mediump mat3 convolutionMatrix;

 varying vec2 textureCoordinate;
 varying vec2 leftTextureCoordinate;
 varying vec2 rightTextureCoordinate;

 varying vec2 topTextureCoordinate;
 varying vec2 topLeftTextureCoordinate;
 varying vec2 topRightTextureCoordinate;

 varying vec2 bottomTextureCoordinate;
 varying vec2 bottomLeftTextureCoordinate;
 varying vec2 bottomRightTextureCoordinate;

 void main()
 {
     mediump vec4 bottomColor = texture2D(inputImageTexture, bottomTextureCoordinate);
     mediump vec4 bottomLeftColor = texture2D(inputImageTexture, bottomLeftTextureCoordinate);
     mediump vec4 bottomRightColor = texture2D(inputImageTexture, bottomRightTextureCoordinate);
     mediump vec4 centerColor = texture2D(inputImageTexture, textureCoordinate);
     mediump vec4 leftColor = texture2D(inputImageTexture, leftTextureCoordinate);
     mediump vec4 rightColor = texture2D(inputImageTexture, rightTextureCoordinate);
     mediump vec4 topColor = texture2D(inputImageTexture, topTextureCoordinate);
     mediump vec4 topRightColor = texture2D(inputImageTexture, topRightTextureCoordinate);
     mediump vec4 topLeftColor = texture2D(inputImageTexture, topLeftTextureCoordinate);

     mediump vec4 resultColor = topLeftColor * convolutionMatrix[0][0] + topColor * convolutionMatrix[0][1] + topRightColor * convolutionMatrix[0][2];
     resultColor += leftColor * convolutionMatrix[1][0] + centerColor * convolutionMatrix[1][1] + rightColor * convolutionMatrix[1][2];
     resultColor += bottomLeftColor * convolutionMatrix[2][0] + bottomColor * convolutionMatrix[2][1] + bottomRightColor * convolutionMatrix[2][2];

     gl_FragColor = resultColor;
 }

即使有上述注意事项,这个着色器在 iPhone 4 上运行 640x480 帧视频的时间约为 2 毫秒,而 4S 可以使用这样的着色器轻松处理 30 FPS 的 1080p 视频。

于 2012-06-23T01:25:02.737 回答
0

您为什么不使用分离的高斯风格模糊运行两次通道?在第一遍中垂直敲击 3 次,然后在第二遍中敲击水平 3 次。

于 2012-08-17T08:00:56.487 回答