So I've been playing around with OpenCl a lot recently and it's pretty impressive. The first thing I wanted to do was to make an mandelbrot set generator, so I did. It works wonderful and I am really amazed by the results, almost a thousand times faster than my js version, but I am not satisfied by the coloring as it is now.
The colors are pretty okay at standard zoom but it quickly gets pretty ugly when you zoom in. I am aware of the continuous coloring that's supose to eliminate banding, but I am unsure how to use it properly. Right now the coloring is based on the iteration count generating a HSV color.

So for my question, how am I supose to use to use the continuous coloring formula to achieve a smooth coloring that also works on high zoom levels ?


5 Years
Discussion Span
Last Post by K0ns3rv

I haven't worked with mandelbrot set but try using this :

//zn is your last complex number used and n is the iteration count
flota smoothcolor = n + 1 - Math.log(Math.log(zn.abs()))/Math.log(2)
Color col = Color.HSBtoRGB(0.95f + 10 * smoothcolor ,0.6f,1.0f);

I've trie something like that but it just doesn't work at all. Smoothcolor is supose to be within [0,1) if you divide it by max iterations. And the code you posted doesn't seem to make any sense because for Color.HSBtoRGB the hue should be [0,1] and in that case if iterations are n it will be in [n,n+1).

Maybe I am doing something really wrong, this is my current code anyway:

#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
	#define TYPE double
	#define TYPE float
typedef unsigned int uint;

typedef struct Complex {
	TYPE re;
	TYPE im;
} Complex;

typedef struct Mandelbrot{
	Complex min;
	Complex max;
	ushort height;
	ushort width;
	TYPE xScale;
	TYPE yScale;
	ushort iter;

typedef struct Color{
	ushort r;
	ushort g;
	ushort b;

Complex cSquare(const Complex c){
	TYPE x = c.re;
	TYPE y = c.im;
	Complex result;
	result.re = x*x - y*y; 
	result.im = 2*y*x;
	return result;

Complex cAdd(const Complex a,const Complex b){
	Complex c;
	c.re = a.re + b.re;
	c.im = a.im + b.im;
	return c;

TYPE cDot(const Complex c){
	return (c.re*c.re+c.im*c.im); 

TYPE cAbs(const Complex c){
	return sqrt(cDot(c));

double smooth(Complex z, int n){
	return n - log (log (cAbs(z)))/ log (2.0);


__kernel void kernel_entry(__constant struct Mandelbrot* b,__global  Color* R,__global double* dbg) {
	TYPE esc = 4.0;
	int index = get_global_id(0);
	int iter = 0;
	int x = index%b->width;
	int y = index/b->width;
        Complex z;
	z.re = 0;
	z.im = 0;
	Complex c;
	c.re = b->min.re + b->xScale*x;
	c.im = b->min.im + b->yScale*y;
	while (iter < b->iter ){
		z = cSquare(z);
		z = cAdd(z,c);
		float a = 0;
		a = cDot(z);
		if ( a > esc )


	Color result;
	double i = smooth(z,iter);
	if ( iter == b->iter ) {
		result.r = 0;
		result.g = 0;
		result.b = 0;

		i /= b->iter;
		double s = 0.6+i;
		result = HSVtoRGB(s*360,0.6,1.0);
	R[index] = result;
	dbg[index] = i;
This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.