绘制一个圆形放大镜,显示XNA / Monogame中的缩放基础内容(2D)

时间:2016-10-19 21:54:09

标签: c# graphics xna zoom monogame

我在Monogame中有一些带有一些基元和精灵的2D场景(即在PrimitiveBatches和SpriteBatches中),我想用圆形镜头创建一个放大镜效果,显示其下面内容的缩放视图。我该怎么做?

感谢。

1 个答案:

答案 0 :(得分:1)

我不使用你的环境,但我总是用像素位移来做这个效果。如果您对渲染场景进行了像素访问(理想情况下仍然在后缓冲区中,因此它不会闪烁),那么只需将镜头内的像素移动到向外位置即可。使用恒定位移或更好的是当你在中间移动更多(更大的变焦)而不是靠近边缘时。

典型实现如下:

  1. 将镜头区域复制到某个temp缓冲区
  2. 循环(x,y)通过镜头区域
  3. 从镜头中心r 计算已处理像素的实际半径(x0,y0) 忽略镜头区域(r>R)
  4. 之外的像素
  5. 计算已处理像素的实际缩放m

    我喜欢这样使用cos

    m=1.0+(1.5*cos(0.5*M_PI*double(r)/double(r0))); // M_PI=3.1415...
    

    您可以使用1.0,1.5常量。它们确定最小(1.0)和最大(1.0+1.5)缩放。这也是cos[rad]中采取角度的问题所以如果你需要[deg]而是用0.5*M_PI改变90.0

  6. 将像素从temp复制到后备缓冲区或屏幕

    backbuffer(x,y)=temp(x0+(x-x0)/m,y0+(y-y0)/m)
    
  7. 此处 C ++ / VCL 示例:

    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);
        }
    

    这里有动画GIF预览(GIF编码降低了质量和fps):

    preview

    如果您需要帮助以了解我的代码中的gfx访问权限,请参阅: