我在Monogame中有一些带有一些基元和精灵的2D场景(即在PrimitiveBatches和SpriteBatches中),我想用圆形镜头创建一个放大镜效果,显示其下面内容的缩放视图。我该怎么做?
感谢。
答案 0 :(得分:1)
我不使用你的环境,但我总是用像素位移来做这个效果。如果您对渲染场景进行了像素访问(理想情况下仍然在后缓冲区中,因此它不会闪烁),那么只需将镜头内的像素移动到向外位置即可。使用恒定位移或更好的是当你在中间移动更多(更大的变焦)而不是靠近边缘时。
典型实现如下:
temp
缓冲区 (x,y)
通过镜头区域 r
计算已处理像素的实际半径(x0,y0)
忽略镜头区域(r>R)
计算已处理像素的实际缩放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
将像素从temp
复制到后备缓冲区或屏幕
backbuffer(x,y)=temp(x0+(x-x0)/m,y0+(y-y0)/m)
此处 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):
如果您需要帮助以了解我的代码中的gfx访问权限,请参阅: