2016-11-14 NSArray用のも追加
たぶん当たり前すぎて誰も書いてないんでしょうけど、GPUImageではじめてシェーダ触る僕が苦労したのでまとめました。
なんかもっと良い方法あったら教えてください。
GPUImageFilterを継承したクラス
GPUImageArrayTestFilter.h
# import <GPUImage/GPUImage.h>
@interface GPUImageArrayTestFilter : GPUImageFilter
{
//配列のユニフォーム
GLint testUniform;
//長さのユニフォーム
GLint sizeUniform;
}
//配列データを受け取るプロパティ
@property(readwrite, nonatomic) GLfloat *test;
//配列の長さも同時に指定するセッタ
-(void)setTest:(GLfloat *)test withSize:(GLsizei)size;
@end
GPUImageArrayTestFilter.m
# import "GPUImageArrayTestFilter.h"
//シェーダーをNSStringの文字列として用意する
NSString *const kGPUImageArrayTestShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
//固定長しかダメ?
uniform highp float test[256];
//実際に使う配列の長さ
uniform highp int size;
void main()
{
//基本は黒
lowp vec3 color = vec3(0.0, 0.0, 0.0);
//配列内で指定された矩形だけ赤くする
for(int i = 0 ; i < size; i+=4){
if(test[i] < textureCoordinate.x
&& textureCoordinate.x < test[i] + test[i + 2]
&& test[i+1] < textureCoordinate.y
&& textureCoordinate.y < test[i+1] + test[i+3]
){
color = vec3(1.0, 0.0, 0.0);
break;
}
}
gl_FragColor = vec4(color, 1);
}
);
@implementation GPUImageArrayTestFilter
- (id)init{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageArrayTestShaderString]))
{
return nil;
}
//配列のuniformIndexを登録
testUniform = [filterProgram uniformIndex:@"test"];
//長さのuniformIndexを登録
sizeUniform = [filterProgram uniformIndex:@"size"];
return self;
}
//C言語の配列とその長さも同時に指定するセッタ
-(void)setTestCArr:(GLfloat *)test withSize:(GLsizei)size{
_test = test;
//配列のポインタをセット
[self setFloatArray:_test length:size forUniform:testUniform program:filterProgram];
//実際のデータのサイズをセット
[self setInteger:size forUniform:_sizeUniform program:filterProgram];
}
//NSArrayを代入するセッタ
-(void)setTestNSArr:(NSArray*)test{
float *cArr = (float*)malloc(sizeof(float*)*test.size);
for(int i = 0 ; i < test.size ; i++){
cArr[i] = [test[i] floatValue];
}
[self setTestCArr:cArr withSize:test.size];
free(cArr);
}
//デフォルトのセッタは配列の長さを0としておく
-(void)setTest:(GLfloat *)test{
[self setTest:test withSize:0];
}
@end
使い方
test.m
//矩形表示用のテストデータ
float test[8] = {
//x,y,width,heightの順で入れている
0.2, 0.2, 0.1, 0.1
,0.6, 0.2, 0.1, 0.1
};
GPUImageArrayTestFilter *filter = [GPUImageArrayTestFilter new];
[filter setTestCArr:test withSize:8];
//あとはGPUImageのフィルタとして実行
実行結果
最後
これで検出した顔情報ごとに何か処理をやるみたいなこともできますね