SMAA、FXAAのofExample

前回の続き。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不要な気がする。

スクリーンショット 2014-02-04 12.01.35

ところでSMAAなんだけど、MacbookAir(Intel HD 4000)でどうしてもうまく動いてくれないのだ。なんでだろー。わからーん。

「SMAA、FXAAのofExample」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です