Linearly interpolate colors in a triangle using SVG (Gouraud shading)

After a long battle with the SVG documentation here is a triangle colored by linearly interpolated colors specified at each vertex.


<svg xmlns="http://www.w3.org/2000/svg" version="1.200000" width="100%" height="100%" viewBox="0 0 100.000000 86.600000" xmlns:xlink="http://www.w3.org/1999/xlink">
  <g transform="matrix(1 0 0 -1 0 86.600000)">
    <defs>

      <linearGradient id="fadeA-1" gradientUnits="userSpaceOnUse" x1="50.000000" y1="0.000000" x2="50.000000" y2="86.600000">
        <stop offset="0%" stop-color="#FF0000"/>
        <stop offset="100%" stop-color="#000000" />
      </linearGradient>
      <linearGradient id="fadeB-1" gradientUnits="userSpaceOnUse" x1="0.000000" y1="86.60000" x2="75.000000" y2="43.300000">
        <stop offset="0%" stop-color="#00FF00"/>
        <stop offset="100%" stop-color="#000000" />
      </linearGradient>
      <linearGradient id="fadeC-1" gradientUnits="userSpaceOnUse" x1="100.000000" y1="86.60000" x2="25.000000" y2="43.300000">
        <stop offset="0%" stop-color="#0000FF"/>
        <stop offset="100%" stop-color="#000000" />
      </linearGradient>

      <path id="pathA-1" d="M 50.000000,0.000000 L 0.000000,86.600000 100.000000,86.600000 Z" fill="url(#fadeA-1)"/>
      <path id="pathB-1" d="M 50.000000,0.000000 L 0.000000,86.600000 100.000000,86.600000 Z" fill="url(#fadeB-1)"/>
      <filter id="Default">
        <feImage xlink:href="#pathA-1" result="layerA" x="0" y="0" />
        <feImage xlink:href="#pathB-1" result="layerB" x="0" y="0" />
        <feComposite in="layerA" in2="layerB" operator="arithmetic" k1="0" k2="1.0" k3="1.0" k4="0" result="temp"/>
        <feComposite in="temp" in2="SourceGraphic"   operator="arithmetic" k1="0" k2="1.0" k3="1.0" k4="0"/>
      </filter>
    </defs>
    <g stroke="none" stroke-width="0" shape-rendering="crispEdges" >
      <path d="M 50.000000,0.000000 L 0.000000,86.600000 100.000000,86.600000 Z" fill="url(#fadeC-1)" filter="url(#Default)" />
    </g>
  </g>
</svg>

SVG render

JPG rasterization

What you should see above if your browser supports SVG resterized linear interpolation of colors in triangle svg

Update: This still isn’t quite linear interpolation. For some reason I get a tendency toward black in the middle. I tried using fancier arithmetic (multiplication) with masks but this made things worse (quantization artifacts). There is also a nasty relative coordinates issue with the filters I used above.

Update: For reference, here’s what I’d like to see:

linear interpolation

Tags: , , , , , ,

5 Responses to “Linearly interpolate colors in a triangle using SVG (Gouraud shading)”

  1. Ebbs says:

    Actually, this is linear interpolation. The color you’ll en up with in the middle is (in hex code) about 0x7F7F7F which is some dark gray color. The reason for this is that the color in the middle of the triangle will be composed of half of the max value of each starting color. This exact interpolation (actually called barycentric interpolation) is used by your hardware rasterizer to interpolate colors inside triangles.
    This image shows a triangle where its vertices are given the same starting colors as you are using and then the hardware rasterizer have automatically interpolated the colors inside the triangle:
    http://www.arcsynthesis.org/gltut/Basics/VertexColors.png

  2. ajx says:

    @Ebbs, The SVG code above is not explicitly doing linear interpolation. I guess you’ve rendered a triangle with vertex colors in OpenGL/DirectX, but this feature is exactly what’s missing in the SVG format. Hence this hack to get something close.

  3. Ben says:

    The triangle looks dark in the center because this is “linear” interpolation in nonlinear sRGB space. The center of the triangle is #555555, which is much darker than linear (1/3, 1/3, 1/3), which would be about #9C9C9C.

    You could make the gradients actually linear by adding a bunch of additional stops using the formula at https://en.wikipedia.org/wiki/sRGB, or maybe approximate it with a gamma of 2.2, if that’s possible in SVG.

  4. Ben says:

    By the way, Eric Brasseur’s rant about this problem (as it applies to image scaling) is a good read: http://www.4p8.com/eric.brasseur/gamma.html

  5. imgur says:

    It means that you get total discounts at the time of subscription. They offer so many
    extras that make starting up a new website so simple that even a complete novice could get a website up and running.

    What search results will offered up with unless you possess a website or perhaps a blog
    to market your business.

Leave a Reply