2017-10-31 28 views
1

これは、アンチエイリアシングされた線を描画する簡単なプログラムです。プログラムが動作し、私は投影を追加する場合にのみ問題があります。私は別の文脈でこのプログラムを使用しなければなりません、私はそこで正射投影を使用しなければなりません。私はジオメトリシェーダのパラメータ "win_scale"を置き換えなければならないと思いますが、投影法を使用している場合、結果をどのようにスケーリングしなければならないか、関数をどのように書き直す必要がありますか。 ここにシェーダがあります。 バーテックスシェーダ:OpenGL、正射投影によるジオメトリシェーダ

#version 330 core 
layout (location = 0) in vec2 position; 
layout (location = 1) in vec3 color; 

uniform mat4 model; 
//uniform mat4 view; 
uniform mat4 projection; 

out VS_OUT { 
    vec3 color; 
} vs_out; 

void main() { 
    gl_Position = projection * vec4(position.x, position.y, 0.0f, 1.0f); 
    vs_out.color = color; 
} 

ジオメトリシェーダ

#version 330 core 
layout (points) in; 
layout (triangle_strip, max_vertices = 4) out; 

uniform vec2 target; 

uniform float thickness; 
uniform vec2 win_scale; //window width and height 

in VS_OUT { 
    vec3 color; 
} gs_in[]; 

out vec3 fColor; 

vec2 screen_space(vec4 vertex) { 
    return vec2(vertex.xy/vertex.w) * win_scale; 

} 

void main() { 
    fColor = gs_in[0].color; 
    vec2 p0 = screen_space(gl_in[0].gl_Position); // gs_in[0] since there's only one input vertex 
    vec2 p1 = target * win_scale; 

    // determine the direction of each of the segments 
    vec2 v0 = normalize(p1-p0); 
    // determine the normal of each of the segments 
    vec2 n0 = vec2(-v0.y, v0.x); 


    gl_Position = vec4((p0 - thickness * n0)/win_scale, 0.0, 1.0); 
    EmitVertex(); 
    gl_Position = vec4((p0 + thickness * n0)/win_scale, 0.0, 1.0); 
    EmitVertex(); 
    gl_Position = vec4((p1 - thickness * n0)/win_scale, 0.0, 1.0); 
    EmitVertex(); 
    gl_Position = vec4((p1 + thickness * n0)/win_scale, 0.0, 1.0); 
    EmitVertex();   

    EndPrimitive(); 
} 

そしてメインに、私は次の方法で投影値を渡している,:もちろん

glm::mat4 proj = glm::ortho(0.f, (float)width, 0.f, (float)height, -1.f, 1.f); 
glUniformMatrix4fv(glGetUniformLocation(shader.Program, "projection"), 1, GL_FALSE, glm::value_ptr(proj)); 

、誰かが持っている場合より良いアンチエイリアス処理されたラインを実装する方法についての提案ですが、これは歓迎です。

答えて

0

あなたは、あなたは、ジオメトリシェーダで計算を行うと、あなたが頂点でそれを行うと、ジオメトリシェーダで同じようにprojection行列を使用することができ、ジオメトリシェーダに

out VS_OUT { 
    vec2 pos; 
    vec3 color; 
} vs_out; 

void main() 
{ 
    vs.out.pos = position; 

    ..... 
} 

を頂点位置を渡す必要がありますシェーダ:

in VS_OUT { 
    vec2 pos; 
    vec3 color; 
} gs_in[]; 


uniform mat4 projection; 
uniform vec2 win_scale; // compensation for the view matrix 

void main() 
{ 
    ..... 

    vec2 p0 = gs_in[0].pos 
    vec2 p1 = target; 

    // determine the direction of each of the segments 
    vec2 v0 = normalize(p1-p0); 
    // determine the normal of each of the segments 
    vec2 n0 = vec2(-v0.y, v0.x); 

    .... 

    gl_Position = projection * vec4((p0 - thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p0 + thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p1 - thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p1 + thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 

    .... 
} 


注意、一般的な解決策はGL_LINESGL_LINE_STRIP、またはGL_LINE_LISTを描画するとジオメトリシェードを使用することです入力レイアウトlinesとR:

#version 330 core 
layout (lines) in; 
layout (triangle_strip, max_vertices = 4) out; 

uniform float thickness; 
uniform mat4 projection; 
uniform vec2 win_scale; // compensation for the view matrix 

in VS_OUT { 
    vec2 pos; 
    vec3 color; 
} gs_in[]; 

out vec3 fColor; 

void main() { 
    fColor = gs_in[0].color; 

    vec2 p0 = gs_in[0].pos; 
    vec2 p1 = gs_in[1].pos; 

    vec2 v0 = normalize(p1-p0); 
    vec2 n0 = vec2(-v0.y, v0.x); 

    gl_Position = projection * vec4((p0 - thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p0 + thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p1 - thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 
    gl_Position = projection * vec4((p1 + thickness*n0)/win_scale, 0.0, 1.0); EmitVertex(); 

    EndPrimitive(); 
} 


さらにKhronos OpenGL wiki - Geometry Shaderを見る


注意、レンダリングでは一般的に、シーンの各オブジェクトは、通常、モデル行列によって変換され、ビュー行列投影行列

  • 射影行列:
    射影行列は、ビューポートの2D点に、シーンの3D点からのマッピングを記述する。射影行列は、ビュー空間からクリップ空間に変換され、クリップ空間内の座標は、(-1、-1、-1)から(1,1,1)の範囲の正規化装置座標(NDC)クリップ座標のwの成分で割ることによって計算される。

  • マトリックスを表示:
    ビューのマトリックスは、シーンを見る方向と位置を示します。ビュー行列は、wolrd空間からビュー(目)空間に変換されます。ビューポート上のコーディネートシステムでは、X軸はビューの左、Y軸上およびZ軸を指します(右手システムでは、Z軸はX軸のクロス積であることに注意してください)軸とY軸)。

  • モデルマトリクス:
    モデルマトリックスは、シーン内のメッシュの位置、大きさおよび相対的なサイズを定義します。モデル行列は、メッシュの頂点位置をワールド空間に変換します。

これは、このようなスペースの作品をクリップする頂点の変換を意味します

gl_Position = projection * view * model * vec4(pos.xyz, 1.0); 

あなたが持つ2Dシーンや正投影を持っているので、あなたがモデル行列で変換をスキップして、ビューマトリックス。あなたのケースでは、win_scaleで割ることにより、これを補う:

gl_Position = projection * vec4(pos.xy/win_scale, 0.0, 1.0); 


がさらにOpenGL - Mouse coordinates to Space coordinates参照:

+0

を私はこのすべての変更を行ったが、私は、 'gl_Positionは=投影*のvec4((P0置けば - 厚さ* n0)、0.0、1.0); 'gl_position = vec4((p0 - thickness * n0)/ win_scale、0.0、1.0);を実行しても動作しません。あなたのアプローチは正しくなければならない、私は何が間違っているのかを正確に理解することはできない。 – Luis

+0

@ルイス私は私の答えを延長しました – Rabbid76

+0

今すぐwin_scaleが動作します。 – Luis

関連する問題