OpenCL Heightfield Coloriser

PeMo's picture

For any OpenCL geniuses out there:

I'm attempting to colourise a vertex mesh generated in OpenCL from an input image (in fact a movie) that contains only greyscale pixels. The greyscale values drive the height (Y) of a given vertex from the XZ plane of the mesh (or whatever appropriate axes are, depending on your perspective.)

This seems to bel working fine, but I am completely stumped - as an OpenCL ignoramus - as to how I might go about creating an artificial colour ramp parametrically driven by the height of a vertex from the XZ plane (where the rest of the vertices are). A simple rainbow ramp would do.

Normally I'd attempt this using standard QC patches, but as this is running in OpenCL it seems sensible to keep it all within the kernel & hopefully running fast :)

Here's the code:


__kernel void imageRead(__rd image2d_t srcimg, const float2 size, __global float4 *vertices, __global float4 *colors, __global float4 *colorHeight) { int2 pos = make_int2(get_global_id(0), get_global_id(1)), resolution = make_int2(get_global_size(0), get_global_size(1)); int index = mad24(pos.y, resolution.x, pos.x); // faster than: pos.y * resolution.x + pos.x; float4 color; float x, y, z, r, g, b, a; sampler_t smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST;

color = read_imagef(srcimg, smp, pos);

//define output colors - greyscale based on greyscale source colors[index] = color;

x = (float)pos.x/resolution.xsize.x-size.x/2; y = size.y-(float)pos.y/resolution.ysize.y-size.y/2; z = length(color.xyzw)*0.5 -.0; vertices[index] = make_float4(x, y, z, 1.);

//define output colors - height field //something I've just stuck in to see if it kinda works // putput = r,g,b,a r = z; g = z; b = z; a = 1; colorHeight[index] = make_float4(r, g , b, a);

}


I pinched this from this example http://kineme.net/composition/dust/parallelpainting.

I've attached example QC comp to demonstrate what I'm ~trying~ to do (so far with no luck - but learning lots about OpenCL in the process).

Anyway, if someone with more experience than I can have a look & make a suggestion then that would be great :) Thanks in advance.

PreviewAttachmentSize
OpenCL_colorize_heightfield.qtz150.38 KB

Achim Breidenbach's picture
Re: OpenCL Heightfield Coloriser

If you really want to have a rainbow, You could use a HSL to RGB colorspace transform: you put in Hue=0...1 (your height normalized) Sat=0.5, Lum=0.5 and convert it to RGB. Here is some code:

vec4 HSLToRGB(vec4 colorHSL) {

float h = colorHSL.x; float s = colorHSL.y; float l = colorHSL.z;

float c = (1.0 -abs(2.0 * l - 1.0) ) * s; float hh = h * 6.0; // same as "divide by 60 degrees" float x = c * ( 1.0 -abs( mod(hh , 2.0) - 1.0) );

vec4 rgb = vec4(0.0);

if(hh < 1.0){ rgb = vec4 (c, x, 0.0, 1.0); } else if(hh < 2.0){ rgb = vec4 (x, c, 0.0, 1.0); } else if(hh < 3.0){ rgb = vec4 (0.0, c, x, 1.0); } else if(hh < 4.0){ rgb = vec4 (0.0, x, c, 1.0); } else if(hh < 5.0){ rgb = vec4 (x, 0.0, c, 1.0); } else{ rgb = vec4 (c, 0.0, x, 1.0); } float m = l - c * 0.5;

rgb += m;

return vec4(rgb.r, rgb.g, rgb.b, colorHSL.a); }

PeMo's picture
Re: OpenCL Heightfield Coloriser

Thanks Achim :) I assume this is a Core Image Filter in OpenGL?

I'm trying to run the HSL->RGB conversion within the OpenCL kernel (which seems to use a different syntax - e.g. doesn't recognise the vec4 type), so I've not had much luck so far. But it's puzzling & I suspect I'm simply not understanding something - looking at this: http://stackoverflow.com/questions/1211705/paint-me-a-rainbow/34663498#3... seems to indicate that conditional branching is not so great for GPUs, but also that OpenGL and OpenCL should be able to talk to each other. Regrettably I am a novice in both (that's why I use QC and Python!).

I'll keep on hunting around - but if I have misunderstood your code & this can actually be implemented in the OpenCL kernel and you have a moment to clarify, that would be great.