Работая на другой фильтр OpenGL ES изображений на основе this:GPUImage пользовательских OpenGL ES шейдеры приводят к черному изображению
uniform sampler2D texture;
uniform float amount;
uniform vec2 texSize;
varying vec2 texCoord;
void main() {
vec4 color = texture2D(texture, texCoord);
vec4 orig = color;
/* High pass filter */
vec4 highpass = color * 5.0;
float dx = 1.0/texSize.x;
float dy = 1.0/texSize.y;
highpass += texture2D(texture, texCoord + vec2(-dx, -dy)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(dx, -dy)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(dx, dy)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(-dx, dy)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(-dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(dx * 2.0, dy * 2.0)) * -0.625;
highpass += texture2D(texture, texCoord + vec2(-dx * 2.0, dy * 2.0)) * -0.625;
highpass.a = 1.0;
/* Overlay blend */
vec3 overlay = vec3(1.0);
if (highpass.r <= 0.5) {
overlay.r = 2.0 * color.r * highpass.r;
} else {
overlay.r = 1.0 - 2.0 * (1.0 - color.r) * (1.0 - highpass.r);
}
if (highpass.g <= 0.5) {
overlay.g = 2.0 * color.g * highpass.g;
} else {
overlay.g = 1.0 - 2.0 * (1.0 - color.g) * (1.0 - highpass.g);
}
if (highpass.b <= 0.5) {
overlay.b = 2.0 * color.b * highpass.b;
} else {
overlay.b = 1.0 - 2.0 * (1.0 - color.b) * (1.0 - highpass.b);
}
color.rgb = (overlay * 0.8) + (orig.rgb * 0.2);
/* Desaturated hard light */
vec3 desaturated = vec3(orig.r + orig.g + orig.b/3.0);
if (desaturated.r <= 0.5) {
color.rgb = 2.0 * color.rgb * desaturated;
} else {
color.rgb = vec3(1.0) - vec3(2.0) * (vec3(1.0) - color.rgb) * (vec3(1.0) - desaturated);
}
color = (orig * 0.6) + (color * 0.4);
/* Add back some color */
float average = (color.r + color.g + color.b)/3.0;
color.rgb += (average - color.rgb) * (1.0 - 1.0/(1.001 - 0.45));
gl_FragColor = (color * amount) + (orig * (1.0 - amount));
}
За мой question yesterday, я знал, что для назначения точности для каждого поплавка и VEC. На этот раз он скомпилировался отлично, однако, когда я иду на применение фильтра в GPUImage (например, установив значение clarity
на 0.8
), изображение становится черным. Моя кишка говорит мне, что это связано с размером текстуры, но, не зная, как GPUImage справляется с этим, я немного застрял.
Вот моя реализация в Objective-C:
.h
#import <GPUImage/GPUImage.h>
@interface GPUImageClarityFilter : GPUImageFilter
{
GLint clarityUniform;
}
// Gives the image a gritty, surreal contrasty effect
// Value 0 to 1
@property (readwrite, nonatomic) GLfloat clarity;
@end
.m
#import "GPUImageClarityFilter.h"
#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kGPUImageClarityFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
uniform lowp float clarity;
uniform highp vec2 textureSize;
varying highp vec2 textureCoordinate;
void main() {
highp vec4 color = texture2D(inputImageTexture, textureCoordinate);
highp vec4 orig = color;
/* High pass filter */
highp vec4 highpass = color * 5.0;
highp float dx = 1.0/textureSize.x;
highp float dy = 1.0/textureSize.y;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx, -dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx, -dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx, dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx, dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx * 2.0, dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx * 2.0, dy * 2.0)) * -0.625;
highpass.a = 1.0;
/* Overlay blend */
highp vec3 overlay = vec3(1.0);
if (highpass.r <= 0.5) {
overlay.r = 2.0 * color.r * highpass.r;
} else {
overlay.r = 1.0 - 2.0 * (1.0 - color.r) * (1.0 - highpass.r);
}
if (highpass.g <= 0.5) {
overlay.g = 2.0 * color.g * highpass.g;
} else {
overlay.g = 1.0 - 2.0 * (1.0 - color.g) * (1.0 - highpass.g);
}
if (highpass.b <= 0.5) {
overlay.b = 2.0 * color.b * highpass.b;
} else {
overlay.b = 1.0 - 2.0 * (1.0 - color.b) * (1.0 - highpass.b);
}
color.rgb = (overlay * 0.8) + (orig.rgb * 0.2);
/* Desaturated hard light */
highp vec3 desaturated = vec3(orig.r + orig.g + orig.b/3.0);
if (desaturated.r <= 0.5) {
color.rgb = 2.0 * color.rgb * desaturated;
} else {
color.rgb = vec3(1.0) - vec3(2.0) * (vec3(1.0) - color.rgb) * (vec3(1.0) - desaturated);
}
color = (orig * 0.6) + (color * 0.4);
/* Add back some color */
highp float average = (color.r + color.g + color.b)/3.0;
color.rgb += (average - color.rgb) * (1.0 - 1.0/(1.001 - 0.45));
gl_FragColor = (color * clarity) + (orig * (1.0 - clarity));
}
);
#else
NSString *const kGPUImageClarityFragmentShaderString = SHADER_STRING
(
uniform sampler2D inputImageTexture;
uniform float clarity;
uniform vec2 textureSize;
varying vec2 textureCoordinate;
void main() {
vec4 color = texture2D(inputImageTexture, textureCoordinate);
vec4 orig = color;
/* High pass filter */
vec4 highpass = color * 5.0;
float dx = 1.0/textureSize.x;
float dy = 1.0/textureSize.y;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx, -dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx, -dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx, dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx, dy)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx * 2.0, -dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(dx * 2.0, dy * 2.0)) * -0.625;
highpass += texture2D(inputImageTexture, textureCoordinate + vec2(-dx * 2.0, dy * 2.0)) * -0.625;
highpass.a = 1.0;
/* Overlay blend */
vec3 overlay = vec3(1.0);
if (highpass.r <= 0.5) {
overlay.r = 2.0 * color.r * highpass.r;
} else {
overlay.r = 1.0 - 2.0 * (1.0 - color.r) * (1.0 - highpass.r);
}
if (highpass.g <= 0.5) {
overlay.g = 2.0 * color.g * highpass.g;
} else {
overlay.g = 1.0 - 2.0 * (1.0 - color.g) * (1.0 - highpass.g);
}
if (highpass.b <= 0.5) {
overlay.b = 2.0 * color.b * highpass.b;
} else {
overlay.b = 1.0 - 2.0 * (1.0 - color.b) * (1.0 - highpass.b);
}
color.rgb = (overlay * 0.8) + (orig.rgb * 0.2);
/* Desaturated hard light */
vec3 desaturated = vec3(orig.r + orig.g + orig.b/3.0);
if (desaturated.r <= 0.5) {
color.rgb = 2.0 * color.rgb * desaturated;
} else {
color.rgb = vec3(1.0) - vec3(2.0) * (vec3(1.0) - color.rgb) * (vec3(1.0) - desaturated);
}
color = (orig * 0.6) + (color * 0.4);
/* Add back some color */
float average = (color.r + color.g + color.b)/3.0;
color.rgb += (average - color.rgb) * (1.0 - 1.0/(1.001 - 0.45));
gl_FragColor = (color * clarity) + (orig * (1.0 - clarity));
}
);
#endif
@implementation GPUImageClarityFilter
@synthesize clarity = _clarity;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageClarityFragmentShaderString]))
{
return nil;
}
clarityUniform = [filterProgram uniformIndex:@"clarity"];
self.clarity = 0.0;
return self;
}
#pragma mark -
#pragma mark Accessors
- (void)setClarity:(GLfloat)clarity;
{
_clarity = clarity;
[self setFloat:_clarity forUniform:clarityUniform program:filterProgram];
}
@end
Еще одна вещь, которую я думал, что делать применяет встроенную GPUImage в в фильтрах нижних частот и высоких частот, но у меня возникает ощущение, что в итоге получится довольно неуклюжий olution.
Спасибо, Брэд, я сделаю снимок. – brandonscript
Провел некоторое время, играя с ним, но, к сожалению, я недостаточно знаком с написанием шейдеров, чтобы выяснить, как интегрировать 3x3TextureSamplingFilter. Вместо этого я просто играл с некоторыми жестко закодированными значениями для текстуры и приземлялся на «320.0», придавая мне отличный эффект. – brandonscript
Черт, и, конечно, это работает только в том случае, если входное изображение имеет конкретное измерение. – brandonscript