web-dev-qa-db-ja.com

OpenGLのアウトライン効果

OpenGLでは、オブジェクトを通常どおりに描画してから、元のオブジェクトが描画されないようにステンシルバッファを使用して、ワイヤーフレームとして再度描画することで、オブジェクトの輪郭を描くことができます。ただし、これにより、1つの単色のアウトラインが作成されます。

enter image description here

この画像では、クリーチャーの輪郭のピクセルは、輪郭を描くクリーチャーから離れるほど透明になっているように見えます。 OpenGLで同様の効果を達成するにはどうすればよいですか?

19
dupersuper

彼らはこれにワイヤーフレームを使用しませんでした。シェーダーに大きく関連していて、これが必要だと思います。

  1. オブジェクトをステンシルバッファにレンダリングする
  2. ぼかしを適用しながら、選択した色でステンシルバッファをレンダリングする
  3. その上にモデルをレンダリングする
6
weltensturm

私は答えに遅れましたが、私は同じことを達成しようとしていて、私が使用している解決策を共有したいと思いました。

同様の効果は、それほど複雑ではないシェーダーを使用した1回の描画操作で実現できます。

フラグメントシェーダーでは、稲妻とテクスチャに基づいてフラグメントの色を計算し、強調表示されていない色「colorA」を取得します。

2番目の色は、アウトラインの色「colorB」です。

フラグメントをカメラベクトルに取得し、それを正規化してから、このベクトルとフラグメントの法線との内積を取得する必要があります。

フラグメントからカメラへのベクトルは、単にアイスペース内のフラグメントの位置の逆数です。

フラグメントの色は次のとおりです。

float CameraFacingPercentage = dot(v_fragmentToCamera, v_Normal);
gl_FragColor = ColorA * CameraFacingPercentage + ColorB * (1 - FacingCameraPercentage);

これは基本的な考え方ですが、アウトラインの色を多かれ少なかれ使用するには、いろいろと試してみる必要があります。また、モデルの凹面部分も強調表示されますが、質問に投稿された画像にも当てはまります。

6
EmericBeaufays

Dotprod(view、normal)を使用してGLSLシェーダーでエッジを検出します

http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading#Outlines

2
ChatCloud

私が見る限り、画面への影響は短く、コミックのアウトラインのように、多くの「エッジ」効果は純粋なエッジではありません。ほとんどの場合、1つのパスがあり、オブジェクトを通常どおりにレンダリングしてから、ジオメトリ(テクスチャなし)とGLSLシェーダーのみを含むパスがあります。フラグメントシェーダーでは、法線が取得され、その法線は、オブジェクトに色を付けるカメラベクトルに垂直です。次に、完全な垂線に近い領域を含めることにより、効果が滑らかになります。

正確な計算を調べる必要がありますが、カメラのベクトルと法線の内積をとると、「垂直性」の量が得られると思います。次に、expのような関数を実行して、1にバイアスをかけることができます。

したがって(それが正しいことを保証することなく):

exp(dot(vec3(0, 0, 1), normal));

(注:すべてが画面スペースにあります。)

1
rioki