[opengl] OpenGL에서 프리미티브를 와이어 프레임으로 어떻게 렌더링합니까?

OpenGL에서 프리미티브를 와이어 프레임으로 어떻게 렌더링합니까?



답변

glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

스위치를 켜려면

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

정상으로 돌아갑니다.

텍스처 매핑 및 조명과 같은 기능이 활성화되어 있으면 와이어 프레임 라인에 계속 적용되어 이상하게 보일 수 있습니다.


답변

에서 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);


답변

OpenGL 3 이상에서 순방향 호환 컨텍스트를 가정하면 glPolygonMode앞에서 언급 한대로 사용할 수 있지만 두께가 1px 이상인 줄은 더 이상 사용되지 않습니다. 따라서 삼각형을 와이어 프레임으로 그릴 수는 있지만 매우 얇아 야합니다. OpenGL ES에서는 GL_LINES동일한 제한으로 사용할 수 있습니다 .

OpenGL에서는 지오메트리 쉐이더를 사용하여 들어오는 삼각형을 가져 와서 분해하고 굵은 선을 에뮬레이트하는 쿼드 (실제 삼각형 쌍)로 래스터 화를 위해 보낼 수 있습니다. 지오메트리 셰이더가 성능 스케일링이 좋지 않다는 점을 제외하고는 매우 간단합니다.

대신 수행 할 수있는 작업과 OpenGL ES에서 작동하는 작업은 조각 쉐이더 를 사용하는 것 입니다. 와이어 프레임 삼각형의 질감을 삼각형에 적용하는 것을 고려하십시오. 텍스처가 필요하지 않은 경우 절차 적으로 생성 할 수 있습니다. 그러나 충분한 대화를 해보자. 프래그먼트 셰이더 :

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
}

여기에서 무게 중심의 좌표는 단순히 (1, 0, 0), (0, 1, 0)그리고 (0, 0, 1)세 개의 삼각형의 정점 (순서는, 정말 중요합니까 잠재적으로 쉽게 삼각형 스트립으로 포장하게된다).

이 방법의 명백한 단점은 텍스처 좌표를 먹고 버텍스 배열을 수정해야한다는 것입니다. 매우 간단한 지오메트리 쉐이더로 해결할 수는 있지만 GPU에 더 많은 데이터를 공급하는 것보다 느릴 것이라고 생각합니다.


답변

고정 파이프 라인 (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 를 호출하여 선 너비를 변경할 수 있습니다

그렇지 않으면 draw 메서드 내에서 다각형 모드 (glDrawElements, glDrawArrays 등)를 변경해야합니다. 정점 데이터가 삼각형이고 선을 출력하기 때문에 결과가 거칠어 질 수 있습니다. 최상의 결과를 얻으려면 형상 셰이더를 사용 하거나 와이어 프레임에 대한 새 데이터를 만드는 것이 좋습니다 .


답변

가장 쉬운 방법은 프리미티브를로 그리는 것 GL_LINE_STRIP입니다.

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


답변

Modern OpenGL (OpenGL 3.2 이상)에서는 Geometry Shader를 사용할 수 있습니다.

#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();
}

공지 사항 :


답변

다음과 같이 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);