Perform the following steps:
- In the compute shader, we start by defining the number of shader invocations per work group:
layout( local_size_x = 32, local_size_y = 32 ) in;
- Next, we declare the output image as well as some other uniform variables:
layout( binding = 0, rgba8) uniform image2D ColorImg; #define MAX_ITERATIONS 100 uniform vec4 CompWindow; uniform uint Width = 256; uniform uint Height = 256;
- We define a function to compute the number of iterations for a given position on the complex plane:
uint mandelbrot( vec2 c ) { vec2 z = vec2(0.0,0.0); uint i = 0; while(i < MAX_ITERATIONS && (z.x*z.x + z.y*z.y) < 4.0) { z = vec2( z.x*z.x-z.y*z.y+c.x, 2 * z.x*z.y + c.y ); i++; } return i; }
- In the main function, we start by computing the size of a pixel in the complex space:
void main() { float dx = (CompWindow.z - CompWindow.x) / Width; float dy = (CompWindow.w - CompWindow.y) / Height;
- Then, we determine the value of c for this invocation:
vec2 c = vec2( dx * gl_GlobalInvocationID.x + CompWindow.x, dy * gl_GlobalInvocationID.y + CompWindow.y);
- Next, we call the mandelbrot function and determine the color based on the number of iterations:
uint i = mandelbrot(c); vec4 color = vec4(0.0,0.5,0.5,1); if( i < MAX_ITERATIONS ) { if( i < 5 ) color = vec4(float(i)/5.0,0,0,1); else if( i < 10 ) color = vec4((float(i)-5.0)/5.0,1,0,1); else if( i < 15 ) color = vec4(1,0,(float(i)-10.0)/5.0,1); else color = vec4(0,0,1,0); } else color = vec4(0,0,0,1);
- We then write the color to the output image:
imageStore(ColorImg, ivec2(gl_GlobalInvocationID.xy), color); }
- Within the render function of the OpenGL program, we execute the compute shader with one invocation per texel, and call glMemoryBarrier:
glDispatchCompute(256/32, 256/32, 1); glMemoryBarrier( GL_SHADER_IMAGE_ACCESS_BARRIER_BIT );
- Then, we render the scene, applying the texture to the appropriate objects.