Simplified shader code and added comments
This commit is contained in:
parent
64ea6393ec
commit
d64af0a39f
|
|
@ -15,41 +15,34 @@ uniform float zoom; // Zoom of the scale
|
||||||
uniform int maxIterations; // Max iterations per pixel
|
uniform int maxIterations; // Max iterations per pixel
|
||||||
|
|
||||||
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
||||||
|
const float max2 = max * max; // Square of max to avoid computing square root
|
||||||
float modI(float a, float b) {
|
|
||||||
float m = a - floor((a + 0.5)/b)*b;
|
|
||||||
return floor(m + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
||||||
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
||||||
vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
||||||
z.x += offset.x;
|
c.x += offset.x;
|
||||||
z.y += offset.y;
|
c.y += offset.y;
|
||||||
float a = z.x;
|
float a = 0.0;
|
||||||
float b = z.y;
|
float b = 0.0;
|
||||||
float absOld = 0.0;
|
|
||||||
float convergeNumber = float(maxIterations);
|
// The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function
|
||||||
|
// fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0
|
||||||
|
// Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i
|
||||||
|
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
while (iter < maxIterations)
|
while (iter < maxIterations)
|
||||||
{
|
{
|
||||||
float aa = a*a;
|
float aa = a*a;
|
||||||
float bb = b*b;
|
float bb = b*b;
|
||||||
float abs = sqrt(aa + bb);
|
if (aa + bb > max2)
|
||||||
if (abs > max)
|
|
||||||
{
|
|
||||||
convergeNumber = float(iter) + (max - absOld)/(abs - absOld);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
float twoab = 2.0*a*b;
|
float twoab = 2.0*a*b;
|
||||||
a = aa - bb + z.x;
|
a = aa - bb + c.x;
|
||||||
b = twoab + z.y;
|
b = twoab + c.y;
|
||||||
|
|
||||||
absOld = abs;
|
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,9 +52,9 @@ void main()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float normR = modI(convergeNumber, 55.0)/55.0;
|
float normR = float(iter - (iter/55)*55)/55.0;
|
||||||
float normG = modI(convergeNumber, 69.0)/69.0;
|
float normG = float(iter - (iter/69)*69)/69.0;
|
||||||
float normB = modI(convergeNumber, 40.0)/40.0;
|
float normB = float(iter - (iter/40)*40)/40.0;
|
||||||
|
|
||||||
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,41 +13,34 @@ uniform float zoom; // Zoom of the scale
|
||||||
uniform int maxIterations; // Max iterations per pixel
|
uniform int maxIterations; // Max iterations per pixel
|
||||||
|
|
||||||
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
||||||
|
const float max2 = max * max; // Square of max to avoid computing square root
|
||||||
float modI(float a, float b) {
|
|
||||||
float m = a - floor((a + 0.5)/b)*b;
|
|
||||||
return floor(m + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
||||||
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
||||||
vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
||||||
z.x += offset.x;
|
c.x += offset.x;
|
||||||
z.y += offset.y;
|
c.y += offset.y;
|
||||||
float a = z.x;
|
float a = 0.0;
|
||||||
float b = z.y;
|
float b = 0.0;
|
||||||
float absOld = 0.0;
|
|
||||||
float convergeNumber = float(maxIterations);
|
// The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function
|
||||||
|
// fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0
|
||||||
|
// Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i
|
||||||
|
|
||||||
int iter = 0;
|
int iter = 0;
|
||||||
while (iter < maxIterations)
|
while (iter < maxIterations)
|
||||||
{
|
{
|
||||||
float aa = a*a;
|
float aa = a*a;
|
||||||
float bb = b*b;
|
float bb = b*b;
|
||||||
float abs = sqrt(aa + bb);
|
if (aa + bb > max2)
|
||||||
if (abs > max)
|
|
||||||
{
|
|
||||||
convergeNumber = float(iter) + (max - absOld)/(abs - absOld);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
float twoab = 2.0*a*b;
|
float twoab = 2.0*a*b;
|
||||||
a = aa - bb + z.x;
|
a = aa - bb + c.x;
|
||||||
b = twoab + z.y;
|
b = twoab + c.y;
|
||||||
|
|
||||||
absOld = abs;
|
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,9 +50,9 @@ void main()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float normR = modI(convergeNumber, 55.0)/55.0;
|
float normR = float(iter - (iter/55)*55)/55.0;
|
||||||
float normG = modI(convergeNumber, 69.0)/69.0;
|
float normG = float(iter - (iter/69)*69)/69.0;
|
||||||
float normB = modI(convergeNumber, 40.0)/40.0;
|
float normB = float(iter - (iter/40)*40)/40.0;
|
||||||
|
|
||||||
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
gl_FragColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,47 +14,44 @@ uniform float zoom; // Zoom of the scale
|
||||||
uniform int maxIterations; // Max iterations per pixel
|
uniform int maxIterations; // Max iterations per pixel
|
||||||
|
|
||||||
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
const float max = 4.0; // We consider infinite as 4.0: if a point reaches a distance of 4.0 it will escape to infinity
|
||||||
|
const float max2 = max * max; // Square of max to avoid computing square root
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
// The pixel coordinates are scaled so they are on the mandelbrot scale
|
||||||
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
// NOTE: fragTexCoord already comes as normalized screen coordinates but offset must be normalized before scaling and zoom
|
||||||
vec2 z = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
vec2 c = vec2((fragTexCoord.x - 0.5)*2.5, (fragTexCoord.y - 0.5)*1.5)/zoom;
|
||||||
z.x += offset.x;
|
c.x += offset.x;
|
||||||
z.y += offset.y;
|
c.y += offset.y;
|
||||||
float a = z.x;
|
float a = 0.0;
|
||||||
float b = z.y;
|
float b = 0.0;
|
||||||
float absOld = 0.0;
|
|
||||||
float convergeNumber = float(maxIterations);
|
|
||||||
|
|
||||||
int iterations = 0;
|
// The Mandelbrot set is a two-dimensional set defined in the complex plane on which the iteration of the function
|
||||||
for (iterations = 0; iterations < maxIterations; iterations++)
|
// fc(z) = z^2 + c on the complex numbers c from the plane does not diverge to infinity starting at z = 0
|
||||||
|
// Here: z = a + bi. Iterations: z -> z^2 + c = (a + bi)^2 + (c.x + c.yi) = (a^2 - b^2 + c.x) + (2ab + c.y)i
|
||||||
|
|
||||||
|
int iter = 0;
|
||||||
|
for (iter = 0; iter < maxIterations; ++iter)
|
||||||
{
|
{
|
||||||
float aa = a*a;
|
float aa = a*a;
|
||||||
float bb = b*b;
|
float bb = b*b;
|
||||||
float abs = sqrt(aa + bb);
|
if (aa + bb > max2)
|
||||||
if (abs > max)
|
|
||||||
{
|
|
||||||
convergeNumber = float(iterations);// + (max - absOld)/(abs - absOld);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
float twoab = 2.0*a*b;
|
float twoab = 2.0*a*b;
|
||||||
a = aa - bb + z.x;
|
a = aa - bb + c.x;
|
||||||
b = twoab + z.y;
|
b = twoab + c.y;
|
||||||
|
|
||||||
absOld = abs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iterations >= maxIterations)
|
if (iter >= maxIterations)
|
||||||
{
|
{
|
||||||
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
|
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float normR = float(int(convergeNumber)%55)/55.0;
|
float normR = float(iter%55)/55.0;
|
||||||
float normG = float(int(convergeNumber)%69)/69.0;
|
float normG = float(iter%69)/69.0;
|
||||||
float normB = float(int(convergeNumber)%40)/40.0;
|
float normB = float(iter%40)/40.0;
|
||||||
|
|
||||||
finalColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
finalColor = vec4(sin(normR*PI), sin(normG*PI), sin(normB*PI), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ int main(void)
|
||||||
// Offset and zoom to draw the mandelbrot set at. (centered on screen and default size)
|
// Offset and zoom to draw the mandelbrot set at. (centered on screen and default size)
|
||||||
float offset[2] = { startingOffset[0], startingOffset[1] };
|
float offset[2] = { startingOffset[0], startingOffset[1] };
|
||||||
float zoom = startingZoom;
|
float zoom = startingZoom;
|
||||||
|
// Depending on the zoom the mximum number of iterations must be adapted to get more detail as we zzoom in
|
||||||
|
// The solution is not perfect, so a control has been added to increase/decrease the number of iterations with UP/DOWN keys
|
||||||
int maxIterations = 333;
|
int maxIterations = 333;
|
||||||
float maxIterationsMultiplier = 166.5f;
|
float maxIterationsMultiplier = 166.5f;
|
||||||
|
|
||||||
|
|
@ -160,9 +162,11 @@ int main(void)
|
||||||
updateShader = true;
|
updateShader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case a parameter has been changed, update the shader values
|
||||||
if (updateShader)
|
if (updateShader)
|
||||||
{
|
{
|
||||||
// As we zoom in, increase the number of max iterations to get more detail
|
// As we zoom in, increase the number of max iterations to get more detail
|
||||||
|
// Aproximate formula, but it works-ish
|
||||||
maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier);
|
maxIterations = (int)(sqrtf(2.0f*sqrtf(fabsf(1.0f - sqrtf(37.5f*zoom))))*maxIterationsMultiplier);
|
||||||
|
|
||||||
// Update the shader uniform values!
|
// Update the shader uniform values!
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user