2010-02-27 6 views
6

Tôi đang viết trò chơi 2D bằng OpenGL. Khi tôi muốn blit một phần của kết cấu như một sprite Tôi sử dụng glTexCoord2f (u, v) để xác định UV tọa độ, với U và V tính toán như thế này:OpenGL: Làm cách nào để tránh các lỗi làm tròn khi chỉ định tọa độ UV

GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)width_of_texture; 
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)height_of_texture; 

này hoạt động hoàn hảo hầu hết thời gian , trừ khi tôi sử dụng glScale để phóng to hoặc thu nhỏ trò chơi. Sau đó, các lỗi làm tròn dấu chấm động làm cho một số điểm ảnh được vẽ một bên phải hoặc một bên dưới hình chữ nhật dự định trong kết cấu.

Điều gì có thể được thực hiện về điều này? Tại thời điểm này tôi trừ một giá trị 'epsilon' từ các cạnh phải và dưới của hình chữ nhật, và nó có vẻ làm việc nhưng điều này có vẻ giống như một kludge khủng khiếp. Có giải pháp nào tốt hơn không?

Trả lời

-1

xpos bạn/ypos phải căn cứ vào từ 0 đến (chiều rộng hoặc chiều cao) - 1 và sau đó:

GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)(width_of_texture - 1); 
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)(height_of_texture - 1); 
+0

Điều này là sai. Nói width_of_texture = 2 (với 1, nó thậm chí còn thú vị hơn), và bạn muốn vẽ 2 quads mà bản đồ chính xác đến 2 texels. Bạn cần U = 0, U = 0,5 cho các góc quad 0 và U = 0,5, U = 1 cho quad 1 góc. Đó chính xác là công thức mà Sirp cung cấp (nếu bạn cho nó ăn với xpos đúng, tức là 0, 1, 2), và không phải cái bạn làm (bạn chỉ cung cấp số nguyên với chiều rộng = 2). – Bahbar

+0

Đúng, tôi đã nghĩ rằng anh ta đang chỉ định vị trí pixel, nhưng nếu anh ta chỉ định vị trí giữa các pixel, thì nó sẽ hoạt động. Tôi đã từng làm việc ở các vị trí pixel, tất nhiên là hoàn toàn bị phá vỡ khi kết cấu nhỏ đến 2x2. –

0

Do bộ phận như là một đôi, vòng kết quả xuống mình vào mức độ mong muốn của chính xác, sau đó đúc nó vào GLFloat.

3

Sự cố của bạn có nhiều khả năng không phải do lỗi làm tròn, mà là sự hiểu lầm về cách OpenGL ánh xạ tới các pixel. Nếu bạn nhận thấy các lỗi off-by-one, có thể là do các UV của bạn, các vị trí đỉnh của bạn hoặc cặp ma trận/khung nhìn chiếu của bạn không được căn chỉnh với vị trí mà chúng phải là.

Để đơn giản hóa, tôi sẽ chỉ nói về 1D, và được giả sử bạn sử dụng một máy chiếu và một khung nhìn mà map X, Y tọa độ đến vị trí điểm ảnh tương đương (tức là một glOrtho(0,width,0,height,zmin,zmax)glViewport(0,width,0,height).

Giả sử bạn muốn vẽ 5 texels (bắt đầu từ 0 để đơn giản) của kết cấu 64 inch của bạn hiển thị trên 10 pixel (tỷ lệ 2) của màn hình của bạn bắt đầu từ pixel 20.

Để đến đó, vẽ hình tam giác với tọa độ X 20 và 30, và U (của cặp UV) của 10/64 và 15/64. Việc rasterization OpenGL sẽ tạo ra 10 pixel để bóng râm, với X tọa độ 20.5, 21.5, ... 29.5. Lưu ý rằng vị trí itions không phải là số nguyên đầy đủ. OpenGL rasterizes ở giữa pixel.

Tương tự, nó sẽ tạo tọa độ U là 10,25/64, 10,75/64, 11,25/64, 11,75/64 ... 14,25/64, 14,75/64. Lưu ý một lần nữa rằng tọa độ texel, đưa trở lại vị trí texel trong không gian kết cấu, không phải là số nguyên đầy đủ. OpenGL mẫu từ giữa các địa điểm texel, do đó, điều này là tốt. Làm thế nào các samplers sử dụng các tia UV này để tạo ra các giá trị texel phụ thuộc vào các chế độ lọc, nhưng nó là gần nhất hoặc tuyến tính, các pixel nên được chứa bên trong các texas quan tâm (0.25 với kích thước 0.5 chỉ nên sử dụng màu từ 0, 0, 0, 10, 04835). đến 0,5, tất cả nằm trong texel đầu tiên).

Nói chung, nếu bạn tuân thủ các nguyên tắc chung tôi đã nêu, bạn sẽ không bao giờ thấy hiện vật.

  1. Sử dụng Ortho và Viewport chính xác kích thước bộ đệm khung hình của bạn
  2. Sử dụng vị trí của X, X + chiều rộng chính xác
  3. Sử dụng UVs tương ứng với chính xác texels bạn muốn (nếu bạn muốn 10 texels bắt đầu từ texel 0, sử dụng U = 0 đến U = 10.

Nếu bạn có -1 ở đâu đó trong môn toán, có thể không chính xác (đối với vị trí hoặc UV).

Để quay lại ví dụ của bạn, không rõ cách bạn liên kết các uv bạn tính toán với các vị trí (vì bạn không hiển thị tính toán vị trí). Nó cũng không rõ làm thế nào bạn có xpos_in_texture (bạn nên giải thích cách bạn tính chúng cho các góc của sprite của bạn). Tôi đoán là bạn đã tính sai.

+0

Đây là một lời giải thích tuyệt vời, và tôi gặp phải vấn đề này khi triển khai hệ thống văn bản dưới DirectX 11. Điều này: "2. Sử dụng vị trí của X, X + chiều rộng chính xác" đã khắc phục sự cố tôi gặp phải. –

2

Một chút trễ, nhưng đối với hậu thế, tôi đã gặp vấn đề tương tự, với các điểm ảnh từ các vùng lân cận của bản đồ kết cấu xuất hiện thành các hình xếp/thu nhỏ khi thu phóng hoặc thu phóng chế độ xem. Tôi có kích thước glOrtho, glViewport, vv của mình được thiết lập chính xác, sau đó tôi nhận ra vấn đề là tôi đã mở rộng chế độ xem trước khi dịch máy ảnh, điều này có nghĩa là mặc dù tôi đã chụp đến một phần nhỏ của pixel và giới thiệu vấn đề về texel.

Vì vậy, nếu mã của bạn trông giống như thế này, nơi camera.zoom là một tổ chức phi số nguyên (ví dụ: 0,75):

glScalef(camera.zoom, camera.zoom, 1.0f); 
glTranslatef(camera.x, camera.y, 0.0f); 

Bạn sẽ muốn chắc chắn kết quả của bản dịch sau khi mở rộng quy mô căn chỉnh với toàn bộ pixel trên màn hình, vì vậy, bạn có thể làm điều gì đó như:

glScalef(camera.zoom, camera.zoom, 1.0f); 
glTranslatef(
    floor(camera.x * camera.zoom)/camera.zoom, 
    floor(camera.y * camera.zoom)/camera.zoom, 
    0.0f);