web-dev-qa-db-ja.com

OpenGLでプリミティブをワイヤフレームとしてどのようにレンダリングしますか?

OpenGLでプリミティブをワイヤフレームとしてどのようにレンダリングしますか?

203
Phineas
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

スイッチを入れるには、

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

通常に戻ります。

テクスチャマッピングやライティングなどの機能が有効になっている場合、ワイヤフレームラインに適用されることに注意してください。

340
Mike F

から http://cone3d.gamedev.net/cgi-bin/index.pl?page=tutorials/ogladv/tut5

// Turn on wireframe mode
glPolygonMode(GL_FRONT, GL_LINE);
glPolygonMode(GL_BACK, GL_LINE);

// Draw the box
DrawBox();

// Turn off wireframe mode
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
30
John Millikin

OpenGL 3以降で前方互換性のあるコンテキストを想定すると、前述のようにglPolygonModeを使用できますが、1pxを超える太さの行は廃止されることに注意してください。そのため、ワイヤーフレームとして三角形を描くことはできますが、非常に薄くする必要があります。 OpenGL ESでは、GL_LINESを同じ制限付きで使用できます。

OpenGLでは、ジオメトリシェーダーを使用して着信三角形を取得し、それらを逆アセンブルして、太い線をエミュレートする四角形(実際には三角形のペア)としてラスタライズするために送信できます。ジオメトリシェーダーがパフォーマンススケーリングの悪さで悪名高いことを除けば、本当に簡単です。

代わりにできること、そしてOpenGL ESでも機能するのはfragmentシェーダーを採用することです。ワイヤフレームの三角形のテクスチャを三角形に適用することを考えてください。テクスチャが不要な場合を除き、プロシージャルで生成できます。しかし、十分に話して、コーディングしましょう。フラグメントシェーダー:

in vec3 v_barycentric; // barycentric coordinate inside the triangle
uniform float f_thickness; // thickness of the rendered lines

void main()
{
    float f_closest_Edge = min(v_barycentric.x,
        min(v_barycentric.y, v_barycentric.z)); // see to which Edge this pixel is the closest
    float f_width = fwidth(f_closest_Edge); // calculate derivative (divide f_thickness by this to have the line width constant in screen-space)
    float f_alpha = smoothstep(f_thickness, f_thickness + f_width, f_closest_Edge); // calculate alpha
    gl_FragColor = vec4(vec3(.0), f_alpha);
}

そして頂点シェーダー:

in vec4 v_pos; // position of the vertices
in vec3 v_bc; // barycentric coordinate inside the triangle

out vec3 v_barycentric; // barycentric coordinate inside the triangle

uniform mat4 t_mvp; // modeview-projection matrix

void main()
{
    gl_Position = t_mvp * v_pos;
    v_barycentric = v_bc; // just pass it on
}

ここで、重心座標は、3つの三角形の頂点の(1, 0, 0)(0, 1, 0)、および(0, 0, 1)にすぎません(順序は重要ではないため、三角形ストリップへのパッキングが容易になる可能性があります)。

このアプローチの明らかな欠点は、テクスチャ座標を消費し、頂点配列を変更する必要があることです。非常にシンプルなジオメトリシェーダーで解決できますが、GPUに追加のデータを供給するよりも遅いと思われます。

20
the swine

最も簡単な方法は、プリミティブをGL_LINE_STRIPとして描画することです。

glBegin(GL_LINE_STRIP);
/* Draw vertices here */
glEnd();
4
Hochester

固定パイプライン(OpenGL <3.3)または互換性プロファイルを使用している場合は、使用できます

//Turn on wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

//Draw the scene with polygons as lines (wireframe)
renderScene();

//Turn off wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

この場合、 glLineWidth を呼び出すことにより、線幅を変更できます

そうしないと、描画メソッド(glDrawElements、glDrawArraysなど)内でポリゴンモードを変更する必要があり、頂点データが三角形用であり、ラインを出力しているため、いくつかの大まかな結果が得られる可能性があります。最良の結果を得るには、 ジオメトリシェーダー を使用するか、ワイヤフレームの新しいデータを作成することを検討してください。

4
Zaphyk

OpenGL ES 2.の場合は、次の描画モード定数のいずれかを選択できます。

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,は線を引きます。

GL_POINTS(頂点のみを描画する必要がある場合)、または

GL_TRIANGLE_STRIPGL_TRIANGLE_FAN、およびGL_TRIANGLESは、塗りつぶされた三角形を描画します

あなたの最初の引数として

glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)

または

glDrawArrays(GLenum mode, GLint first, GLsizei count)呼び出し。

1
Victor

次のようなglutライブラリを使用できます。

  1. 球の場合:

    glutWireSphere(radius,20,20);
    
  2. シリンダーの場合:

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. キューブの場合:

    glutWireCube(1.5);
    
1
H.Mohcen

Modern OpenGL(OpenGL 3.2以降)では、これにジオメトリシェーダーを使用できます。

#version 330

layout (triangles) in;
layout (line_strip /*for lines, use "points" for points*/, max_vertices=3) out;

in vec2 texcoords_pass[]; //Texcoords from Vertex Shader
in vec3 normals_pass[]; //Normals from Vertex Shader

out vec3 normals; //Normals for Fragment Shader
out vec2 texcoords; //Texcoords for Fragment Shader

void main(void)
{
    int i;
    for (i = 0; i < gl_in.length(); i++)
    {
        texcoords=texcoords_pass[i]; //Pass through
        normals=normals_pass[i]; //Pass through
        gl_Position = gl_in[i].gl_Position; //Pass through
        EmitVertex();
    }
    EndPrimitive();
}

通知 :

1
LMD