如何放大 Mandelbrot 集中的光标点?

How to zoom in on cursor point in Mandelbrot Set?

我目前正在尝试为我一直在处理的 Mandelbrot 集代码实现缩放功能。我的想法是在我 left/right 单击的地方缩放 in/out。到目前为止,每当我单击屏幕时,分形确实被放大了。问题是分形不是在原点呈现的——换句话说,它没有放大到我想要的点。我希望通过这里我可以获得代码审查和概念上的理解,了解如何在一般情况下放大一个点。

以下是我在使用转义算法之前转换像素坐标的方式:

MandelBrot.Frag

vec2 normalizedFragPos = (gl_FragCoord.xy/windowSize); //normalize fragment position

dvec2 scaledFragPos = normalizedFragPos*aspectRatio;

scaledFragPos -= aspectRatio/2; //Render the fractal at center of window

scaledFragPos /= scale; //Factor to zoom in or out coordinates.

scaledFragPos -= translation; //Translate coordinate
//Escape Algorithm Below

在我的左键单击手柄上,我认为我应该将光标位置转换为与 Mandelbrot 范围相同的坐标范围。所以我基本上做了我在片段着色器中做的同样的事情:

Window.cpp

float x_coord{ float(GET_X_LPARAM(informaton_long))/size.x }; // normalized mouse x-coordinate
float y_coord{ float(GET_Y_LPARAM(informaton_long))/size.y }; // normalized mouse y-coordinate

x_coord *= aspectRatio[0]; //move point based of relative position to length of window.
y_coord *= aspectRatio[1]; //move point based of relative position to width of window.
x_coord /= scale; //Scale point to match previous zoom factor
y_coord /= scale; //Scale point to match previous zoom factor
translation[0] = x_coord;
translation[1] = y_coord;
//increment scale
scale += .15f;

让我们应用一些代数。您的着色器执行以下转换:

mandelbrotCoord = aspectRatio * (gl_FragCoord / windowSize - 0.5) / scale - translation

当我们放大mouseCoord时,我们想改变scale并调整translation,使鼠标下的madelbrotCoord保持不变。为此,我们首先使用旧比例计算鼠标下的 mandelbrotCoord

mandelbrotCoord = aspectRatio * (mouseCoord / windowSize - 0.5) / scale - translation

然后改变比例(顺便说一句,应该按指数方式改变):

scale *= 1.1;

然后解决新的翻译:

translation = aspectRatio * (mouseCoord / windowSize - 0.5) / scale - mandelbrotCoord

另请注意,您的系统可能报告鼠标坐标 y 坐标向下增加,而 OpenGL 的 window y 坐标向上增加(除非您用 glClipControl).因此,您可能还需要翻转 mouseCoordy 坐标。

mouseCoord[1] = windowSize[1] - mouseCoord[1];

为了获得最佳效果,我还会将鼠标坐标调整到像素的中间 (+0.5, +0.5)。

综合起来:

float mouseCoord[] = {
    GET_X_LPARAM(informaton_long) + 0.5,
    GET_Y_LPARAM(informaton_long) + 0.5
};
mouseCoord[1] = size[1] - mouseCoord[1];

float anchor[] = {
    aspectRatio[0] * (mouseCoord[0] / size[0] - 0.5) / scale - translation[0],
    aspectRatio[1] * (mouseCoord[1] / size[1] - 0.5) / scale - translation[1]
};

scale *= 1.1;

translation[0] = aspectRatio[0] * (mouseCoord[0] / size[0] - 0.5) / scale - anchor[0];
translation[1] = aspectRatio[1] * (mouseCoord[1] / size[1] - 0.5) / scale - anchor[1];

注意:上面的一些数学运算可能会被取消。但是,如果您想实现适当的平移和缩放功能(当您在平移时可以使用鼠标滚轮进行缩放时),那么您需要存储平移开始位置的初始 mandelbrotCoord,然后在随后的运动和滚轮事件,直到释放鼠标。令人惊讶的是,大量的图片浏览者都把这部分弄错了!