title: Rendering an image as a node in Three.js with SVGRenderer (or otherwise rendering spheres)
body: <p>I have a <code>&lt;circle&gt;</code> element in an SVG document, to which I apply a <code>&lt;radialGradient&gt;</code> to give the illusion of it being a sphere:</p>
  
  <pre><code>&lt;svg version="1.1" id="sphere_svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="640px" height="640px" viewBox="0 0 640 640" enable-background="new 0 0 640 640" xml:space="preserve"&gt;
      &lt;defs&gt;
          &lt;radialGradient id="sphere_gradient" cx="292.3262" cy="287.4077" r="249.2454" fx="147.7949" fy="274.5532" gradientTransform="matrix(1.0729 0 0 1.0729 -23.3359 -23.3359)" gradientUnits="userSpaceOnUse"&gt;
              &lt;stop id="sphere_gradient_0" offset="0" style="stop-color:#F37D7F"/&gt;
              &lt;stop id="sphere_gradient_1" offset="0.4847" style="stop-color:#ED1F24"/&gt;
              &lt;stop id="sphere_gradient_2" offset="1" style="stop-color:#7E1416"/&gt;
          &lt;/radialGradient&gt;
      &lt;/defs&gt;
      &lt;circle fill="url(#sphere_gradient)" cx="320" cy="320" r="320"/&gt;
  &lt;/svg&gt;
  </code></pre>
  
  <p>It looks something like this:</p>
  
  <p><img src="https://i.stack.imgur.com/Xtpjr.png" alt="red sphere"></p>
  
  <p><a href="http://jsfiddle.net/pLo97a6g/" rel="nofollow noreferrer">JSFiddle</a></p>
  
  <p>I can render this in a three.js <code>WebGLRenderer</code> container by using <a href="https://github.com/gabelerner/canvg" rel="nofollow noreferrer">Gabe Lerner's <code>canvg</code> library</a>:</p>
  
  <pre><code>/* sphere_asset is a div containing the svg element */
  var red_svg_html = new String($('#sphere_asset').html()); 
  var red_svg_canvas = document.createElement("canvas");
  canvg(red_svg_canvas, red_svg_html);
  var red_svg_texture = new THREE.Texture(red_svg_canvas);
  var red_particles = new THREE.Geometry();
  var red_particle_material = new THREE.PointCloudMaterial({ 
      map: red_svg_texture, 
      transparent: true, 
      size: 0.15, 
      alphaTest: 0.10 
  });
  var red_particle_count = 25;
  for (var p = 0; p &lt; red_particle_count; p++) {
      var pX = 0.9 * (Math.random() - 0.5),
          pY = 0.9 * (Math.random() - 0.5),
          pZ = 0.9 * (Math.random() - 0.5),
          red_particle = new THREE.Vector3(pX, pY, pZ);
      red_particles.vertices.push(red_particle);
  }
  var red_particle_system = new THREE.PointCloud(red_particles, red_particle_material);
  scene.add(red_particle_system);
  </code></pre>
  
  <p>So far, so good. I can even programmatically modify the gradient and render different categories of particles:</p>
  
  <p><img src="https://i.stack.imgur.com/6LD3I.png" alt="spheres"></p>
  
  <p>What I would like to do is now switch over from <code>WebGLRenderer</code> to using an <code>SVGRenderer</code>, so that I can allow the end user to set the desired orientation and then export a vector image (SVG, or converted to PDF on the back end) that can be used for publication-quality work.</p>
  
  <p>Using the <a href="http://threejs.org/examples/#svg_sandbox" rel="nofollow noreferrer">SVG sandbox example</a> from three.js as the basis for experimentation, I have tried a couple different techniques and have not had much luck. I'm hoping someone with experience with three.js may have some suggestions.</p>
  
  <p>My first attempt was to use <code>canvg</code> to render the SVG into a PNG image, and then apply that to an <code>&lt;image&gt;</code> node:</p>
  
  <pre><code>var red_svg_html = new String($('#sphere_asset').html());
  var red_svg_canvas = document.createElement("canvas");
  canvg(red_svg_canvas, red_svg_html);
  var red_png_data = red_svg_canvas.toDataURL('image/png');
  var red_node = document.createElementNS('http://www.w3.org/2000/svg', 'image');
  red_node.setAttributeNS('http://www.w3.org/1999/xlink', 'href', red_png_data);
  red_node.setAttributeNS('http://www.w3.org/2000/svg', 'height', '10');
  red_node.setAttributeNS('http://www.w3.org/2000/svg', 'width', '10');
  var red_particle_count = 25;
  for (var i = 0; i &lt; red_particle_count; i++) {
      var object = new THREE.SVGObject(red_node.cloneNode());
      object.position.x = 0.9 * (Math.random() - 0.5);
      object.position.y = 0.9 * (Math.random() - 0.5);
      object.position.z = 0.9 * (Math.random() - 0.5);
      scene.add(object);
  }
  </code></pre>
  
  <p>No nodes show up in my viewbox.</p>
  
  <p>The next thing I tried was a <code>THREE.Sprite</code> object, using <code>canvg</code> and <code>THREE.Texture</code> routines:</p>
  
  <pre><code>var red_svg_html = new String($('#sphere_asset').html());
  var red_svg_canvas = document.createElement("canvas");
  canvg(red_svg_canvas, red_svg_html);
  var red_svg_texture = new THREE.Texture(red_svg_canvas);
  red_svg_texture.needsUpdate = true;
  var red_sprite = THREE.ImageUtils.loadTexture(red_png_data);
  var red_particle_count = 25;
  for (var p = 0; p &lt; red_particle_count; p++) {
      var material = new THREE.SpriteMaterial( { 
          map: red_svg_texture, 
          transparent: true, 
          size: 0.15, 
          alphaTest: 0.10 
      });
      var sprite = new THREE.Sprite( material );
      sprite.position.x = 0.9 * (Math.random() - 0.5),
      sprite.position.y = 0.9 * (Math.random() - 0.5),
      sprite.position.z = 0.9 * (Math.random() - 0.5),
      sprite.scale.set(0.1, 0.1, 0.1);
      scene.add(sprite);
  }
  </code></pre>
  
  <p>This was slightly better, in that I get white, opaque boxes where the spheres would otherwise appear in the rendered viewbox.</p>
  
  <p>A third attempt was made to create an <code>&lt;svg&gt;</code> to nest within the parent SVG node, which contains a reference-able <code>&lt;radialGradient&gt;</code> with the id <code>#sphere_gradient</code>:</p>
  
  <pre><code>var xmlns = "http://www.w3.org/2000/svg";
  var svg = document.createElementNS(xmlns, 'svg');
  svg.setAttributeNS(null, 'version', '1.1');
  svg.setAttributeNS(null, 'x', '0px');
  svg.setAttributeNS(null, 'y', '0px');
  svg.setAttributeNS(null, 'width', '640px');
  svg.setAttributeNS(null, 'height', '640px');
  svg.setAttributeNS(null, 'viewBox', '0 0 640 640');
  svg.setAttributeNS(null, 'enable-background', 'new 0 0 640 640');
  
  var defs = document.createElementNS(xmlns, "defs");
  var radialGradient = document.createElementNS(xmlns, "radialGradient");
  radialGradient.setAttributeNS(null, "id", "sphere_gradient");
  radialGradient.setAttributeNS(null, "cx", "292.3262");
  radialGradient.setAttributeNS(null, "cy", "287.4077");
  radialGradient.setAttributeNS(null, "r", "249.2454");
  radialGradient.setAttributeNS(null, "fx", "147.7949");
  radialGradient.setAttributeNS(null, "fy", "274.5532");
  radialGradient.setAttributeNS(null, "gradientTransform", "matrix(1.0729 0 0 1.0729 -23.3359 -23.3359)");
  radialGradient.setAttributeNS(null, "gradientUnits", "userSpaceOnUse");
  
  var stop0 = document.createElementNS(null, "stop");
  stop0.setAttributeNS(null, "offset", "0");
  stop0.setAttributeNS(null, "stop-color", "#f37d7f");
  radialGradient.appendChild(stop0);
  
  var stop1 = document.createElementNS(null, "stop");
  stop1.setAttributeNS(null, "offset", "0.4847");
  stop1.setAttributeNS(null, "stop-color", "#ed1f24");
  radialGradient.appendChild(stop1);
  
  var stop2 = document.createElementNS(null, "stop");
  stop2.setAttributeNS(null, "offset", "1");
  stop2.setAttributeNS(null, "stop-color", "#7e1416");
  radialGradient.appendChild(stop2);
  
  defs.appendChild(radialGradient);
  
  svg.appendChild(defs);
  
  var red_circle = document.createElementNS(xmlns, "circle")
  red_circle.setAttribute('fill', 'url(#sphere_gradient)');
  red_circle.setAttribute('r', '320');
  red_circle.setAttribute('cx', '320');
  red_circle.setAttribute('cy', '320');
  svg.appendChild(red_circle);
  
  var red_particle_count = 25;
  for (var i = 0; i &lt; red_particle_count; i++) {
      var object = new THREE.SVGObject(svg.cloneNode(true));
      object.position.x = 0.85 * (Math.random() - 0.5);
      object.position.y = 0.85 * (Math.random() - 0.5);
      object.position.z = 0.85 * (Math.random() - 0.5);
      scene.add(object);
  }
  </code></pre>
  
  <p>No nodes are rendered. Adjustments of the <code>&lt;circle&gt;</code> element's <code>r</code>, <code>cx</code> or <code>cy</code> do not change the end result. </p>
  
  <p>Interestingly, if I change the <code>fill</code> attribute from <code>url(#sphere_gradient)</code> to <code>red</code>, I get a large circle mostly rendered outside my viewbox, which is not attached to the scene (it does not rotate with other elements in my parent scene, like the sides of a cube).</p>
  
  <p>Is there a (working and performant) way to draw spheres or rounded, sphere-like particles in space using a <code>SVGRenderer</code> in three.js?</p>