In my attempt to understand texture coordinates in WPF 3D, I started off with a very simple example: a single triangle, a linear-gradient brush, and texture coordinates, as follows:
<Viewport3D>
<ModelVisual3D>
<ModelVisual3D.Content>
<Model3DGroup>
<GeometryModel3D>
<!-- Geometry -->
<GeometryModel3D.Geometry>
<MeshGeometry3D
Positions="10 10 0,
20 10 0,
15 15 0"
TriangleIndices="0 1 2"
TextureCoordinates="0.5 0.0,
0.5 0.0,
0.5 0.0" />
</GeometryModel3D.Geometry>
<!-- Foreground and background brushes -->
<GeometryModel3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<LinearGradientBrush StartPoint="0.5 0" EndPoint="0.5 1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Red" Offset="0.0"/>
<GradientStop Color="Yellow" Offset="0.50"/>
<GradientStop Color="Green" Offset="1.0"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.BackMaterial>
<DiffuseMaterial Brush="Blue" />
</GeometryModel3D.BackMaterial>
</GeometryModel3D>
<!-- Lighting -->
<AmbientLight Color="White" />
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
<!-- Camera -->
<Viewport3D.Camera>
<PerspectiveCamera Position="15 12 10"
LookDirection="0 0 -1"
UpDirection="0 1 0"
FieldOfView="90">
</PerspectiveCamera>
</Viewport3D.Camera>
</Viewport3D>
What I'm expecting is a Red triangle, since all y-coordinates of the textures are 0.0, but what I get is a Green one! Can someone please explain this behavior, so that I can correct my understanding, and move on to larger models? Thanks!
Usually, texture coordinates are defined in the range [0, 1]. However, WPF allows you to use any multiple. But let's stay with the [0, 1] range for the beginning. Then the gradient you defined looks like this:
If we change the texture coordinates to the following:
TextureCoordinates="0.5 0.0,
0.5 0.0,
0.5 1.0"
then we get a nice gradient on the triangle:
The texture coordinates are interpolated in the triangle and the appropriate colors are fetched from the gradient. The bottom left vertex has texture coordinate (0.5, 0), which is red in the gradient. The top vertex has texture coordinate (0.5, 1), which is green in the gradient.
As I said, texture coordinates can be used relatively. They are scaled by their bounding box. So we could also define the following coordinates to get the same result (scaled by 2 and shifted by (0.5, 0.5)):
TextureCoordinates="1.5 0.5,
1.5 0.5,
1.5 2.5"
And this is exactly the point, why you get a green triangle with your texture coordinates. Because all coordinates are the same, the bounding box is 0 units wide and 0 units high. There is just no reasonable way to fit an arbitrary texture coordinate into this degenerate bounding box. I can't tell why WPF chooses the green edge. Probably undefined behavior.
Concluding, always define proper texture coordinates that do not result in a degenerate bounding box.
You may have noticed that the alternative texture coordinates produce a bounding box with zero width. However, this is ok in this case, because the gradient does not change along the u-direction.
See Daniel Lehenbauer's blog for a helpful description of the 2D to 3D mapping procedure in WPF.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With