2016-10-19 1 views

Répondre

1

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:

  1. zone de lentille de copie certaine tampon temp
  2. boucle (x,y) à travers la zone de lentille
  3. 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)
  4. 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

  5. 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):

preview

Si vous avez besoin d'aide à comprendre l'accès GFX dans mon siège de code:

+0

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

+0

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