Tại sao kết quả khác nhau khi thay đổi thứ tự đầu vào trong GL_LINES?


8

Mã số:

#include <math.h>
#include <GL/glut.h>
#pragma comment(lib, "opengl32")
#include <gl/gl.h>
#include <gl/glu.h>

//Initialize OpenGL 
void init(void) {
    glClearColor(0, 0, 0, 0);

    glViewport(0, 0, 500, 500);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0, 500, 0, 500, 1, -1);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
} 

void drawLines(void) {
    glClear(GL_COLOR_BUFFER_BIT);  
    glColor3f(1.0,1.0,1.0); 

    glBegin(GL_LINES);

    glVertex3d(0.5,         0.999,  0.0f);
    glVertex3d(499.501,     0.999,  0.0f);

    glEnd();

    glFlush();
} 


int _tmain(int argc, _TCHAR* argv[])
{
    glutInit(&argc, argv);  
    glutInitWindowPosition(10,10); 
    glutInitWindowSize(500,500); 
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); 

    glutCreateWindow("Example"); 
    init(); 
    glutDisplayFunc(drawLines); 
    glutMainLoop();

    return 0;
}

Mô tả vấn đề:

  • Mã ở trên sẽ đặt toàn bộ pixel hàng dưới cùng của khu vực máy khách cửa sổ thành màu trắng.
  • Nếu tôi hoán đổi thứ tự lệnh, từ glVertex3d(0.5, 0.999, 0.0f);glVertex3d(499.501, 0.999, 0.0f);đến glVertex3d(499.501, 0.999, 0.0f);glVertex3d(0.5, 0.999, 0.0f);, thì chỉ pixel dưới cùng bên trái sẽ không vẽ.

Những hiểu biết của tôi:

  • Hai đỉnh cuối cùng sẽ được chuyển đổi thành tọa độ trung tâm pixel 2D là (0,0, 0,499) và (499,001, 0,499).
  • Thuật toán vẽ đường chỉ chấp nhận các điểm nguyên trung tâm pixel làm đầu vào.
  • Vì vậy, hai đỉnh sẽ sử dụng int (x + 0,5) và sẽ là (0, 0) và (499, 0). Điều này phù hợp với kết quả đầu tiên nhưng mâu thuẫn với kết quả khi thứ tự đầu vào thay đổi. Tại sao?

Câu trả lời:


10

Sự khác biệt trong đó các pixel được bao phủ tùy thuộc vào thứ tự đỉnh có liên quan đến quy tắc rasterization . Chúng là các quy tắc mà phần cứng GPU sử dụng để xác định chính xác các pixel được bao phủ bởi một nguyên thủy.

Quy tắc rasterization là một chút tinh tế. Một trong những mục tiêu của họ là đảm bảo rằng bất cứ khi nào bạn vẽ nhiều nguyên thủy được kết nối chặt chẽ với nhau, thì quá trình raster hóa không bao giờ tạo ra bất kỳ vết nứt nào giữa chúng, cũng không có bất kỳ pixel nào được phủ hai lần (điều quan trọng đối với việc trộn). Để đạt được điều đó, các quy tắc có một số trường hợp cạnh và góc rất cụ thể. Theo nghĩa đen ... họ là trường hợp phải làm với các cạnh và góc nguyên thủy. :)

Trong trường hợp của dòng, nó hoạt động như sau. Có một vùng hình kim cương xung quanh mỗi trung tâm pixel, như được hiển thị trong đoạn trích sơ đồ này từ bài viết MSDN được liên kết ở trên.

quy tắc kim cương cho rasterization dòng

Quy tắc là một pixel được che nếu dòng thoát khỏi viên kim cương, khi truy tìm từ đầu đến cuối dòng. Lưu ý rằng một pixel không bị che nếu đường vào, nhưng không thoát ra, kim cương. Điều này đảm bảo rằng nếu bạn có hai phân đoạn dòng được kết nối từ đầu đến cuối, thì pixel ở điểm cuối được chia sẻ của chúng chỉ thuộc về một trong các phân đoạn và do đó không bị rasterized hai lần.

Bạn cũng có thể thấy trong sơ đồ trên cách thay đổi thứ tự của các đỉnh có thể ảnh hưởng đến các pixel được che phủ (điều này không xảy ra với các hình tam giác, BTW). Biểu đồ cho thấy hai phân đoạn dòng giống hệt nhau ngoại trừ việc hoán đổi thứ tự điểm cuối và bạn có thể thấy nó tạo ra sự khác biệt mà pixel được che phủ.

Phân khúc dòng của bạn có phần giống với điều này. Đầu bên trái, tại (0,5, 0,999) nằm bên trong viên kim cương của pixel (0, 0), do đó, nó được bao phủ khi nó là đỉnh đầu tiên (đường bắt đầu bên trong viên kim cương, sau đó thoát ra) và không phải khi nó là giây thứ hai đỉnh (đường vào kim cương, và kết thúc bên trong nó, vì vậy nó không bao giờ thoát ra). Trên thực tế, các đỉnh được gắn vào điểm cố định với 8 bit subpixel trước khi rasterization, do đó, đỉnh này được làm tròn thành (0,5, 1,0), chính xác ở góc trên cùng của viên kim cương. Tùy thuộc vào các quy tắc rasterization, điều này có thể hoặc không thể được xem xét bên trong viên kim cương; có vẻ như trên GPU của bạn, nó được xem xét bên trong, nhưng điều này có thể khác nhau giữa các lần triển khai, vì thông số GL không hoàn toàn tuân thủ các quy tắc.

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.