==================
Applying Materials
==================

This tutorial will demonstrate how to apply materials to a shell. A shell is one of the fundamental and most versatile geometric objects of |HPSNOW|. Creating a portfolio and applying materials will also be discussed. The code in this tutorial is demonstrated using the framework of the WPF and MFC sandboxes. Those applications are found in the projects *wpf_sandbox* and *mfc_sandbox* in the |HPSNOW| solution and you are encouraged to follow along. The sandbox applications contain a basic |HPSNOW| window as well as four "User Code" buttons which you can use to invoke the example code and interact with the scene.

The cube sample model used in this tutorial can be found in the *samples/data* directory in your |HPSNOW| installation.


2.1 Loading a Shell
===================

|HPSNOW| offers a few primitives for 3D geometric representation, however, the vast majority of geometry will be represented by shells. It is recommended that you read :doc:`this section </prog_guide/0201_shells>` of the Programming Guide to gain a deep understanding of shells.

This section of the tutorial will use the sandbox to demonstrate how to load a shell cube from a file. Later, we'll apply materials to each face. In the sandbox, the :doc:`view hierarchy </prog_guide/0301_core>` is already preconfigured and ready to use, so we can begin without any initialization other than creating the model segment.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [loading_shell]
		   :end-before: //! [loading_shell]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [loading_shell]
		   :end-before: //! [loading_shell]
		   
.. admonition:: note

	To load the model in the screenshot, replace ``path_to_file`` with *<Visualize_Install_Directory>/samples/data/cube.hsf*.

If everything went well, at this point the geometry from the file should be loaded into the model segment. Again, the code above should be placed into one of the ``Execute`` methods, such as the one in ``DemoUser1Command``. If you were to start the application now, and run the code above by clicking "User Code X", you would get an image like the following:

.. image:: images/02/t.2.1.b.png

*The shell cube*

The cube doesn't look great as it's unlit and at a flat camera angle. Let's make the cube look better by adjusting some of the attributes in its segment. We'll set a transparent color for the faces and enable the visibility of edges:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [set_color]
		   :end-before: //! [set_color]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [set_color]
		   :end-before: //! [set_color]

.. image:: images/02/t.2.1.c.png

*The cube after color and transparency is applied. Note that you can rotate the cube using the orbit operator (first tab in the ribbon control).*

Because the materials are set using the segment's ``HPS::MaterialMappingControl``, the setting will apply to all geometry in that segment - and is also inherited by subsegments. Note that *applying materials at the segment level is recommended* over setting them at the geometry level because |HPSNOW| is able to use performance optimizations when attributes are grouped on segments. However, sometimes it is impossible to arrange the scene in this way because you might, for example, desire to set different materials on faces of the same shell. The following sections will build new materials in a material palette and demonstrate how to apply them to each of the cube's faces.

.. _0202:

2.2 Applying a Diffuse Texture
==============================

This section deals with setting a texture on geometry, however, as texture is a material, the procedure in this exercise can be applied to all types of materials. A diffuse texture can be thought of as a standard, unadorned image applied to the face of a geometric object. It is the simplest type of texturing as the face color is simply replaced by the image's pixels. Details about loading and defining a texture are discussed in depth in the :doc:`texture section </prog_guide/0503_textures>` of the Programming Guide. More information on applying materials can be found in :doc:`this section </prog_guide/0504_applying_materials>`. The remainder of this tutorial will assume you know how to import images and define materials.

Segment-Level
-------------

Like other materials, textures can be applied at the segment, entity, or face level. A segment-level texture means the texture will be applied to every face in the segment - even across disparate geometric bodies (this is the least performance-intensive way to apply materials). An entity-level material will be applied to a single entity, such as a particular shell or mesh. Setting a texture at the face level allows you to control how individual faces are textured - at the expense of rendering speed. For example, the quads below all belong to the same shell. To set a texture to cover all three of them, you could set a segment-level texture by calling:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [set_face_texture]
		   :end-before: //! [set_face_texture]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [set_face_texture]
		   :end-before: //! [set_face_texture]

.. image:: images/02/wood-cube.png

*A shell textured at the segment level*


Entity-Level
------------

Materials can be set for individual geometry if the geometry is a shell or mesh. Setting a material on a particular shell or mesh requires using a ``HPS::MaterialMappingKit``. You can set any material property on a ``HPS::MaterialMappingKit``, but for this example, we'll keep it simple and just set color. To do this, build a kit and apply it to the particular shell key that you want to be different:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [mmk]
		   :end-before: //! [mmk]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [mmk]
		   :end-before: //! [mmk]

.. image:: images/02/entity-level-material.png

*All geometry is in a single segment, and the material is set on just one piece*

Setting material at the geometry level does incur a performance penalty relative to setting materials at the segment level.


Face-Level
----------

Face-level texturing is the most performance-intensive way to apply a material. It should be reserved for those times when fine-tuned control of the appearance is absolutely necessary. It also may be appropriate if there are many shells in a segment, but some of the shells have their own specific material. In any case, when applying materials to faces, the primary difference is that the texture itself must be part of a :ref:`material palette <prog_guide/0501_materials_introduction:Defining material palettes>`. For this tutorial, we'll reload the cube model from section 2.1. Six material kits are defined, one for each face of the cube. In each subsection in this tutorial, we'll build another material to apply to the cube:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [face_level_texturing]
		   :end-before: //! [face_level_texturing]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [face_level_texturing]
		   :end-before: //! [face_level_texturing]

The code in the snippet above builds a palette and sets it as the active palette for the segment. The next step sets the mapping between the palette materials and the faces of the shell:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [set_face_colors]
		   :end-before: //! [set_face_colors]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [set_face_colors]
		   :end-before: //! [set_face_colors]

In this snippet, we are setting the face indices array for all faces, even though we're only texturing one face at this time (the ``HPS::MaterialPaletteDefinition`` has only one real material, as the others are only initialized with defaults). Also note that for this model, the vertex parameters for each face have been stored in the model file. Normally, you will have to set up the vertex parameters as described in :doc:`this section </prog_guide/0503_textures>`.

.. image:: images/02/t.2.2.b.png

*The cube shell with a texture applied to a single face using a material palette.*

Lastly, the code in this section assumes you have a reference to the ``HPS::ShellKey`` for this shell. When loading from a file, you will not have the keys for the geometry inside. In order to find them, you must search the model segment for the keys. In this case, the procedure is easy as there is only one shell in ``cube.hsf``:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [search]
		   :end-before: //! [search]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [search]
		   :end-before: //! [search]


Applying Diffuse Color Using a Palette
--------------------------------------

Now that you have an idea of how material palettes work in |HPSNOW|, we can revisit simple color. All that is needed is to create a ``HPS::MaterialKit`` and set its diffuse color:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [set_diffuse_color]
		   :end-before: //! [set_diffuse_color]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [set_diffuse_color]
		   :end-before: //! [set_diffuse_color]

.. image:: images/02/t.2.2.c.png

*Diffuse color and transparency set on one face of the cube.*


2.3 Bump Mapping
================

A :ref:`bump map <prog_guide/0503_textures:Bump mapping>` is a texture that uses a height map in order to create the illusion of a surface with ridges or bumps. Using a bump map is very similar to normal texture mapping. The main difference is the requirement of the height map to provide the height information to the renderer. Since the bump calculation depends on lighting, you must have at least one light in your scene. Bump mapping is most noticeable when the light is able to reflect off of the surface of the geometry (as opposed to being located behind the geometry).

Bump textures have a diffuse component and a height component. Frequently these components are in two separate files - the procedure for loading them as textures in |HPSNOW| is identical. Simply load both components as a normal texture. The code below demonstrates how to make two textures into a bump map. In this case we'll reuse the ``materialKitArray`` from the previous section. Note that lighting must be enabled in order to see the bump effect.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [set_bump]
		   :end-before: //! [set_bump]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [set_bump]
		   :end-before: //! [set_bump]
		   
.. image:: images/02/t.2.3.a.png

*The diffuse texture and heightmap combined to form a finished bump mapped texture.*


Note that in order to get the bump texture into the material palette, you must redefine the palette with the new material inside. Normally, you wouldn't do it this way, as you would simply load all of your textures into the palette at once. But for the purposes of this tutorial, they are loaded separately for clarity's sake.


.. _0204:

2.4 Multi-Texturing
===================

|HPSNOW| also supports multitexturing. A multitexture is a texture that is composed of two other textures blended together using modulation. For this example, a brick image and a grass image are loaded. You can have up to eight layers of textures blended together. Only one texture may be modulated, the other must be loaded without modulation.

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../internals/tests/docs/source/cpp/00730_tutorial2_1.cpp
		   :start-after: //! [multitexturing]
		   :end-before: //! [multitexturing]
		   
	.. group-tab:: C#

		.. literalinclude:: ../../../internals/tests/docs/source/cs/00730_tutorial2_1.cs
		   :start-after: //! [multitexturing]
		   :end-before: //! [multitexturing]

.. image:: images/02/t.2.4.a.png

*The grass and brick textures blended together using texture modulation.*

