12.5 应用实例

对于图像处理应用,通常会将轨迹跟踪输出到屏幕上。对于这样的应用,其表面都会使用多个三角形进行构成,然后通过WebGL进行渲染。计算内核代码提供了更加自由的方式,方便我们对通用计算进行优化。片元渲染器相较计算渲染器要难优化许多。更重要的是,纹理内存是缓存在处理器中,这样要比通过全局内存的方式访问CPU内存高效的多。不过,有些设备不支持图像内存,可以使用WebCLBuffer创建像素数组对象,从而更新WebGL的纹理。

本节中,我们使用Iñigo Quilez片元渲染器所渲染的影子玩具——曼德尔球[1],将这个例子转化成一个WebCL内核,如图12.4所示。WebGL使用两个纹理三角形对画面进行填充。WebCL每帧都会生成新的纹理。因此,考虑到画布的大小(width,height),WebCL将会生成width x height个像素点。

应用实例 - 图1

图12.4 WebGL中两个三角形可以画一幅WebCL生成的图像。

当WebCL要使用WebGL内存进行计算时,WebGL上下文必须要进行初始化,并且在WebGL上下文上共享产生WebCL的上下文,然后就可以WebCL就能使用WebGL的相关内存对象进行计算。下面的代码中展示了,如何创建WebGL的纹理,并且将其用于WebCL进行计算:

  1. // retrieva a <canvas> object with id glcanvas in HTML page
  2. var canvas = documnet.getElementById("glcanvas");
  3. // Try to grab the standard context. If it fails, fallback to experimental.
  4. var gl = canvas.getContext("webcl") || canvas.getContext("experimental-webgl");
  5. // Create OpenGL texture object
  6. Texture = gl.createTexture();
  7. gl.bindTexture(gl.TEXTURE_2D, Texture);
  8. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  9. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  10. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, TextureWidth, TextureHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  11. gl.bindTexture(gl.TEXTURE_2D, null);
  12. // Create OpenCL representation (a WebCLImage) of OpenGL texture
  13. try{
  14. clTexture = context.createFormGLTexture2D(cl.MEM_WRITE_ONLY, gl.TEXTURE_2D, 0, Texture);
  15. } catch(ex) {
  16. throw "Error: Failed to create WebCLImage." + ex;
  17. }
  18. // To use this texture, somewhere in your code, do as usual:
  19. glBindTexture(gl.TEXTURE_2D, Texture);

将这个纹理作为参数传入内核。

  1. kernel.setArg(0, clTexture);
  2. kernel.setArg(1, new Uint32Array([TextureWidth]));
  3. kernel.setArg(2, new Uint32Array([TextureHeight]));

最后,在内核代码中对WebCLImage对象进行调用。

  1. __kernel
  2. void compute(__write_only image2d_t pix, uint width, uint height){
  3. const int x = get_global_id(0);
  4. const int y = get_global_id(1);
  5. // compute pixel color as a float4
  6. write_imagef(pix, (in2)(x, y), color);
  7. }

[1] Iñigo Quilez。 ShaderToy with Mandelbulb shader, http://www.iquilezles.org/apps/shadertoy/?p$=$mandelbulb