Je n'utilise pas votre environnement mais j'ai toujours fait cet effet avec le déplacement des pixels. Si vous avez un accès pixel à la scène rendue (idéalement, alors qu'il est toujours dans un tampon arrière de sorte qu'il ne scintille pas), il suffit de déplacer les pixels à l'intérieur de votre objectif vers les positions extérieures. Soit utiliser un déplacement constant ou mieux c'est quand vous bougez plus (plus grand zoom) au milieu et moins près des bords.
mise en œuvre typique se présente comme suit:
- zone de lentille de copie certaine tampon
temp
- boucle
(x,y)
à travers la zone de lentille
- rayon réel de calcul
r
de pixel traité du centre de la lentille (x0,y0)
ignore les pixels en dehors de la zone de l'objectif (r>R)
zoom Compute réelle m
de pixel traité
J'aime utiliser cos
pour cela comme ceci:
m=1.0+(1.5*cos(0.5*M_PI*double(r)/double(r0))); // M_PI=3.1415...
vous pouvez jouer avec les 1.0,1.5
constantes. Ils déterminent le (1.0)
et le zoom maximal (1.0+1.5)
. Aussi ceci est pour cos
prendre angle [rad]
donc si le vôtre besoin [deg]
changer la place du 0.5*M_PI
avec 90.0
pixel copie de temp
à backbuffer ou à l'écran
backbuffer(x,y)=temp(x0+(x-x0)/m,y0+(y-y0)/m)
Ici C++/VCL exemple:
void TMain::draw()
{
// clear bmp (if image not covering whole area)
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
// copy background image
bmp->Canvas->Draw(0,0,jpg); // DWORD pxy[ys][xs] is bmp direct pixel access, (xs,ys) is bmp size
// here comes the important stuff:
int x0=mx,y0=my; // position = mouse
const int r0=50; // radius
DWORD tmp[2*r0+3][2*r0+3]; // temp buffer
double m;
int r,x,y,xx,yy,xx0,xx1,yy0,yy1;
// zoom area bounding box
xx0=x0-r0; if (xx0< 0) xx0=0;
xx1=x0+r0; if (xx1>=xs) xx1=xs-1;
yy0=y0-r0; if (yy0< 0) yy0=0;
yy1=y0+r0; if (yy1>=ys) yy1=ys-1;
// copy bmp to tmp
for (y=yy0;y<=yy1;y++)
for (x=xx0;x<=xx1;x++)
tmp[y-yy0][x-xx0]=pyx[y][x];
// render zoomed area
for (y=yy0;y<=yy1;y++)
for (x=xx0;x<=xx1;x++)
{
// compute radius
xx=x-x0;
yy=y-y0;
r=sqrt((xx*xx)+(yy*yy));
if (r>r0) continue;
if (r==r0) { pyx[y][x]=clWhite; continue; }
// compute zoom: 2.5 on center, 1.0 at eges
m=1.0+(1.5*cos(0.5*M_PI*double(r)/double(r0))); // M_PI=3.1415...
// compute displacement
xx=double(double(xx)/m)+x0;
yy=double(double(yy)/m)+y0;
// copy
if ((xx>=xx0)&&(yy>=yy0)&&(xx<=xx1)&&(yy<=yy1))
pyx[y][x]=tmp[yy-yy0][xx-xx0];
}
// just refresh screen with backbuffer
Canvas->Draw(0,0,bmp);
}
Et aperçu GIF ici animé (est abaissé par le codage GIF qualité et fps):
Si vous avez besoin d'aide à comprendre l'accès GFX dans mon siège de code:
Merci pour cette suggestion détaillée. Cependant, je ne sais pas comment accéder aux pixels de mon pipeline Monogame. Et je voudrais certainement éviter d'agrandir simplement les données vectorielles pixellisées car cela donnerait une vue mise à l'échelle pixélisée. – Tamori
En Java2D, je créerais un objet graphique à partir d'une nouvelle image, appliquerais une transformation d'échelle correspondant au facteur de zoom, dessinerais mon contenu avec une zone de découpage correspondant à la forme de l'objectif et dessinerais l'image dans la peinture de ma toile. J'imagine que la stratégie est similaire dans XNA, mais je ne connais pas les éléments d'API que je peux utiliser pour le faire. J'ai cherché un peu et il me semble que je devrais définir un RenderTarget2D, y dessiner mes trucs avec mes paramètres de rendu et ensuite les dessiner dans le buffer arrière. Je ne sais pas exactement comment j'appliquerais une transformation d'échelle et un découpage circulaire. – Tamori