J'ai du mal à restituer un tas de valeurs à une cible de rendu. Les valeurs ne se retrouvent jamais dans la plage exacte que je souhaite. Fondamentalement, j'utilise un quadruple plein écran et un pixel shader pour effectuer le rendu sur ma texture de rendu cible, puis j'ai l'intention d'utiliser les coordonnées de texture comme base pour certains calculs dans le shader. Les coordonnées de texture de la plage quadruple de (0,0) en haut à gauche à (1,1) dans le coin inférieur droit ... le problème est, après interpolation, ces valeurs n'arrivent pas au pixel shader en tant que tel .
Un exemple: je rend une texture 4x4 et le shader dans ce cas produit simplement les coordonnées de texture (u, v) dans les canaux rouge et vert:
return float4(texCoord.rg, 0, 1);
Ce que je veux en retirer, c'est une texture où le pixel en haut à gauche est RGB (0,0,0) et donc noir, le pixel en haut à droite est RGB (255,0,0) et donc un brillant rouge et le pixel en bas à gauche est RVB (0,255,0) - un vert brillant.
Cependant, au lieu de cela, je le trouve ici à droite:
(rendu quadruple droit, pas de correction)
Le pixel supérieur gauche est noir, mais je n'obtiens qu'un rouge et un vert foncé relativement foncés dans les autres coins. Leurs valeurs RVB sont (191,0,0) et (0,191,0). Je soupçonne fortement que cela a à voir avec les emplacements d'échantillonnage du quad: le pixel supérieur gauche échantillonne correctement le coin supérieur gauche du quad et obtient (0,0) en coordonnées UV, mais les autres pixels d'angle ne sont pas échantillonnés à partir de les autres coins du quad. J'ai illustré cela dans l'image de gauche avec la boîte bleue représentant le quad et les points blancs les coordonnées d'échantillonnage supérieures.
Maintenant, je connais le décalage d'un demi-pixel que vous devez appliquer à vos coordonnées lors du rendu des quadrilatères alignés à l'écran dans Direct3D9. Voyons quel genre de résultat j'obtiens:
(rendu quad avec le décalage d'un demi-pixel de DX9)
Le rouge et le vert sont devenus plus lumineux mais ne sont toujours pas corrects: 223 est le maximum que j'obtiens sur le canal de couleur rouge ou vert. Mais maintenant, je n'ai même plus de noir pur, mais plutôt un gris foncé et jaunâtre avec RGB (32,32,0)!
Ce dont j'ai réellement besoin serait ce type de rendu:
(rendu cible, taille quad réduite)
Il semble que je doive déplacer le bord droit et le bord inférieur de mon quad exactement d'un pixel vers le haut et vers la gauche, par rapport à la première figure. Ensuite, la colonne de droite et la rangée inférieure de pixels devraient toutes obtenir correctement les coordonnées UV directement à partir de la bordure du quad:
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)),
};
Cependant, cela n'a pas tout à fait fonctionné et a empêché le rendu des pixels inférieur et droit. Je suppose que les centres de ces pixels ne sont plus couverts par le quad et ne seront donc pas traités par le shader. Si je modifie le calcul de pixelSize par une petite quantité pour agrandir le quad, il fonctionne un peu ... au moins sur une texture 4x4. Cela ne fonctionne pas sur les textures plus petites et je crains que cela ne déforme subtilement la distribution uniforme des valeurs UV sur les textures plus grandes:
Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);
(J'ai modifié le calcul pixelSize de 0,001f - pour les textures plus petites, par exemple les tables de recherche 1D, cela ne fonctionne pas et je dois l'augmenter à 0,01f ou quelque chose de plus grand)
Bien sûr, ceci est un exemple trivial et je pourrais faire ce calcul beaucoup plus facilement sur le CPU sans avoir à se soucier de mapper les UV aux centres de pixels ... encore, il doit y avoir un moyen de rendre un rendu complet et complet [0, 1] plage de pixels sur une cible de rendu!?