4
4
//
5
5
// Created by Thayer J Andrews on 7/9/14.
6
6
//
7
- //
8
- // This effect makes use of algorithms and GLSL shaders from GPUImage whose
9
- // license is included here.
10
- //
11
- // <Begin GPUImage license>
12
- //
13
- // Copyright (c) 2012, Brad Larson, Ben Cochran, Hugues Lismonde, Keitaroh
14
- // Kobayashi, Alaric Cole, Matthew Clark, Jacob Gundersen, Chris Williams.
15
- // All rights reserved.
16
- //
17
- // Redistribution and use in source and binary forms, with or without
18
- // modification, are permitted provided that the following conditions are met:
19
- //
20
- // Redistributions of source code must retain the above copyright notice, this
21
- // list of conditions and the following disclaimer.
22
- // Redistributions in binary form must reproduce the above copyright notice,
23
- // this list of conditions and the following disclaimer in the documentation
24
- // and/or other materials provided with the distribution.
25
- // Neither the name of the GPUImage framework nor the names of its contributors
26
- // may be used to endorse or promote products derived from this software
27
- // without specific prior written permission.
28
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
- // POSSIBILITY OF SUCH DAMAGE.
39
- //
40
- // <End GPUImage license>
41
7
42
8
43
9
#import " CCEffectHue.h"
44
10
#import " CCEffect_Private.h"
45
11
#import " CCRenderer.h"
46
12
#import " CCTexture.h"
47
13
48
- #define CCEFFECTHUE_USES_COLOR_MATRIX 1
49
-
50
-
51
14
static float conditionHue (float hue);
52
15
53
- #if CCEFFECTHUE_USES_COLOR_MATRIX
54
16
static GLKMatrix4 matrixWithHue (float hue);
55
- #endif
56
17
57
18
58
19
@interface CCEffectHue ()
59
- #if CCEFFECTHUE_USES_COLOR_MATRIX
60
20
@property (nonatomic , strong ) NSValue *hueRotationMtx;
61
- #else
62
- @property (nonatomic , strong ) NSNumber *conditionedHue;
63
- #endif
64
21
@end
65
22
66
23
@@ -74,21 +31,13 @@ -(id)init
74
31
-(id )initWithHue : (float )hue
75
32
{
76
33
NSArray *uniforms = @[
77
- #if CCEFFECTHUE_USES_COLOR_MATRIX
78
34
[CCEffectUniform uniform: @" mat4" name: @" u_hueRotationMtx" value: [NSValue valueWithGLKMatrix4: GLKMatrix4Identity]]
79
- #else
80
- [CCEffectUniform uniform: @" float" name: @" u_hue" value: [NSNumber numberWithFloat: hue]]
81
- #endif
82
35
];
83
36
84
37
if ((self = [super initWithFragmentUniforms: uniforms vertexUniforms: nil varyings: nil ]))
85
38
{
86
39
_hue = hue;
87
- #if CCEFFECTHUE_USES_COLOR_MATRIX
88
40
_hueRotationMtx = [NSValue valueWithGLKMatrix4: matrixWithHue (conditionHue (hue))];
89
- #else
90
- _conditionedHue = [NSNumber numberWithFloat: conditionHue (hue)];
91
- #endif
92
41
self.debugName = @" CCEffectHue" ;
93
42
}
94
43
return self;
@@ -106,47 +55,9 @@ -(void)buildFragmentFunctions
106
55
CCEffectFunctionInput *input = [[CCEffectFunctionInput alloc ] initWithType: @" vec4" name: @" inputValue" initialSnippet: @" cc_FragColor * texture2D(cc_PreviousPassTexture, cc_FragTexCoord1)" snippet: @" texture2D(cc_PreviousPassTexture, cc_FragTexCoord1)" ];
107
56
108
57
// The non-color matrix shader is based on the hue filter in GPUImage - https://github.com/BradLarson/GPUImage
109
- #if CCEFFECTHUE_USES_COLOR_MATRIX
110
58
NSString * effectBody = CC_GLSL (
111
59
return u_hueRotationMtx * inputValue;
112
60
);
113
- #else
114
- NSString * effectBody = CC_GLSL (
115
- const highp vec4 kRGBToYPrime = vec4 (0.299 , 0.587 , 0.114 , 0.0 );
116
- const highp vec4 kRGBToI = vec4 (0.595716 , -0.274453 , -0.321263 , 0.0 );
117
- const highp vec4 kRGBToQ = vec4 (0.211456 , -0.522591 , 0.31135 , 0.0 );
118
-
119
- const highp vec4 kYIQToR = vec4 (1.0 , 0.9563 , 0.6210 , 0.0 );
120
- const highp vec4 kYIQToG = vec4 (1.0 , -0.2721 , -0.6474 , 0.0 );
121
- const highp vec4 kYIQToB = vec4 (1.0 , -1.1070 , 1.7046 , 0.0 );
122
-
123
- // Convert to YIQ
124
- highp float YPrime = dot (inputValue, kRGBToYPrime );
125
- highp float I = dot (inputValue, kRGBToI );
126
- highp float Q = dot (inputValue, kRGBToQ );
127
-
128
- // Calculate the hue and chroma
129
- highp float hue = atan (Q, I);
130
- highp float chroma = sqrt (I * I + Q * Q);
131
-
132
- // Make the user's adjustments.
133
- hue += -u_hue; // Why is this negative?
134
-
135
- // Convert back to YIQ
136
- Q = chroma * sin (hue);
137
- I = chroma * cos (hue);
138
-
139
- // Convert back to RGB
140
- vec4 outputColor;
141
- highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0 );
142
- outputColor.r = dot (yIQ, kYIQToR );
143
- outputColor.g = dot (yIQ, kYIQToG );
144
- outputColor.b = dot (yIQ, kYIQToB );
145
- outputColor.a = inputValue.a ;
146
-
147
- return outputColor;
148
- );
149
- #endif
150
61
151
62
CCEffectFunction* fragmentFunction = [[CCEffectFunction alloc ] initWithName: @" hueEffect" body: effectBody inputs: @[input] returnType: @" vec4" ];
152
63
[self .fragmentFunctions addObject: fragmentFunction];
@@ -163,11 +74,7 @@ -(void)buildRenderPasses
163
74
164
75
pass.shaderUniforms [CCShaderUniformMainTexture] = previousPassTexture;
165
76
pass.shaderUniforms [CCShaderUniformPreviousPassTexture] = previousPassTexture;
166
- #if CCEFFECTHUE_USES_COLOR_MATRIX
167
77
pass.shaderUniforms [weakSelf.uniformTranslationTable[@" u_hueRotationMtx" ]] = weakSelf.hueRotationMtx ;
168
- #else
169
- pass.shaderUniforms [weakSelf.uniformTranslationTable[@" u_hue" ]] = weakSelf.conditionedHue ;
170
- #endif
171
78
} copy]];
172
79
173
80
self.renderPasses = @[pass0];
@@ -176,11 +83,7 @@ -(void)buildRenderPasses
176
83
-(void )setHue : (float )hue
177
84
{
178
85
_hue = hue;
179
- #if CCEFFECTHUE_USES_COLOR_MATRIX
180
86
_hueRotationMtx = [NSValue valueWithGLKMatrix4: matrixWithHue (conditionHue (hue))];
181
- #else
182
- _conditionedHue = [NSNumber numberWithFloat: conditionHue (hue)];
183
- #endif
184
87
}
185
88
186
89
@end
@@ -191,12 +94,9 @@ float conditionHue(float hue)
191
94
return clampf (hue, -180 .0f , 180 .0f ) * M_PI / 180 .0f ;
192
95
}
193
96
194
- #if CCEFFECTHUE_USES_COLOR_MATRIX
195
97
GLKMatrix4 matrixWithHue (float hue)
196
98
{
197
99
// RGB to YIQ and YIQ to RGB matrix values source from here:
198
- // https://github.com/BradLarson/GPUImage/blob/master/framework/Source/GPUImageHueFilter.m
199
- // And here:
200
100
// http://en.wikipedia.org/wiki/YIQ
201
101
//
202
102
// Note that GL matrices are column major so we have to transpose them when loading them in
@@ -224,5 +124,4 @@ GLKMatrix4 matrixWithHue(float hue)
224
124
GLKMatrix4 composed = GLKMatrix4Multiply (yiqToRgb, GLKMatrix4Multiply (rotation, rgbToYiq));
225
125
return composed;
226
126
}
227
- #endif
228
127
0 commit comments