前回の続き。SMAAの実装の紹介。
ソースは最新のこっちにした。
https://github.com/iryoku/smaa
SMAAで3回分のシェーダが必要なんだけど、shader3つも作るのはナンセンスだから1つにまとめてみた。でも、これだと1passはrgチャンネルしか使わないのでbit数の最適化ができてない。まぁいいか・・・。
バーテックスシェーダ
#include "../common/version.glsl" /* uStep * 0:Edge Detection * 1:Weight Calculation * 2:BlendingWeight */ uniform int uStep=0; layout(binding=0) uniform sampler2D uInpTex; vec2 texSize = vec2(textureSize(uInpTex, 0)); #define SMAA_RT_METRICS vec4(1.0/texSize,texSize) #define SMAA_INCLUDE_PS 0 #define SMAA_GLSL_4 1 #define SMAA_PRESET_ULTRA 1 #include "SMAA.hlsl" noperspective out vec2 texcoord; noperspective out vec2 pixcoord; noperspective out vec4 offset[3]; layout(location=0) in vec3 position; void main(){ texcoord = position.xy * 0.5 + 0.5; if(uStep==2){ SMAANeighborhoodBlendingVS(texcoord, offset[0]); }else if(uStep==1){ SMAABlendingWeightCalculationVS(texcoord, pixcoord, offset); }else{ SMAAEdgeDetectionVS(texcoord, offset); } gl_Position = vec4(position.xy, 0.0, 1.0); }
ピクセルシェーダ
#include "../common/version.glsl" /* uStep * 0:Edge Detection * 1:Weight Calculation * 2:BlendingWeight */ uniform int uStep=0; layout(binding=0) uniform sampler2D uInpTex; layout(binding=1) uniform sampler2D uInpTex2; layout(binding=2) uniform sampler2D uInpTex3; vec2 texSize = vec2(textureSize(uInpTex, 0)); #define SMAA_RT_METRICS vec4(1.0/texSize,texSize) #define SMAA_INCLUDE_VS 0 #define SMAA_GLSL_4 1 #define SMAA_PRESET_ULTRA 1 #include "SMAA.hlsl" noperspective in vec2 texcoord; noperspective in vec2 pixcoord; noperspective in vec4 offset[3]; layout(location = 0) out vec4 fOut; void main(){ if(uStep==2){ fOut = SMAANeighborhoodBlendingPS(texcoord, offset[0], uInpTex, uInpTex2); }else if(uStep==1){ fOut = SMAABlendingWeightCalculationPS(texcoord, pixcoord, offset, uInpTex, uInpTex2, uInpTex3, ivec4(0)); }else{ fOut = vec4(SMAAColorEdgeDetectionPS(texcoord, offset, uInpTex),0.0,0.0); } }
多分こんな感じ。GLSLは410以降が必要。
作業用のFBOはアルファチャンネルも使うのでRGBAが必要。あと、テクスチャ用のヘッダファイルがあるのでofTextureとして登録。
ofFbo::Settings defaultSetting; defaultSetting.numSamples=0; defaultSetting.textureTarget=GL_TEXTURE_2D; defaultSetting.height=768; defaultSetting.internalformat=GL_RGBA; defaultSetting.useDepth=false; defaultSetting.useStencil=false; defaultSetting.width=1024; defaultSetting.wrapModeHorizontal=GL_CLAMP_TO_EDGE; defaultSetting.wrapModeVertical=GL_CLAMP_TO_EDGE; defaultSetting.numSamples=false; fboRender_.allocate(defaultSetting); //入力用 fboAA_.allocate(defaultSetting); // AA結果表示用 fboSmaaWk_.allocate(defaultSetting); //作業用 //SMAAテクスチャ texSmaaArea_.allocate(AREATEX_WIDTH,AREATEX_HEIGHT,GL_RG8,false); texSmaaArea_.loadData(areaTexBytes,AREATEX_WIDTH,AREATEX_HEIGHT,GL_RG); texSmaaArea_.setTextureMinMagFilter(GL_LINEAR,GL_LINEAR); texSmaaSearch_.allocate(SEARCHTEX_WIDTH,SEARCHTEX_HEIGHT,GL_R8,false); texSmaaSearch_.loadData(searchTexBytes,SEARCHTEX_WIDTH,SEARCHTEX_HEIGHT,GL_RED); texSmaaSearch_.setTextureMinMagFilter(GL_NEAREST,GL_NEAREST);
処理はこんな感じ。blendモードとかちゃんときっておかないと動かない。
glDisable(GL_BLEND); glClearColor(0,0,0,0); shaderSmaa_.begin(); fboAA_.begin(false); glColorMask(GL_TRUE,GL_TRUE,GL_FALSE,GL_FALSE); glClear(GL_COLOR_BUFFER_BIT); shaderSmaa_.setUniform1i("uStep",0); shaderSmaa_.setUniformTexture("uInpTex",fboRender_,0); ssObj.draw(); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); fboAA_.end(); fboSmaaWk_.begin(false); glClear(GL_COLOR_BUFFER_BIT); shaderSmaa_.setUniform1i("uStep",1); shaderSmaa_.setUniformTexture("uInpTex",fboAA_,0); shaderSmaa_.setUniformTexture("uInpTex2",texSmaaArea_,1); shaderSmaa_.setUniformTexture("uInpTex3",texSmaaSearch_,2); ssObj.draw(); fboSmaaWk_.end(); fboAA_.begin(false); shaderSmaa_.setUniform1i("uStep",2); shaderSmaa_.setUniformTexture("uInpTex",fboRender_,0); shaderSmaa_.setUniformTexture("uInpTex2",fboSmaaWk_,1); ssObj.draw(); fboAA_.end(); shaderSmaa_.end();
Openframeworksのサンプルコードはこちら(vs2012のみー)
ちなみにこのなかのofShaderHelperは、#includeとか使うために適当に作ったやつだから信用できないwGLSL4系だと結構モジュール化とかやりやすくなってるから需要あると思うので、ちゃんとしたやつをofShaderの中で強化してもらえるといいなぁ。
サンプルではFBOへの出力を単純にポストプロセスでAAかけてて、汎用的に使えると思う。最適かどうかはおいておいて、FXAA,SMAAを比較することで、メリット、デメリットが見えてくるう。SMAAは画質重視で重い。FXAAはディテールの破壊があるが高速。カメラワーク、オブジェクトの動きが激しいシーンではFXAAにスイッチするとかして使い分けるのもいいかもしれない。てかDofとか入れるとほとんどAA不要な気がする。
ところでSMAAなんだけど、MacbookAir(Intel HD 4000)でどうしてもうまく動いてくれないのだ。なんでだろー。わからーん。
「SMAA、FXAAのofExample」への1件のフィードバック