How to blend SolidColorBrush with ImageBrush?

When defining GeometryModel3D.Material I'd like to blend SolidColorBrush with ImageBrush. If I define materials in this order:

<MaterialGroup>
  <DiffuseMaterial>
    <DiffuseMaterial.Brush>
      <ImageBrush ImageSource="image.bmp" />
    </DiffuseMaterial.Brush>
  </DiffuseMaterial>
  <DiffuseMaterial>
    <DiffuseMaterial.Brush>
      <SolidColorBrush Color="Red" />
    </DiffuseMaterial.Brush>
  </DiffuseMaterial>
</MaterialGroup>

I get pure SolidColorBrush. If I define materials in reverse order:

<MaterialGroup>
  <DiffuseMaterial>
    <DiffuseMaterial.Brush>
      <SolidColorBrush Color="Red" />
    </DiffuseMaterial.Brush>
  </DiffuseMaterial>
  <DiffuseMaterial>
    <DiffuseMaterial.Brush>
      <ImageBrush ImageSource="image.bmp" />
    </DiffuseMaterial.Brush>
  </DiffuseMaterial>
</MaterialGroup>

I get pure ImageBrush.

Is there a way to blend two (or more) diffuse materials

 



Answer this question

How to blend SolidColorBrush with ImageBrush?

  • iam_venny

    As you have discovered, Materials in a MaterialGroup are rendered in order and, unlike EmissiveMaterial and SpecularMaterial, DiffuseMaterial "overwrites" what has already been drawn. This is why you only see the last thing in the MaterialGroup in your first example.

    In eburke's example, making image.bmp non-transparent should work. However, this is not as efficient as it could be because you aren't actually looking for diffuse red lighting -- you're just trying to tint image.bmp.

    Instead, try using a red EmissiveMaterial and adjust the red channel or the opacity to your liking. An EmissiveMaterial is a simple additive blend that doesn't involve lighting calculations.

    The downside to a MaterialGroup is that we will render the mesh once per Material. To avoid the MaterialGroup, you could try using a red AmbientLight, e.g.:

         <AmbientLight Color="red" />
         <!-- a "half strength" white light -->
         <DirectionalLight Color="#ff7F7F7F" Direction="whatever"/>
         ...
             <GeometryModel3D.Material>

                 <DiffuseMaterial>
                     <DiffuseMaterial.Brush>
                         <ImageBrush ImageSource="image.bmp" />
                     </DiffuseMaterial.Brush>
                 </DiffuseMaterial>  
             </GeometryModel3D.Material>

         ...

    Now if you have other objects in your scene this could tint them red as well so this might not be an option.

    If you were going to try to do the red tinting in 2D before you put it on the 3D model, I think you could do it with a DrawingBrush with a DrawingGroup containing an ImageDrawing and a red rectangle GeometryDrawing. My hunch is the all 3D solution will be faster (unless your graphics card is bad).

    Jordan


  • Anders Jensen

    try setting the Opacity property of the Brushes to some value < 1.0.

    e.g.,

    <MaterialGroup>
    <DiffuseMaterial>
    <DiffuseMaterial.Brush>
    <ImageBrush ImageSource="image.bmp" Opacity="0.5"/>
    </DiffuseMaterial.Brush>
    </DiffuseMaterial>
    <DiffuseMaterial>
    <DiffuseMaterial.Brush>
    <SolidColorBrush Color="Red" Opacity="0.5"/>
    </DiffuseMaterial.Brush>
    </DiffuseMaterial>
    </MaterialGroup>


  • Henrik Jensen

    I tried that but the model itself got transparent. I need blending when the model remains opaque and material's final color is calculated as solid_color * texture_color or somehow like this.
  • How to blend SolidColorBrush with ImageBrush?