如何放大 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
).因此,您可能还需要翻转 mouseCoord
的 y
坐标。
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
,然后在随后的运动和滚轮事件,直到释放鼠标。令人惊讶的是,大量的图片浏览者都把这部分弄错了!
我目前正在尝试为我一直在处理的 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
).因此,您可能还需要翻转 mouseCoord
的 y
坐标。
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
,然后在随后的运动和滚轮事件,直到释放鼠标。令人惊讶的是,大量的图片浏览者都把这部分弄错了!