Mam problem z renderowaniem wiązki wartości w rendertarget. Wartości nigdy nie kończą się w dokładnie takim zakresie, jaki chcę. Zasadniczo używam kwadratu pełnoekranowego i modułu cieniującego piksele do renderowania na mojej tekstu rendertarget, a następnie zamierzam użyć współrzędnych tekstury jako podstawy do niektórych obliczeń w module cieniującym. Współrzędne tekstury dla zakresu quada od (0,0) w lewym górnym rogu do (1,1) w prawym dolnym rogu ... problem polega na tym, że po interpolacji te wartości nie docierają do modułu cieniującego jako takiego .
Przykład: renderuję teksturę 4x4, a moduł cieniujący w tym przypadku po prostu wyświetla współrzędne tekstury (u, v) w kanałach czerwonym i zielonym:
return float4(texCoord.rg, 0, 1);
Chcę z niego uzyskać teksturę, w której piksel w lewym górnym rogu to RGB (0,0,0), a zatem czarny, piksel w prawym górnym rogu to RGB (255,0,0), a zatem jasny czerwony, a piksel w lewym dolnym rogu to RGB (0,255,0) - jasna zieleń.
Zamiast tego widzę to tutaj po prawej stronie:
(renderowanie prostego kwadratu, bez korekty)
Lewy górny piksel jest czarny, ale w pozostałych rogach dostaję stosunkowo ciemnoczerwony i ciemnozielony kolor. Ich wartości RGB to (191,0,0) i (0,191,0). Podejrzewam, że ma to związek z lokalizacjami próbkowania kwadratu: lewy górny piksel poprawnie próbkuje lewy górny róg kwadratu i otrzymuje (0,0) jako współrzędne UV, ale pozostałe piksele narożne nie próbkują z pozostałe rogi quada. Zilustrowałem to na lewym obrazie z niebieskim polem reprezentującym kwadrat, a białymi kropkami górne współrzędne próbkowania.
Teraz wiem o przesunięciu o pół piksela, które powinieneś zastosować do swoich współrzędnych podczas renderowania quad wyrównanych do ekranu w Direct3D9. Zobaczmy, jaki wynik mam z tego:
(quad renderowany z przesunięciem pół piksela DX9)
Czerwone i zielone stały się jaśniejsze, ale nadal nie są poprawne: 223 to maksimum, jakie dostaję na kanale koloru czerwonego lub zielonego. Ale teraz nie mam już nawet czystej czerni, ale zamiast tego ciemnożółty szary z RGB (32,32,0)!
Tak naprawdę potrzebuję tego rodzaju renderowania:
(docelowy rendering, zmniejszony rozmiar quada)
Wygląda na to, że muszę przesunąć prawą i dolną ramkę mojego quada dokładnie o jeden piksel w górę i w lewo, w porównaniu do pierwszej cyfry. Następnie prawa kolumna i dolny rząd pikseli powinny poprawnie uzyskać współrzędne UV od granicy kwadratu:
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)),
};
Jednak to nie całkiem zadziałało i spowodowało, że dolne i prawe piksele w ogóle się nie renderowały. Podejrzewam, że centra tych pikseli nie są już objęte quadem i dlatego nie będą przetwarzane przez moduł cieniujący. Jeśli zmienię obliczenie pixelSize o niewielką ilość, aby quad był nieco większy, to trochę to działa ... przynajmniej na fakturze 4x4. Nie działa na mniejszych teksturach i obawiam się, że subtelnie zaburza równomierny rozkład wartości UV na większych teksturach:
Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);
(Zmodyfikowałem obliczenie pixelSize o 0,001f - w przypadku mniejszych tekstur, np. Tabel przeglądowych 1D, to nie działa i muszę go zwiększyć do 0,01f lub coś większego)
Oczywiście jest to trywialny przykład i mógłbym wykonać te obliczenia o wiele łatwiej na CPU bez martwienia się o mapowanie UV do centrów pikseli ... jednak musi istnieć sposób, aby faktycznie renderować pełne, pełne [0, 1] zakres do pikseli w rendertargecie !?