private static Thread createShaderThread(final Image drawing,
			final Color foregroundColor,
			final Color backgroundColor,
			final ReentrantLock drawingLock,
			final int scale, 
			final Point2D center) {
		Thread shaderThread = new Thread() {

			@Override
			public void run() {
				System.out.println("Shader: [START]");
				int id = currentDrawingId;
				int currentIterations = iterations;
				super.run();
				
				int width = drawing.getWidth(null);
				int height = drawing.getHeight(null);
				
				Point pixelCenter = new Point(width / 2, height / 2);
				
				while (active) {
					// TODO: remove busy-wait
					while (true) {
						queueLock.lock();
						if (toDoList.size() == 0) {
							queueLock.unlock();
							break;
						}
						Point p = toDoList.poll();
						int i = p.x;
						int j = p.y;
						queueLock.unlock();
						
						double k = 0;
						
						double aliasInterval = 1.0 / antiAliasing;
						for (int aliasx = 0; aliasx < antiAliasing; ++aliasx) {
							for (int aliasy = 0; aliasy < antiAliasing; ++aliasy) {
								double x = i - 0.5 + aliasInterval / 2 + aliasInterval * aliasx;
								double y = j - 0.5 + aliasInterval / 2 + aliasInterval * aliasy;
								Complex c = toComplex(x, y, pixelCenter, scale, center);
								Complex z = new Complex(c.getReal(), c.getImaginary());
								k += 1.0;
								for (int aliask = 1; aliask < currentIterations; ++aliask, k += 1.0) {
									if (id != currentDrawingId)
										return;
									z = z.multiply(z).add(c);
									if (z.abs() > 2)
										break;
								}
							}
						}
						
						k /= antiAliasing * antiAliasing; 
						if (Math.ceil(k) == currentIterations) {
							drawingLock.lock();
							Graphics g = drawing.getGraphics();
							Color color = mixColors(foregroundColor, backgroundColor, k + 1 - currentIterations);

							g.setColor(color);
							g.fillRect(i, j, 1, 1);
							drawingLock.unlock();
						} else {
							drawingLock.lock();
							Graphics g = drawing.getGraphics();
							Color color = mixColors(backgroundColor, foregroundColor, (double) k / currentIterations);
							g.setColor(color);
							g.fillRect(i, j, 1, 1);
							drawingLock.unlock();
						}
						nDrawnLock.lock();
						++nDrawn;
						nDrawnLock.unlock();
					}
				}
				long interval = System.currentTimeMillis() - startTime;
				System.out.println("Shader: [END after " + interval + " ms]");
				saveImage(drawing, drawingLock);
			}
		};
		return shaderThread;
	}