Simple fractals with Qt 5 shaders
Tags: programming, projects
I wanted to play around with some shaders recently so I was looking for simple things to implement. One of the nicest ways to get started in a new graphics framework is to get some fractals going—so this is what I did.
The Mandelbrot shader
We first require some GLSL magic to make the Mandelbrot fractal happen:
uniform int iterations;
uniform highp vec2 centre;
uniform highp float scale;
varying highp vec2 texture_out;
void main()
{
vec2 z;
vec2 c;
c.x = scale * ( 3.0 * texture_out.x - 2.0 ) + centre.x;
c.y = scale * ( 2.0 * texture_out.y - 1.0 ) + centre.y;
z = c;
int i = 0;
for(; i < iterations; ++i)
{
float x = z.x*z.x - z.y*z.y + c.x;
float y = z.x*z.y + z.y*z.x + c.y;
if( x*x + y*y > 4.0 )
break;
z.x = x;
z.y = y;
}
vec4 color = vec4(0.0);
if(i < iterations - 1)
{
color.x = sin(float(i) / 3.0);
color.y = sin(float(i) / 6.0);
color.z = cos(float(i) / 12.0 + 3.141 / 4.0);
}
gl_FragColor = color;
}
Basically, I am filling the texture coordinates with colours, based on
the number of iterations it took for the series to reach the desired
norm of 4.0. The scale
and centre
parameter exist only for the
purpose of modifying the view within the controlling application.
The Julia set shader
Now let’s add another shader for the Julia set:
uniform int iterations;
uniform highp vec2 c;
uniform highp vec2 centre;
uniform highp float scale;
varying highp vec2 texture_out;
void main()
{
vec2 z;
z.x = scale * ( 3.0 * texture_out.x - 2.0 ) + centre.x;
z.y = scale * ( 2.0 * texture_out.y - 1.0 ) + centre.y;
int i = 0;
for(; i < iterations; ++i)
{
float x = z.x*z.x - z.y*z.y + c.x;
float y = z.x*z.y + z.y*z.x + c.y;
if( x*x + y*y > 4.0 )
break;
z.x = x;
z.y = y;
}
vec4 color = vec4(0.0);
if(i < iterations - 1)
{
color.x = sin(float(i) / 3.0);
color.y = sin(float(i) / 6.0);
color.z = cos(float(i) / 12.0 + 3.141 / 4.0);
}
gl_FragColor = color;
}
Note that the differences between the shaders are minuscule at best.
Using Qt 5 to put it together
Putting the fractals on the screen then turned out to be a rather easy
exercise with Qt 5. Using a QGLShaderProgram
, I only need to render a
quad onto the screen, bind the appropriate shader, and we are done.
Check out the code on
GitHub for more details.
Screenshots
Click to see the screenshots in their original resolution.