Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9192701
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T20:59:21+00:00 2026-06-17T20:59:21+00:00

I want to make a new filter like GPUImage’s GPUImageTwoInputFilter. here is my code

  • 0

I want to make a new filter like GPUImage’s GPUImageTwoInputFilter.

here is my code . A base class named IFFourInputFilter, it is likely GPUImageTwoInputFilter.

#import "IFFourInputFilter.h"

NSString *const kIFFourInputTextureVertexShaderString = SHADER_STRING
(
 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;
 attribute vec4 inputTextureCoordinate2;
 attribute vec4 inputTextureCoordinate3;
 attribute vec4 inputTextureCoordinate4;

 varying vec2 textureCoordinate;
 varying vec2 textureCoordinate2;
 varying vec2 textureCoordinate3;
 varying vec2 textureCoordinate4;

 void main()
 {
     gl_Position = position;
     textureCoordinate = inputTextureCoordinate.xy;
     textureCoordinate2 = inputTextureCoordinate2.xy;
     textureCoordinate3 = inputTextureCoordinate3.xy;
     textureCoordinate4 = inputTextureCoordinate4.xy;
 }
);


@implementation IFFourInputFilter

#pragma mark -
#pragma mark Initialization and teardown

- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
{
    if (!(self = [self initWithVertexShaderFromString:kIFFourInputTextureVertexShaderString fragmentShaderFromString:fragmentShaderString]))
    {
        return nil;
    }

    return self;
}

- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString;
{
    if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString]))
    {
        return nil;
    }

    inputRotation2 = kGPUImageNoRotation;
    inputRotation3 = kGPUImageNoRotation;
    inputRotation4 = kGPUImageNoRotation;

    hasSetTexture1 = NO;
    hasSetTexture2 = NO;
    hasSetTexture3 = NO;

    hasReceivedFrame1 = NO;
    hasReceivedFrame2 = NO;
    hasReceivedFrame3 = NO;
    hasReceivedFrame4 = NO;
    frameWasVideo1 = NO;
    frameWasVideo2 = NO;
    frameWasVideo3 = NO;
    frameWasVideo4 = NO;
    frameCheckDisabled1 = NO;
    frameCheckDisabled2 = NO;
    frameCheckDisabled3 = NO;
    frameCheckDisabled4 = NO;

    frameTime1 = kCMTimeInvalid;
    frameTime2 = kCMTimeInvalid;
    frameTime3 = kCMTimeInvalid;
    frameTime4 = kCMTimeInvalid;

    runSynchronouslyOnVideoProcessingQueue(^{
        [GPUImageOpenGLESContext useImageProcessingContext];
        filterTextureCoordinateAttribute2 = [filterProgram attributeIndex:@"inputTextureCoordinate2"];

        filterInputTextureUniform2 = [filterProgram uniformIndex:@"inputImageTexture2"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
        glEnableVertexAttribArray(filterTextureCoordinateAttribute2);

        filterTextureCoordinateAttribute3 = [filterProgram attributeIndex:@"inputTextureCoordinate3"];

        filterInputTextureUniform3 = [filterProgram uniformIndex:@"inputImageTexture3"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
        glEnableVertexAttribArray(filterTextureCoordinateAttribute3);

        filterTextureCoordinateAttribute4 = [filterProgram attributeIndex:@"inputTextureCoordinate4"];

        filterInputTextureUniform4 = [filterProgram uniformIndex:@"inputImageTexture4"]; // This does assume a name of "inputImageTexture2" for second input texture in the fragment shader
        glEnableVertexAttribArray(filterTextureCoordinateAttribute4);
    });

    return self;
}

- (void)initializeAttributes;
{
    [super initializeAttributes];
    [filterProgram addAttribute:@"inputTextureCoordinate2"];
    [filterProgram addAttribute:@"inputTextureCoordinate3"];
    [filterProgram addAttribute:@"inputTextureCoordinate4"];
}

- (void)disableFrameCheck1;
{
    frameCheckDisabled1 = YES;
}

- (void)disableFrameCheck2;
{
    frameCheckDisabled2 = YES;
}

- (void)disableFrameCheck3;
{
    frameCheckDisabled3 = YES;
}

- (void)disableFrameCheck4;
{
    frameCheckDisabled4 = YES;
}

#pragma mark -
#pragma mark Rendering

- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates sourceTexture:(GLuint)sourceTexture;
{
    if (self.preventRendering)
    {
        return;
    }

    [GPUImageOpenGLESContext setActiveShaderProgram:filterProgram];
    [self setUniformsForProgramAtIndex:0];

    [self setFilterFBO];

    glClearColor(backgroundColorRed, backgroundColorGreen, backgroundColorBlue, backgroundColorAlpha);
    glClear(GL_COLOR_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, sourceTexture);
    glUniform1i(filterInputTextureUniform, 2);

    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, filterSourceTexture2);
    glUniform1i(filterInputTextureUniform2, 3);

    glActiveTexture(GL_TEXTURE4);
    glBindTexture(GL_TEXTURE_2D, filterSourceTexture3);
    glUniform1i(filterInputTextureUniform3, 4);

    glActiveTexture(GL_TEXTURE5);
    glBindTexture(GL_TEXTURE_2D, filterSourceTexture4);
    glUniform1i(filterInputTextureUniform4, 5);

    glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, vertices);
    glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
    glVertexAttribPointer(filterTextureCoordinateAttribute2, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation2]);
    glVertexAttribPointer(filterTextureCoordinateAttribute3, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation3]);
    glVertexAttribPointer(filterTextureCoordinateAttribute4, 2, GL_FLOAT, 0, 0, [[self class] textureCoordinatesForRotation:inputRotation4]);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

- (void)releaseInputTexturesIfNeeded;
{
    if (shouldConserveMemoryForNextFrame)
    {
        [firstTextureDelegate textureNoLongerNeededForTarget:self];
        [textureDelegate2 textureNoLongerNeededForTarget:self];
        [textureDelegate3 textureNoLongerNeededForTarget:self];
        [textureDelegate4 textureNoLongerNeededForTarget:self];
        shouldConserveMemoryForNextFrame = NO;
    }
}

#pragma mark -
#pragma mark GPUImageInput

- (NSInteger)nextAvailableTextureIndex;
{
    if (!hasSetTexture1){
        return 0;
    }else if (!hasSetTexture2) {
        return 1;
    }else if (!hasSetTexture3) {
        return 2;
    }else{
        return 3;
    }
}

- (void)setInputTexture:(GLuint)newInputTexture atIndex:(NSInteger)textureIndex;
{
    switch (textureIndex) {
        case 0:
            filterSourceTexture = newInputTexture;
            hasSetTexture1 = YES;
            break;
        case 1:
            filterSourceTexture2 = newInputTexture;
            hasSetTexture2 = YES;
            break;
        case 2:
            filterSourceTexture3 = newInputTexture;
            hasSetTexture3 = YES;
            break;
        case 3:
            filterSourceTexture4 = newInputTexture;
            break;
        default:
            break;
    }
}

- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
{
    if (textureIndex == 0)
    {
        [super setInputSize:newSize atIndex:textureIndex];

        if (CGSizeEqualToSize(newSize, CGSizeZero))
        {
            hasSetTexture1 = NO;
        }
    }
}

- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex;
{
    switch (textureIndex) {
        case 0:
            inputRotation = newInputRotation;
            break;
        case 1:
            inputRotation2 = newInputRotation;
            break;
        case 2:
            inputRotation3 = newInputRotation;
            break;
        case 3:
            inputRotation4 = newInputRotation;
            break;
        default:
            break;
    }
}

- (CGSize)rotatedSize:(CGSize)sizeToRotate forIndex:(NSInteger)textureIndex;
{
    CGSize rotatedSize = sizeToRotate;

    GPUImageRotationMode rotationToCheck;
    switch (textureIndex) {
        case 0:
            rotationToCheck = inputRotation;
            break;
        case 1:
            rotationToCheck = inputRotation2;
            break;
        case 2:
            rotationToCheck = inputRotation3;
            break;
        case 3:
            rotationToCheck = inputRotation4;
            break;
        default:
            break;
    }

    if (GPUImageRotationSwapsWidthAndHeight(rotationToCheck))
    {
        rotatedSize.width = sizeToRotate.height;
        rotatedSize.height = sizeToRotate.width;
    }

    return rotatedSize;
}

- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
{
    outputTextureRetainCount = [targets count];

    // You can set up infinite update loops, so this helps to short circuit them
    if (hasReceivedFrame1 && hasReceivedFrame2 && hasReceivedFrame3 && hasReceivedFrame4)
    {
        return;
    }

    BOOL updatedMovieFrameOppositeStillImage = NO;

    switch (textureIndex) {
        case 0:
            hasReceivedFrame1 = YES;
            frameTime1 = frameTime;
            if (frameCheckDisabled2)
            {
                hasReceivedFrame2 = YES;
            }
            if (frameCheckDisabled3)
            {
                hasReceivedFrame3 = YES;
            }
            if (frameCheckDisabled4)
            {
                hasReceivedFrame4 = YES;
            }

            if (!CMTIME_IS_INDEFINITE(frameTime))
            {
                if (CMTIME_IS_INDEFINITE(frameTime2) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime4))
                {
                    updatedMovieFrameOppositeStillImage = YES;
                }
            }
            break;
        case 1:
            hasReceivedFrame2 = YES;
            frameTime2 = frameTime;
            if (frameCheckDisabled1)
            {
                hasReceivedFrame1 = YES;
            }
            if (frameCheckDisabled3)
            {
                hasReceivedFrame3 = YES;
            }
            if (frameCheckDisabled4)
            {
                hasReceivedFrame4 = YES;
            }

            if (!CMTIME_IS_INDEFINITE(frameTime))
            {
                if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime4))
                {
                    updatedMovieFrameOppositeStillImage = YES;
                }
            }
            break;
        case 2:
            hasReceivedFrame3 = YES;
            frameTime3 = frameTime;
            if (frameCheckDisabled1)
            {
                hasReceivedFrame1 = YES;
            }
            if (frameCheckDisabled2)
            {
                hasReceivedFrame2 = YES;
            }
            if (frameCheckDisabled4)
            {
                hasReceivedFrame4 = YES;
            }

            if (!CMTIME_IS_INDEFINITE(frameTime))
            {
                if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime2) && CMTIME_IS_INDEFINITE(frameTime4))
                {
                    updatedMovieFrameOppositeStillImage = YES;
                }
            }
            break;
        case 3:
            hasReceivedFrame4 = YES;
            frameTime4 = frameTime;
            if (frameCheckDisabled1)
            {
                hasReceivedFrame1 = YES;
            }
            if (frameCheckDisabled3)
            {
                hasReceivedFrame3 = YES;
            }
            if (frameCheckDisabled2)
            {
                hasReceivedFrame2 = YES;
            }

            if (!CMTIME_IS_INDEFINITE(frameTime))
            {
                if (CMTIME_IS_INDEFINITE(frameTime1) && CMTIME_IS_INDEFINITE(frameTime3) && CMTIME_IS_INDEFINITE(frameTime2))
                {
                    updatedMovieFrameOppositeStillImage = YES;
                }
            }
            break;
        default:
            break;
    }

    // || (hasReceivedFirstFrame && secondFrameCheckDisabled) || (hasReceivedSecondFrame && firstFrameCheckDisabled)
    if ((hasReceivedFrame1 && hasReceivedFrame2 && hasReceivedFrame3 && hasReceivedFrame4) || updatedMovieFrameOppositeStillImage)
    {
        [super newFrameReadyAtTime:frameTime atIndex:0];
        hasReceivedFrame1 = NO;
        hasReceivedFrame2 = NO;
        hasReceivedFrame3 = NO;
        hasReceivedFrame4 = NO;
    }
}

- (void)setTextureDelegate:(id<GPUImageTextureDelegate>)newTextureDelegate atIndex:(NSInteger)textureIndex;
{
    switch (textureIndex) {
        case 0:
            firstTextureDelegate = newTextureDelegate;
            break;
        case 1:
            textureDelegate2 = newTextureDelegate;
            break;
        case 2:
            textureDelegate3 = newTextureDelegate;
            break;
        case 3:
            textureDelegate4 = newTextureDelegate;
            break;
        default:
            break;
    }
}

@end

A class named IFAmaroFilter extend IFFourInputFilter.

#import "IFAmaroFilter.h"

NSString *const kIFAmaroFilterFragmentShaderString = SHADER_STRING
(
 precision lowp float;

 varying highp vec2 textureCoordinate;

 uniform sampler2D inputImageTexture;
 uniform sampler2D inputImageTexture2; //blowout;
 uniform sampler2D inputImageTexture3; //overlay;
 uniform sampler2D inputImageTexture4; //map

 void main()
 {
     vec4 texel = texture2D(inputImageTexture, textureCoordinate);
     vec3 bbTexel = texture2D(inputImageTexture2, textureCoordinate).rgb;

     texel.r = texture2D(inputImageTexture3, vec2(bbTexel.r, texel.r)).r;
     texel.g = texture2D(inputImageTexture3, vec2(bbTexel.g, texel.g)).g;
     texel.b = texture2D(inputImageTexture3, vec2(bbTexel.b, texel.b)).b;

     vec4 mapped;
     mapped.r = texture2D(inputImageTexture4, vec2(texel.r, 0.16666)).r;
     mapped.g = texture2D(inputImageTexture4, vec2(texel.g, .5)).g;
     mapped.b = texture2D(inputImageTexture4, vec2(texel.b, .83333)).b;
     mapped.a = 1.0;

     gl_FragColor = texel;
 }
 );

@implementation IFAmaroFilter

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

    return self;
}

@end

when I use the filter I got a black output. code below:

    filter = [[IFAmaroFilter alloc] init];
    GPUImagePicture *gp1 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"blackboard1024" ofType:@"png"]]];
    GPUImagePicture *gp2 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"overlayMap" ofType:@"png"]]];
    GPUImagePicture *gp3 = [[GPUImagePicture alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"amaroMap" ofType:@"png"]]];

    [stillCamera addTarget:filter atTextureLocation:0];
    [gp1 addTarget:filter atTextureLocation:1];
    [gp1 processImage];
    [gp2 addTarget:filter atTextureLocation:2];
    [gp2 processImage];
    [gp3 addTarget:filter atTextureLocation:3];
    [gp3 processImage];
    [filter addTarget:(GPUImageView *)self.view];
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T20:59:22+00:00Added an answer on June 17, 2026 at 8:59 pm

    I found the GPUImagePicture will be auto release, so the filter will not receive the texture.
    If u met the same question, check the texture’s life control carefully, watch when they be dealloc.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I don't want to make a new instance of Form1 in the class, and
all I want to make a filter just like what instagram's. I use an
I want to make new stackpanal from another stackpanal already made before but if
I am new android app developer i want make app for tablets and phone
I want to make a function for a new datatype in Standard ML, the
I am new to .NET and ideally want to make several layers of abstraction
I want to make a smart keyboard that can learn and save new words
i'm new to gooogle map developing.i want to make a map as follows. http://edition.cnn.com/SPECIALS/world/arab-unrest/index.html
I want to make routing for form when submitting the form, $reportRoute = new
We are designing a new application for Android and we want to make it

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.