2013-03-07 8 views
14

GL_LINESで線を引くことを考慮して、フラグメントシェーダーに線の太さを追加することはできますか?私が見た例のほとんどは、フラグメントシェーダのプリミティブ内のテクセルにのみアクセスするように見え、線の太さのシェーダは線のプリミティブの外側のテクセルに書き込んで太さを取得する必要があります。しかし、可能であれば、非常に小さい、基本的な例が素晴らしいでしょう。フラグメントシェーダーで線の太さを描くことは可能ですか?

答えて

12

フラグメントシェーダーでかなり多くのことが可能です。ちょうどwhat some guys are doingを見てください。私は遠く離れて、そのレベルから自分自身だが、このコードはあなたのアイデアを与えることができます。

#define resolution vec2(500.0, 500.0) 
#define Thickness 0.003 

float drawLine(vec2 p1, vec2 p2) { 
    vec2 uv = gl_FragCoord.xy/resolution.xy; 

    float a = abs(distance(p1, uv)); 
    float b = abs(distance(p2, uv)); 
    float c = abs(distance(p1, p2)); 

    if (a >= c || b >= c) return 0.0; 

    float p = (a + b + c) * 0.5; 

    // median to (p1, p2) vector 
    float h = 2/c * sqrt(p * (p - a) * (p - b) * (p - c)); 

    return mix(1.0, 0.0, smoothstep(0.5 * Thickness, 1.5 * Thickness, h)); 
} 

void main() 
{ 
    gl_FragColor = vec4(
     max(
     max(
      drawLine(vec2(0.1, 0.1), vec2(0.1, 0.9)), 
      drawLine(vec2(0.1, 0.9), vec2(0.7, 0.5))), 
     drawLine(vec2(0.1, 0.1), vec2(0.7, 0.5)))); 
} 

enter image description here

別の方法としては、近くのピクセルの色のためにtexture2Dをチェックすることです - あなたは作ることができる方法(例えば、調整ピクセルのいずれかが白である場合、現在のピクセルを白にし、近くのピクセルに隣接するピクセルが白であれば、現在のピクセルを灰色にする)。

+0

男、そのウェブサイトは壮大です! – Meda

+7

これは「うまくいく」とはいえ、これはおそらく世界で3つの線を描くのに最も非効率的な方法であることに注意してください。処理された断片の99%が混合中に捨てられる。 – Damon

+1

+ Damonはベストプラクティスとして意図されていないと確信しています。私の例はやや馬鹿です。シェーダの原理と可能性を実証するために、さまざまなグローやパーティクルエフェクトを実行したり、単一の頂点を使用しない距離フィールドからの高さマップや複雑な幾何学的なフラクタルから全体のテレーンをレンダリングすることができます。意外にもシェーダはかなり高速になります。 – defhlt

1

いいえ、フラグメントシェーダでは不可能です。ただし、ジオメトリシェーダを使用して太い線として表示されるクワッド(実際には2つの三角形)にラインを拡大することができます。

Here's(コードサンプルあり)その話題に関する素敵な議論。

+0

はそうフラグメントシェーダであなただけのアクセス/描画プリミティブ内の断片を変更することができますか?それは意味をなさないでしょう。ありがとうございますが、OpenGLでは幾何シェーダを使用できません:( – Meda

+0

アクセス不可 - 任意のソースから読み込むことができますが、1つの場所に書き込むことができ、それはラスタライザによって与えられます。 – ltjax

+2

あなたがそれを証明することができる場合を除き、決してnoと言うことはありません。 – GottZ

2

ここに私のアプローチがあります。 p1とp2を線を定義する2点とし、pointを測定したい線までの距離とする。ポイントはgl_FragCoord.xy/resolutionです。

ここに機能があります。

float distanceToLine(vec2 p1, vec2 p2, vec2 point) { 
    float a = p1.y-p2.y; 
    float b = p2.x-p1.x; 
    return abs(a*point.x+b*point.y+p1.x*p2.y-p2.x*p1.y)/sqrt(a*a+b*b); 
} 

それをミックスとスムーズステップ機能で使用します。

また、この答えをチェックアウト: https://stackoverflow.com/a/9246451/911207

関連する問題