runcl

A minimal OpenCL harness for rendering images
git clone git://pollux.codes/git/runcl.git
Log | Files | Refs | README | LICENSE

commit a2beea11221ab50b2faa7dd6651e6458620e4c48
parent deb6c72f2428afd5ca5c69559982073659fabbee
Author: Pollux <pollux@pollux.codes>
Date:   Sun, 19 Jan 2025 13:59:30 -0600

docs: Improve examples

Signed-off-by: Pollux <pollux@pollux.codes>

Diffstat:
MREADME.md | 7+++++--
Dexample.cl | 22----------------------
Aexamples/calligraphy.cl | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aexamples/gradient.cl | 25+++++++++++++++++++++++++
4 files changed, 188 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md @@ -32,6 +32,8 @@ runcl \ output-png-file ``` +The default image size is `640x480`. + Use `clinfo` to see platform information. By default the platform with index 0 is chosen. @@ -41,5 +43,6 @@ In order for `runcl` to work, the OpenCL file used must have a kernel named `render` with three arguments, `const int width`, `const int height`, and `__global float *out`. -See the `example.cl` file for a demonstration of these requirements, as well as -the suggested way of using the arguments. +See `examples/gradient.cl` for a demonstration of these requirements, as well +as the suggested way of using the arguments. The other files in the `examples` +folder contain more sophisticated files for generating more complex images. diff --git a/example.cl b/example.cl @@ -1,22 +0,0 @@ -// This is the main function of the program. -// Runcl passes the following arguments to the program. -// - width: the width of the image in pixels -// - height: the height of the image in pixels -// - *out: the output of the program, formatted as an 3xwxh array of normalized rgm pixel colors -kernel void render(const int width, const int height, __global float *out) -{ - // this gets the id of the particular instance - const int i = get_global_id(0); - - if ( i < width * height ) - { - // this converts the id into normalized image coordinates - float x = (float)(i % width) / width; - float y = (float)(i / width) / height; - - // output the rgb color to the out array - out[3*i] = x; - out[3*i+1] = x; - out[3*i+2] = x; - } -} diff --git a/examples/calligraphy.cl b/examples/calligraphy.cl @@ -0,0 +1,158 @@ +#define CROSSHAIRS false + +#define AA 1.f +#define MAX_DWELL 10000 +#define BAILOUT 1000000000000.f + +#define LOG2 0.6931471806 + +#define SCALE 0.00151f +#define XCENTER -0.77235f +#define YCENTER -0.10664f + +kernel void render(const int width, const int height, __global float *out) +{ + const int i = get_global_id(0); + + if(CROSSHAIRS && (i%width == 1146 || i%width == 2294 || i/width == 480 || i/width == 960)) + { + out[3*i] = 1.f; + out[3*i+1] = 0.f; + out[3*i+2] = 0.f; + return; + } + + if(i < width * height) + { + + float4 pix_col = (float4)(0.f); + + for(float dx = 0.f; dx < 1.f; dx += AA) + { + for(float dy = 0.f; dy < 1.f; dy += AA) + { + + float x = (float)(i % width - width/2 + dx) / height; + float y = (float)(i / width - height/2 + dy) / height; + + float cx = x * SCALE + XCENTER; + float cy = y * SCALE + YCENTER; + + float zx = 0.f; + float zy = 0.f; + + float dzx = 0.0f; + float dzy = 0.0f; + float tmp; + + int n; + float x2, y2; + + + // Color + float arg; + float4 st_avg = (float4)(0.f); + float4 st_avg2 = (float4)(0.f); + + float highlight = 0.f; + + // Main Loop + for(n = 0; n < MAX_DWELL; n++) + { + arg = atan2(zy, zx); + + st_avg = st_avg.xxyz; + st_avg.x += sin( 11.f * arg); + + st_avg2 = st_avg2.xxyz; + st_avg2.x += sin( 11.f * arg); + + highlight += exp(-(zx-.5f)*(zx-.5f)*100000.f); + + x2 = zx*zx; + y2 = zy*zy; + + if(x2 + y2 > BAILOUT) + { + break; + } + + tmp = 2.0f * (zx*dzx - zy*dzy) + 1.0f; + dzy = 2.0f * (zx*dzy + zy*dzx); + dzx = tmp; + + zy = (zx+zx)*zy + cy; + zx = x2 - y2 + cx; + } + + if(n < MAX_DWELL) + { + float z_mag = sqrt(zx*zx+zy*zy); + float dist = z_mag * log(z_mag) / sqrt(dzx*dzx + dzy*dzy); + float c1 = pow(min(1.f, 5000000.f*dist), 3.f); + + + + float4 fac = (float4)(1.f) / (float4)(n, n-1, n-2, n-3); + st_avg = st_avg * fac + (float4)(1.f); + st_avg2 = st_avg2 * fac + (float4)(1.f); + + float nu, nu2, nu3, nc; + + nu = 1.f - log2(log(zx*zx + zy*zy)/log(10000000000.f)); + nu2 = nu*nu; + nu3 = nu2*nu; + nc = n + nu; + + float4 interp = (float4)( + -nu2 + nu3, + nu + 4.f*nu2 - 3.f*nu3, + 2.f - 5.f*nu2 + 3.f*nu3, + -nu + 2.f*nu2 - nu3 + ); + + float c2 = max(0.f, min(1.f, dot(interp, st_avg)-1.0f)); + + + float gx = (zx*dzx + zy*dzy)/(dzx*dzx + dzy*dzy); + float gy = (zy*dzx - zx*dzy)/(dzx*dzx + dzy*dzy); + float l = sqrt(gx*gx + gy*gy); + gx /= l; + gy /= l; + float c3 = 1.0f/sqrt(2.0f) * (gx + gy); + + c3 = max(0.f, c3 + 1.f) * 0.3f + 0.4f; + + + float c5 = max(0.f, min(1.f, (dot(interp, st_avg2) - 2.f)/(n+nu)*100.f)); + c5 = pow(c5, 2.5f); + + //c1=1.f; + //c2=1.f; + //c3=1.f; + + + float4 base = (float4)(239, 241, 245, 0)/255.f; + float4 base2 = (float4)(172, 176, 190, 0)/255.f; + float4 red = (float4)(114, 135, 253, 0)/255.f; + float4 text = (float4)(76, 79, 105, 0)/255.f; + + + float4 color = mix(base2, base, c2*c3); + color = mix(text, color, c1); + + pix_col += color; + } + else + { + float4 color = (float4)(76, 79, 105, 0)/255.f; + pix_col += color; + } + } + } + + out[3*i] = pix_col.x*AA*AA; + out[3*i+1] = pix_col.y*AA*AA; + out[3*i+2] = pix_col.z*AA*AA; + } +} diff --git a/examples/gradient.cl b/examples/gradient.cl @@ -0,0 +1,25 @@ +// This is the main function of the program. +// Runcl passes the following arguments to the program. +// - width: the width of the image in pixels +// - height: the height of the image in pixels +// - *out: the output of the program, formatted as an 3xwxh array of +// normalized rgb pixel colors +kernel void render(const int width, const int height, __global float *out) +{ + // This gets the id of the particular instance. + const int i = get_global_id(0); + + // Depending on the image size, some instances may be outside of the image + // bounds. Make sure to check for this! + if ( i < width * height ) + { + // This converts the instance ID into normalized image coordinates. + float x = (float)(i % width) / width; + float y = (float)(i / width) / height; + + // Finally, output the rgb color to the output array. + out[3*i] = x; + out[3*i+1] = x; + out[3*i+2] = x; + } +}