RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Drawing with Direct3D, Part 2: Lighting and Textures : Page 4

Learn how to use Direct3D's lighting model and textures to create more realistic three-dimensional scenes.

Adding Textures
In addition to drawing three-dimensional objects with specific colors, materials, and lights, a third alternative is to specify the colors of an object's pixels by mapping an image onto the object's triangles. In Direct3D this is called texture-mapping.

Direct3D represents an object's color properties with the Material class. Similarly, it represents an object's texture map with the Texture class. You can think of a Texture object as basically being a fancy wrapper for a bitmapped image. The TextureLoader class provides shared methods for loading texture data from various sources, such as files and streams.

The following code declares a Texture object and then loads it from the file named l_wood04.jpg. The m_Device parameter informs the FromFile method of the Direct3D device that will later use the texture:

   Private m_WoodTexture As Texture = _
       TextureLoader.FromFile(m_Device, "l_wood04.jpg")
The sample program d3dTexturedCube uses the following code to load a texture from a program resource named l_wood04. This is the same image file used in the previous example, but it's saved in a resource rather than loaded from an external file at run time:

   Private m_WoodTexture As Texture
   Dim bmp_stream As IO.MemoryStream
   bmp_stream = New IO.MemoryStream()
   My.Resources.l_wood04.Save( _
      bmp_stream, ImageFormat.Jpeg)
   bmp_stream.Seek(0, IO.SeekOrigin.Begin)
   m_WoodTexture = TextureLoader.FromStream( _
      m_Device, bmp_stream)
The code creates a memory stream and makes the image resource save itself into the stream. It then uses the TextureLoader's FromStream method to load the texture.

Next, you need to tell Direct3D which part of the texture image should go on which part of each of the triangles that you render. You can do this with a new vertex type: PositionTextured. As its name implies, the PositionTextured type allows you to specify a vertex's position and its location in a texture. The type's texture properties, which are called Tu and Tv, give the vertex's position in the texture image. In the image coordinate system, the point (0, 0) is in the lower left corner, the U axis increases to the right, and the V axis increases upward.

Program d3dTexturedCube uses the MakeRectanglePT subroutine to simplify creating textured rectangles. Its parameters are the rectangle's corners and the Tu and Tv values each corner should have.

The following code shows how MakeRectanglePT creates the rectangle's first triangle. It simply creates each vertex, passing its position and texture coordinates into the PositionTextured class's constructor:

   vertices(i) = _
      New CustomVertex.PositionTextured( _
      x0, y0, z0, u0, v0)
   i += 1
   vertices(i) = _
      New CustomVertex.PositionTextured( _
      x1, y1, z1, u1, v1)
   i += 1
   vertices(i) = _
      New CustomVertex.PositionTextured( _
      x2, y2, z2, u2, v2)
   i += 1
The following code shows the call to MakeRectanglePT that d3dTexturedCube makes to build the cube's top. The result is a horizontal rectangle where -1 <= x <= 1, -1 <= z <= 1, and y = 1:

   MakeRectanglePT(vertices, i, _
      1, 1, -1, 0, 1, _
      -1, 1, -1, 0, 0, _
      -1, 1, 1, 0.75, 0, _
      1, 1, 1, 0.75, 1)
Figure 7. Bricks and Boards: The d3dTexturedCube program draws a cube with five wooden sides and one brick side.
After you load the texture and set up the data, you simply tell the Direct3D device to use it. The following code shows how the d3dTexturedCube program tells Direct3D to use textures when rendering. The code first selects a wood texture and draws every triangle except the last two. It then selects a brick texture and draws the final two triangles. Figure 7 shows the result:

   m_Device.SetTexture(0, m_WoodTexture)
   m_Device.DrawPrimitives( _
       PrimitiveType.TriangleList, _
       0, NUM_TRIANGLES - 2)
   ' Draw two triangles in brick.
   m_Device.SetTexture(0, m_BrickTexture)
   m_Device.DrawPrimitives( _
       PrimitiveType.TriangleList, ( _
       NUM_TRIANGLES - 2) * 3, 2)
If you study Figure 7 for a few seconds, you'll notice that it isn't using a lighting model. Each of the cube's sides has the same brightness. If the sides were colored rather than covered by images, you wouldn't be able to see the edges between the sides.

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date