2017-05-15 5 views
2

WebGLのテクスチャからシャープな輪郭を表示しようとしています。 フラグメントシェーダにテクスチャを渡してから、地元の派生物を使用して輪郭線/アウトラインを表示しますが、期待通り滑らかではありません。予想通りフラグメントシェーダのテクスチャからのエッジ/アウトライン検出

ちょうど処理せずにテクスチャを印刷する作品:

ローカル誘導体と
vec2 texc = vec2(((vProjectedCoords.x/vProjectedCoords.w) + 1.0)/2.0, 
      ((vProjectedCoords.y/vProjectedCoords.w) + 1.0)/2.0); 
vec4 color = texture2D(uTextureFilled, texc); 
gl_FragColor = color; 

enter image description here

、それはいくつかのエッジをミス:理論的には

vec2 texc = vec2(((vProjectedCoords.x/vProjectedCoords.w) + 1.0)/2.0, 
      ((vProjectedCoords.y/vProjectedCoords.w) + 1.0)/2.0); 
vec4 color = texture2D(uTextureFilled, texc); 
float maxColor = length(color.rgb); 
gl_FragColor.r = abs(dFdx(maxColor)); 
gl_FragColor.g = abs(dFdy(maxColor)); 
gl_FragColor.a = 1.; 

enter image description here

答えて

2

、あなたのコードは正しいです。

実際には、ほとんどのGPUは2x2ピクセルのブロックで導関数を計算しています。 このようなブロックのすべての4ピクセルで、dFdXとdFdYの値は同じになります。 (詳細な説明here

これはエイリアシングのいくつかの種類の原因となり、あなたが黒から形状色への遷移は、2×2ブロックの境界で発生した場合にこれが起こる(ランダム形状の輪郭のためにいくつかのピクセルを見逃すであろう)。

これを修正し、ピクセル誘導体一人当たりの実質を取得するには、あなたの代わりにそれを自分で計算することができ、これは次のようになります。

// get tex coordinates 
vec2 texc = vec2(((vProjectedCoords.x/vProjectedCoords.w) + 1.0)/2.0, 
       ((vProjectedCoords.y/vProjectedCoords.w) + 1.0)/2.0); 

// compute the U & V step needed to read neighbor pixels 
// for that you need to pass the texture dimensions to the shader, 
// so let's say those are texWidth and texHeight 
float step_u = 1.0/texWidth; 
float step_v = 1.0/texHeight; 

// read current pixel 
vec4 centerPixel = texture2D(uTextureFilled, texc); 

// read nearest right pixel & nearest bottom pixel 
vec4 rightPixel = texture2D(uTextureFilled, texc + vec2(step_u, 0.0)); 
vec4 bottomPixel = texture2D(uTextureFilled, texc + vec2(0.0, step_v)); 

// now manually compute the derivatives 
float _dFdX = length(rightPixel - centerPixel)/step_u; 
float _dFdY = length(bottomPixel - centerPixel)/step_v; 

// display 
gl_FragColor.r = _dFdX; 
gl_FragColor.g = _dFdY; 
gl_FragColor.a = 1.; 

いくつかの重要な事柄:

  • 質感はいけません
  • テクスチャmin & magフィルタリングをGL_NEARESTに設定する
  • テクスチャクランプモードをclamp(noトンリピート)

そして、ここではこれを実証し、ShaderToyサンプルです:

enter image description here

関連する問題