GPUImage着色器崩溃“错误:一个或多个连接的着色器未成功编译”

时间:2015-08-13 20:23:53

标签: ios objective-c opengl-es gpuimage

我正在尝试基于this Javascript为GPUImage构建一个Vibrance过滤器:

/**
 * @filter       Vibrance
 * @description  Modifies the saturation of desaturated colors, leaving saturated colors unmodified.
 * @param amount -1 to 1 (-1 is minimum vibrance, 0 is no change, and 1 is maximum vibrance)
 */
function vibrance(amount) {
    gl.vibrance = gl.vibrance || new Shader(null, '\
        uniform sampler2D texture;\
        uniform float amount;\
        varying vec2 texCoord;\
        void main() {\
            vec4 color = texture2D(texture, texCoord);\
            float average = (color.r + color.g + color.b) / 3.0;\
            float mx = max(color.r, max(color.g, color.b));\
            float amt = (mx - average) * (-amount * 3.0);\
            color.rgb = mix(color.rgb, vec3(mx), amt);\
            gl_FragColor = color;\
        }\
    ');

    simpleShader.call(this, gl.vibrance, {
        amount: clamp(-1, amount, 1)
    });

    return this;
}

有人会认为我应该能够更多/更少地复制着色器块:

GPUImageVibranceFilter.h

@interface GPUImageVibranceFilter : GPUImageFilter
{
    GLint vibranceUniform;
}

// Modifies the saturation of desaturated colors, leaving saturated colors unmodified.
// Value -1 to 1 (-1 is minimum vibrance, 0 is no change, and 1 is maximum vibrance)
@property (readwrite, nonatomic) CGFloat vibrance;

@end

GPUImageVibranceFilter.m

#import "GPUImageVibranceFilter.h"

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageVibranceFragmentShaderString = SHADER_STRING
(
    uniform sampler2D inputImageTexture;
    uniform float vibrance;
    varying highp vec2 textureCoordinate;
    void main() {
        vec4 color = texture2D(inputImageTexture, textureCoordinate);
        float average = (color.r + color.g + color.b) / 3.0;
        float mx = max(color.r, max(color.g, color.b));
        float amt = (mx - average) * (-vibrance * 3.0);
        color.rgb = mix(color.rgb, vec3(mx), amt);
        gl_FragColor = color;
    }
);
#else
NSString *const kGPUImageVibranceFragmentShaderString = SHADER_STRING
(
    uniform sampler2D inputImageTexture;
    uniform float vibrance;
    varying vec2 textureCoordinate;
    void main() {
        vec4 color = texture2D(inputImageTexture, textureCoordinate);
        float average = (color.r + color.g + color.b) / 3.0;
        float mx = max(color.r, max(color.g, color.b));
        float amt = (mx - average) * (-vibrance * 3.0);
        color.rgb = mix(color.rgb, vec3(mx), amt);
        gl_FragColor = color;
    }
);
#endif

@implementation GPUImageVibranceFilter

@synthesize vibrance = _vibrance;

#pragma mark -
#pragma mark Initialization and teardown

- (id)init;
{
    if (!(self = [super initWithFragmentShaderFromString:kGPUImageVibranceFragmentShaderString]))
    {
        return nil;
    }

    vibranceUniform = [filterProgram uniformIndex:@"vibrance"];
    self.vibrance = 0.0;

    return self;
}

#pragma mark -
#pragma mark Accessors

- (void)setVibrance:(CGFloat)vibrance;
{
    _vibrance = vibrance;

    [self setFloat:_vibrance forUniform:vibranceUniform program:filterProgram];
}

@end

但是这不会编译,崩溃:

Failed to compile fragment shader
Program link log: ERROR: One or more attached shaders not successfully compiled
Fragment shader compile log: (null)
Vertex shader compile log: (null)

错误当然很明显,但是对于OpenGL ES着色器缺乏经验,我不知道问题到底是什么。

1 个答案:

答案 0 :(得分:2)

  

有人会认为我应该能够更多/更少地复制着色器块。

在桌面GLSL中可能就是这种情况,但在OpenGL ES中,您无法声明float变量(这包括从float派生的类型,例如vec2mat4 (如果没有先设置精度) - 片段着色器中没有float的预定义默认精度。

实现保证在片段着色器中支持mediumplowp浮点精度。但是,在将highp设置为默认值之前,您必须先检查。

这整个问题对我来说是“缺少精度”,但为什么编译器在编译日志中没有告诉你这个我真的不知道。

刷上4.5.3 Default Precision Qualifiers(第35-36页)

<小时/>

关于您使用CGFloat

的附注

小心使用CGFloat

根据您的编译目标(主机是32位还是64位),该类型将是单精度或双精度。如果您将声明为CGFloat的内容传递给GL,请停止= P

使用GLfloat代替,因为它总是像GL要求的那样是单精度的。

有关详细信息,请参阅related answer I wrote