0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

GPUImageでフラグメントシェーダに配列を渡す方法

Last updated at Posted at 2016-03-13

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のフィルタとして実行

実行結果

こんな画像が出来ます。
IMG_0868.PNG

最後

これで検出した顔情報ごとに何か処理をやるみたいなこともできますね

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?