Làm thế nào để bạn kết xuất nguyên thủy dưới dạng khung lưới trong OpenGL?


220

Làm thế nào để bạn kết xuất nguyên thủy dưới dạng khung lưới trong OpenGL?

opengl 

2
Cụ thể hơn về phiên bản OpenGL bạn đang sử dụng.
Vertexwahn 17/03/2016

Với ModernGL, bạn có thể đơn giản sử dụng thuộc tính khung dây của lớp Ngữ cảnh
Szabolcs Dombi

sử dụng GL_LINES để vẽ khung dây
oxine

Câu trả lời:


367
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

để bật

glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

để trở lại bình thường.

Lưu ý rằng những thứ như ánh xạ kết cấu và ánh sáng vẫn sẽ được áp dụng cho các dòng khung dây nếu chúng được bật, trông có vẻ lạ.


2
Tôi thích bạn. Thêm 4 để đi.
Jo So

37

Từ 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);

75
thực hiện hai cuộc gọi là dư thừa. sử dụng GL_FRONT_AND_BACK
shoosh

6
Là một phụ lục cho nhận xét của @ shoosh, Sách Đỏ tuyên bố rằng GL_FRONT và GL_BACK đã không được chấp nhận và bị xóa khỏi OpenGL 3.1 trở lên. Bây giờ, bạn vẫn có thể sử dụng chúng thông qua tiện ích mở rộng tương thích, nhưng nếu bạn có lựa chọn giữa tương thích về phía trước và tương thích ngược, tôi khuyên bạn nên đi trước.
bốn

1
Liên kết trong câu trả lời này trả về 404.
Ondrej Slinták

1
@ OndrejSlinták Nó đã được sửa bây giờ.
MaxiMouse

24

Giả sử bối cảnh tương thích về phía trước trong OpenGL 3 trở lên, bạn có thể sử dụng glPolygonModenhư đã đề cập trước đó, nhưng lưu ý rằng các dòng có độ dày hơn 1px hiện không được dùng nữa. Vì vậy, trong khi bạn có thể vẽ các hình tam giác dưới dạng khung dây, chúng cần phải rất mỏng. Trong OpenGL ES, bạn có thể sử dụng GL_LINESvới cùng giới hạn.

Trong OpenGL, có thể sử dụng các shader hình học để lấy các hình tam giác đến, tháo rời chúng và gửi chúng cho rasterization dưới dạng hình tứ giác (cặp tam giác thực sự) mô phỏng các đường dày. Khá đơn giản, thực sự, ngoại trừ các shader hình học nổi tiếng với tỷ lệ hiệu suất kém.

Thay vào đó, những gì bạn có thể làm và những gì cũng sẽ hoạt động trong OpenGL ES là sử dụng tạo bóng mảnh . Hãy nghĩ đến việc áp dụng một kết cấu của tam giác khung dây cho tam giác. Ngoại trừ việc không có kết cấu là cần thiết, nó có thể được tạo ra theo thủ tục. Nhưng nói đủ rồi, hãy viết mã. Mảnh vỡ mảnh:

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

Và shader đỉnh:

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
}

Ở đây, tọa độ barycentric chỉ đơn giản là (1, 0, 0) , (0, 1, 0)(0, 0, 1)trong ba đỉnh tam giác (thứ tự không quan trọng, mà làm cho bao bì thành dải tam giác có khả năng dễ dàng hơn).

Nhược điểm rõ ràng của phương pháp này là nó sẽ ăn một số tọa độ kết cấu và bạn cần sửa đổi mảng đỉnh của mình. Có thể được giải quyết bằng trình đổ bóng hình học rất đơn giản nhưng tôi vẫn nghi ngờ nó sẽ chậm hơn so với việc chỉ cung cấp cho GPU nhiều dữ liệu hơn.


Tôi nghĩ rằng điều này có vẻ đầy hứa hẹn, tuy nhiên điều này dường như không hoạt động ở bất kỳ khả năng nào với OpenGL 3.2 (không phải ES). Mặc dù có thể tôi đã làm hỏng thứ gì đó, tôi đã chơi xung quanh với nó khá lâu và không thực sự chắc chắn làm thế nào nó thậm chí còn được sử dụng. Bất kỳ thông tin nào khác về những gì bạn dự định thực sự kết xuất với các shader này sẽ hữu ích; Tôi không thấy bất cứ thứ gì ngoài fill sẽ tạo ra bất cứ thứ gì hữu ích, nhưng điều đó thậm chí không hoạt động nếu giá trị alpha của gl_FragColor dường như bị bỏ qua hoàn toàn trong OpenGL 3.2 ...
user1167662

2
Tất nhiên là thế. Bạn có thể tham khảo việc thực hiện ý tưởng tương tự của ai đó trong stackoverflow.com/questions/7361582/iêu .
con lợn

1
Vấn đề tôi gặp phải khi cố gắng sử dụng triển khai được đề xuất của bạn là, tôi nghĩ rằng, trình đổ bóng sẽ không bao giờ được vẽ bên ngoài đối tượng cần phác thảo. Điều này do đó sẽ vẽ phác thảo trên các đối tượng được phác thảo? Nói cách khác, đề cương sẽ hoàn toàn được chứa trong đối tượng ban đầu được vẽ?
dùng1167662

1
@BrunoLevy bạn có thể phối hợp thêm trong webGL không? Nếu bạn may mắn, bạn có thể có được các tọa độ đó từ texcoords nếu bạn có các mô hình rất đơn giản nhưng nếu không, bạn chỉ cần thêm tọa độ mới. Sẽ là quá tốt nếu nó làm việc mà không có nó :). Tất cả những gì bạn cần là truyền một vô hướng duy nhất cho mỗi đỉnh (và sau đó mở rộng nó thành một vectơ 3 trong shader đỉnh).
con lợn

2
À, bây giờ tôi thấy ... f_creen () là bạn của tôi, về mặt này. Cảm ơn
Neil Gatenby

5

Nếu bạn đang sử dụng đường ống cố định (OpenGL <3.3) hoặc cấu hình tương thích, bạn có thể sử dụng

//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);

Trong trường hợp này, bạn có thể thay đổi độ rộng đường bằng cách gọi glLineWidth

Nếu không, bạn cần thay đổi chế độ đa giác bên trong phương thức vẽ của bạn (glDrawElements, glDrawArrays, v.v.) và bạn có thể kết thúc với một số kết quả thô vì dữ liệu đỉnh của bạn là cho hình tam giác và bạn đang xuất ra các dòng. Để có kết quả tốt nhất, hãy xem xét sử dụng trình đổ bóng Hình học hoặc tạo dữ liệu mới cho khung dây.


3

Cách dễ nhất là vẽ các nguyên thủy như GL_LINE_STRIP.

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

không phải nếu đó là một loạt GL_TRIANGLES: bạn sẽ nhận được các dòng giữa chúng. Trong OpenGL 1.x hoặc di sản, bạn sử dụng glPolygonMode. Trong OpenGL gần đây, bạn chơi với shader hình học.
Fabrice NEYRET

Đây là một cách cổ xưa để làm những việc cần phải bỏ lại.
Benny Mackney

2

Trong OpenGL hiện đại (OpenGL 3.2 trở lên), bạn có thể sử dụng Shader Geometry cho việc này:

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

Thông báo:


1

Bạn có thể sử dụng các thư viện glut như thế này:

  1. cho một hình cầu:

    glutWireSphere(radius,20,20);
    
  2. cho một xi lanh:

    GLUquadric *quadratic = gluNewQuadric();
    gluQuadricDrawStyle(quadratic,GLU_LINE);
    gluCylinder(quadratic,1,1,1,12,1);
    
  3. cho một khối:

    glutWireCube(1.5);
    

0

Một cách tốt và đơn giản để vẽ các đường chống răng cưa trên mục tiêu kết xuất không khử răng cưa là vẽ hình chữ nhật có chiều rộng 4 pixel với kết cấu 1x4, với các giá trị kênh alpha là {0., 1., 1., 0.} và sử dụng lọc tuyến tính với tắt ánh xạ mip. Điều này sẽ làm cho các đường kẻ dày 2 pixel, nhưng bạn có thể thay đổi kết cấu cho các độ dày khác nhau. Điều này nhanh hơn và dễ dàng hơn so với tính toán barymetric.


0

sử dụng chức năng này: void glPolygonMode (mặt GLenum, chế độ GLenum);

mặt: Chỉ định đa giác mà chế độ áp dụng cho. có thể là GL_FRONT cho mặt trước của polygone và GL_BACK cho mặt sau của anh ấy và GL_FRONT_AND_BACK cho cả hai.

chế độ: Ba chế độ được xác định và có thể được chỉ định trong chế độ:

GL_POINT: Các đỉnh đa giác được đánh dấu là điểm bắt đầu của cạnh biên được vẽ dưới dạng các điểm.

GL_LINE: Các cạnh biên của đa giác được vẽ dưới dạng các đoạn thẳng. (Mục tiêu của bạn)

GL_FILL: Phần bên trong của đa giác được lấp đầy.

PS: glPolygonMode kiểm soát việc giải thích các đa giác để rasterization trong đường ống đồ họa.

để biết thêm thông tin, hãy xem các trang tham khảo OpenGL trong nhóm khronos: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPolygonMode.xhtml


-1

Nếu đó là OpenGL ES 2.0 mà bạn đang xử lý, bạn có thể chọn một trong các hằng số chế độ vẽ từ

GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, để vẽ đường

GL_POINTS (nếu bạn chỉ cần vẽ các đỉnh), hoặc

GL_TRIANGLE_STRIP, GL_TRIANGLE_FANGL_TRIANGLESđể vẽ các hình tam giác đầy

như là đối số đầu tiên của bạn

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

hoặc là

glDrawArrays(GLenum mode, GLint first, GLsizei count) các cuộc gọi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.