2020-06-24 18:06:08 +03:00

306 lines
8.4 KiB
Objective-C

#import "PGPhotoBlurPass.h"
#import "GPUImageTwoInputFilter.h"
#import "GPUImageThreeInputFilter.h"
#import "PGPhotoGaussianBlurFilter.h"
NSString *const PGPhotoRadialBlurShaderString = PGShaderString
(
varying highp vec2 texCoord;
varying highp vec2 texCoord2;
uniform sampler2D sourceImage;
uniform sampler2D inputImageTexture2;
uniform lowp float excludeSize;
uniform lowp vec2 excludePoint;
uniform lowp float excludeFalloff;
uniform highp float aspectRatio;
void main()
{
lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);
lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord2);
highp vec2 texCoordToUse = vec2(texCoord2.x, (texCoord2.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp float distanceFromCenter = distance(excludePoint, texCoordToUse);
gl_FragColor = mix(blurredImageColor, sharpImageColor, smoothstep(1.0, excludeFalloff, clamp(distanceFromCenter / excludeSize, 0.0, 1.0)));
}
);
NSString *const PGPhotoLinearBlurShaderString = PGShaderString
(
varying highp vec2 texCoord;
varying highp vec2 texCoord2;
uniform sampler2D sourceImage;
uniform sampler2D inputImageTexture2;
uniform lowp float excludeSize;
uniform lowp vec2 excludePoint;
uniform lowp float excludeFalloff;
uniform highp float angle;
uniform highp float aspectRatio;
void main()
{
lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);
lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord2);
highp vec2 texCoordToUse = vec2(texCoord2.x, (texCoord2.y * aspectRatio + 0.5 - 0.5 * aspectRatio));
highp float distanceFromCenter = abs((texCoordToUse.x - excludePoint.x) * cos(angle) + (texCoordToUse.y - excludePoint.y) * sin(angle));
gl_FragColor = mix(blurredImageColor, sharpImageColor, smoothstep(1.0, excludeFalloff, clamp(distanceFromCenter / excludeSize, 0.0, 1.0)));
}
);
NSString *const PGPhotoMaskedBlurShaderString = PGShaderString
(
varying highp vec2 texCoord;
varying highp vec2 texCoord2;
varying highp vec2 texCoord3;
uniform sampler2D sourceImage;
uniform sampler2D inputImageTexture2;
uniform sampler2D inputImageTexture3;
void main()
{
lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);
lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord2);
lowp vec4 maskImageColor = texture2D(inputImageTexture3, texCoord3);
gl_FragColor = mix(blurredImageColor, sharpImageColor, maskImageColor.r);
}
);
@interface PGPhotoBlurFilter : GPUImageOutput <GPUImageInput>
{
PGPhotoGaussianBlurFilter *_blurFilter;
GPUImageTwoInputFilter *_radialFocusFilter;
GPUImageTwoInputFilter *_linearFocusFilter;
GPUImageThreeInputFilter *_maskedFilter;
GPUImageOutput <GPUImageInput> *_currentFocusFilter;
bool _endProcessing;
}
@end
@implementation PGPhotoBlurFilter
- (instancetype)init
{
self = [super init];
if (self != nil)
{
_blurFilter = [[PGPhotoGaussianBlurFilter alloc] init];
_radialFocusFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:PGPhotoRadialBlurShaderString];
_linearFocusFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:PGPhotoLinearBlurShaderString];
}
return self;
}
- (void)setType:(PGBlurToolType)type
{
id<GPUImageInput> target = nil;
if (_currentFocusFilter.targets.count > 0)
target = _currentFocusFilter.targets[0];
[_currentFocusFilter removeAllTargets];
switch (type)
{
case PGBlurToolTypeRadial:
{
_currentFocusFilter = _radialFocusFilter;
}
break;
case PGBlurToolTypeLinear:
{
_currentFocusFilter = _linearFocusFilter;
}
break;
case PGBlurToolTypePortrait:
{
_currentFocusFilter = _maskedFilter;
}
default:
break;
}
if (target != nil)
[_currentFocusFilter addTarget:target atTextureLocation:0];
[_blurFilter removeAllTargets];
[_blurFilter addTarget:_currentFocusFilter atTextureLocation:1];
}
- (void)setExcludeSize:(CGFloat)excludeSize
{
[_radialFocusFilter setFloat:(float)excludeSize forUniformName:@"excludeSize"];
[_linearFocusFilter setFloat:(float)excludeSize forUniformName:@"excludeSize"];
}
- (void)setExcludeFalloff:(CGFloat)excludeFalloff
{
[_radialFocusFilter setFloat:(float)excludeFalloff forUniformName:@"excludeFalloff"];
[_linearFocusFilter setFloat:(float)excludeFalloff forUniformName:@"excludeFalloff"];
}
- (void)setExcludePoint:(CGPoint)excludePoint
{
[_radialFocusFilter setPoint:excludePoint forUniformName:@"excludePoint"];
[_linearFocusFilter setPoint:excludePoint forUniformName:@"excludePoint"];
}
- (void)setAngle:(CGFloat)angle
{
[_linearFocusFilter setFloat:(float)angle forUniformName:@"angle"];
}
#pragma mark GPUImageOutput
- (void)setTargetToIgnoreForUpdates:(id<GPUImageInput>)targetToIgnoreForUpdates
{
[_currentFocusFilter setTargetToIgnoreForUpdates:targetToIgnoreForUpdates];
}
- (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation
{
[_currentFocusFilter addTarget:newTarget atTextureLocation:textureLocation];
}
- (void)removeTarget:(id<GPUImageInput>)targetToRemove
{
[_currentFocusFilter removeTarget:targetToRemove];
}
- (void)removeAllTargets
{
[_currentFocusFilter removeAllTargets];
}
- (void)setFrameProcessingCompletionBlock:(void (^)(GPUImageOutput *, CMTime))frameProcessingCompletionBlock
{
[_currentFocusFilter setFrameProcessingCompletionBlock:frameProcessingCompletionBlock];
}
- (void (^)(GPUImageOutput *, CMTime))frameProcessingCompletionBlock
{
return [_currentFocusFilter frameProcessingCompletionBlock];
}
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)__unused textureIndex
{
[_blurFilter newFrameReadyAtTime:frameTime atIndex:0];
[_currentFocusFilter newFrameReadyAtTime:frameTime atIndex:0];
}
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)__unused textureIndex
{
[_blurFilter setInputFramebuffer:newInputFramebuffer atIndex:0];
[_currentFocusFilter setInputFramebuffer:newInputFramebuffer atIndex:0];
}
- (NSInteger)nextAvailableTextureIndex
{
return 0;
}
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex
{
[_blurFilter setInputSize:newSize atIndex:textureIndex];
[_radialFocusFilter setInputSize:newSize atIndex:textureIndex];
[_linearFocusFilter setInputSize:newSize atIndex:textureIndex];
[_maskedFilter setInputSize:newSize atIndex:textureIndex];
CGFloat aspectRatio = newSize.height / newSize.width;
[_radialFocusFilter setFloat:(float)aspectRatio forUniformName:@"aspectRatio"];
[_linearFocusFilter setFloat:(float)aspectRatio forUniformName:@"aspectRatio"];
}
- (void)setInputRotation:(GPUImageRotationMode)newInputRotation atIndex:(NSInteger)textureIndex
{
[_blurFilter setInputRotation:newInputRotation atIndex:textureIndex];
[_radialFocusFilter setInputRotation:newInputRotation atIndex:textureIndex];
[_linearFocusFilter setInputRotation:newInputRotation atIndex:textureIndex];
[_maskedFilter setInputRotation:newInputRotation atIndex:textureIndex];
}
- (CGSize)maximumOutputSize
{
return CGSizeZero;
}
- (void)endProcessing
{
if (!_endProcessing)
{
_endProcessing = true;
[_currentFocusFilter endProcessing];
}
}
- (BOOL)wantsMonochromeInput
{
return false;
}
- (void)setCurrentlyReceivingMonochromeInput:(BOOL)__unused newValue
{
}
@end
@implementation PGPhotoBlurPass
- (instancetype)init
{
self = [super init];
if (self != nil)
{
PGPhotoBlurFilter *filter = [[PGPhotoBlurFilter alloc] init];
_filter = filter;
}
return self;
}
- (void)setType:(PGBlurToolType)type
{
_type = type;
[(PGPhotoBlurFilter *)_filter setType:type];
}
- (void)setSize:(CGFloat)size
{
_size = size;
[(PGPhotoBlurFilter *)_filter setExcludeSize:size];
}
- (void)setFalloff:(CGFloat)falloff
{
_falloff = falloff;
[(PGPhotoBlurFilter *)_filter setExcludeFalloff:falloff];
}
- (void)setPoint:(CGPoint)point
{
_point = point;
[(PGPhotoBlurFilter *)_filter setExcludePoint:point];
}
- (void)setAngle:(CGFloat)angle
{
_angle = angle;
[(PGPhotoBlurFilter *)_filter setAngle:angle + (CGFloat)M_PI_2];
}
@end