Tôi gặp một số khó khăn khi hiển thị một loạt các giá trị cho mục tiêu kết xuất. Các giá trị không bao giờ kết thúc trong phạm vi chính xác mà tôi muốn. Về cơ bản, tôi sử dụng một quad toàn màn hình và một pixel shader để kết xuất với kết cấu renderertarget của tôi và sau đó có ý định sử dụng các tọa độ kết cấu làm cơ sở cho một số tính toán trong shader. Các tọa độ kết cấu của phạm vi quad từ (0,0) ở trên cùng bên trái đến (1,1) ở góc dưới bên phải ... vấn đề là, sau khi nội suy, các giá trị này không đến được bộ đổ bóng pixel như vậy .
Một ví dụ: Tôi kết xuất với kết cấu 4 x 4 và trình đổ bóng trong trường hợp này chỉ đơn giản là xuất ra tọa độ kết cấu (u, v) trong các kênh màu đỏ và màu xanh lá cây:
return float4(texCoord.rg, 0, 1);
Những gì tôi muốn nhận được từ nó là một kết cấu trong đó pixel ở phía trên bên trái là RGB (0,0,0) và do đó màu đen, pixel ở phía trên bên phải là RGB (255,0,0) và do đó sáng màu đỏ và pixel ở phía dưới bên trái là RGB (0,255,0) - màu xanh lá cây tươi sáng.
Tuy nhiên, thay vào đó tôi nhận được điều này ở bên phải:
(kết xuất quad thẳng, không hiệu chỉnh)
Điểm ảnh trên cùng bên trái là màu đen, nhưng tôi chỉ nhận được màu đỏ và xanh đậm tương đối ở các góc khác. Giá trị RGB của chúng là (191,0,0) và (0,191,0). Tôi nghi ngờ rằng nó phải làm với các vị trí lấy mẫu của hình tứ giác: pixel trên cùng bên trái lấy mẫu chính xác góc trên cùng bên trái của hình tứ giác và lấy (0,0) làm tọa độ UV, nhưng các pixel góc khác không lấy mẫu từ các góc khác của tứ giác. Tôi đã minh họa điều này trong hình ảnh bên trái với hộp màu xanh tượng trưng cho hình tứ giác và các chấm trắng tọa độ lấy mẫu phía trên.
Bây giờ tôi đã biết về độ lệch nửa pixel mà bạn nên áp dụng cho tọa độ của mình khi hiển thị các góc được căn chỉnh theo màn hình trong Direct3D9. Chúng ta hãy xem loại kết quả tôi nhận được từ điều này:
(quad được hiển thị với độ lệch nửa pixel của DX9)
Màu đỏ và màu xanh lá cây đã sáng hơn nhưng vẫn không chính xác: 223 là mức tối đa tôi có được trên kênh màu đỏ hoặc xanh lục. Nhưng bây giờ, tôi thậm chí không còn màu đen thuần khiết nữa mà thay vào đó là màu xám đen, vàng nhạt với RGB (32,32,0)!
Những gì tôi thực sự cần sẽ là loại kết xuất này:
(kết xuất mục tiêu, giảm kích thước quad)
Có vẻ như tôi phải di chuyển bên phải và viền dưới của hình tứ giác của tôi chính xác một pixel lên và sang trái, so với hình đầu tiên. Sau đó, cột bên phải và hàng pixel dưới cùng sẽ nhận được chính xác tọa độ UV ngay từ đường viền của hình tứ giác:
VertexPositionTexture[] quad = new VertexPositionTexture[]
{
new VertexPositionTexture(new Vector3(-1.0f, 1.0f, 1f), new Vector2(0,0)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, 1.0f, 1f), new Vector2(1,0)),
new VertexPositionTexture(new Vector3(-1.0f, -1.0f + pixelSize.Y, 1f), new Vector2(0,1)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, -1.0f + pixelSize.Y, 1f), new Vector2(1,1)),
};
Tuy nhiên, điều này không thực sự hiệu quả và khiến các pixel phía dưới và bên phải hoàn toàn không hiển thị. Tôi cho rằng các trung tâm của các pixel này không còn được bao phủ bởi bộ tứ nữa và do đó sẽ không được xử lý bởi trình đổ bóng. Nếu tôi thay đổi phép tính pixelSize bằng một số lượng nhỏ để làm cho số lượng lớn hơn gấp bốn lần thì nó sẽ hoạt động ... ít nhất là trên kết cấu 4 x 4. Nó không hoạt động trên các kết cấu nhỏ hơn và tôi sợ nó làm biến dạng một cách tinh tế sự phân phối đồng đều các giá trị uv trên các kết cấu lớn hơn:
Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);
(Tôi đã sửa đổi phép tính pixelSize bằng 0,001f - đối với các kết cấu nhỏ hơn, ví dụ: bảng tra cứu 1D, điều này không hoạt động và tôi phải tăng nó lên 0,01f hoặc một cái gì đó lớn hơn)
Tất nhiên đây là một ví dụ tầm thường và tôi có thể thực hiện phép tính này dễ dàng hơn nhiều trên CPU mà không phải lo lắng về việc ánh xạ tia cực tím đến các trung tâm pixel ... tuy nhiên, vẫn phải có một cách để thực sự hiển thị đầy đủ, hoàn chỉnh [0, 1] phạm vi đến pixel trên một mục tiêu kết xuất!?