Defining New Materials

 

The notion of material in NAU encompasses the following elements:

Colors allow the definintion of the common color components: diffuse, ambient, emissive, specular, and shininess. However, note that these have no particular meaning, i.e. it is up to the shader to interpret and provide meaning to these attributes. These attributes are provided just for user convenience since they are widely used in shaders.

The material textures contain references to previously defined textures in the same or other material library. When using a texture in a material it is possible to define filtering, wrapping modes, among other settings.

Writable textures, also know as image textures in OpenGL, also reference a previously defined texture. It is possible to specify the mipmap level of the texture, the access level, and ask the texture to be cleared every time the material is set.

Material buffers in a material are references to buffers previously defined in the same or other material library.

The rendering state allows a material to set its own rendering state, which overwrites the default rendering state. For instance it is possible. Inside a material it is possible to reference a pre defined state (defined in the same or other material library).

The shader is what brings it all together. The shader definition in the material library is simply the enumeration of the source code files. In a material shader, such predefined shaders can be referenced, and the shader uniforms are assigned to NAU attributes.

Here is an example of a material definition that shades the geometry with a constant color.

Assume the following vertex shader, saved in a file shaders/color.vert:

#version 330

// the matrices
uniform mat4 PVM;

in vec4 position;	

void main () {
	// transform the vertex coordinates
	gl_Position = PVM * position;	
}

The fragment shader, saved in a file shaders/color.frag, is:

#version 330

uniform vec4 diffuse;

out vec4 colorOut;

void main() {

	colorOut = diffuse;
}

To define our new material we must define a shader that will use as source code the above files, and reference it in a material definition. Furthermore, we must provide values for the uniform variables in the shaders, namely m_pvm and diffuse. Uniform m_pvm is the projection x view x model matrix. NAU has a large number of precomputed matrices available for shader use, including the projection view model matrix. All we need is to establish an association between the uniforms in the shader and the variables NAU provides.

The full material library file for this purpose is as follows:

<?xml version="1.0" ?>
<materiallib name="__nau_material_lib">
	
	<shaders>
		<shader name="color"	ps="shaders/color.frag" 
								vs="shaders/color.vert" />
	</shaders>


	<materials>
		<material name="color">
			<color>
				<DIFFUSE r="0.8" g="0.8" b="0.8" a="1.0" />
			</color>
			<shader name = "color">
				<values>														
					<valueof uniform="diffuse" 		  	
									type="COLOR" context="CURRENT" 
									component="DIFFUSE" />
														
					<valueof uniform="PVM"          	
									type="RENDERER" context="CURRENT" 
									component="PROJECTION_VIEW_MODEL" />
														
				</values>
			</shader>
		</material>	
	</materials>
</materiallib>

Lines 4-7 are the shaders section from the material lib. In this section we can define multiple shaders and use the full set of available shader types, including the compute shader. Each shader type can have multiple files, see here.

The materials tag opens the material definition of the material library. In here multiple materials can be defined. Inside this tag we are defining a new material called “color”. This material has a color section where we defined the DIFFUSE attribute to be grey. Afterwards, comes the shader where we reference the previously defined shader named “color”.

NAU is organized in typed objects, where each object has attributes. For instance, cameras, viewports, and textures are examples of objects. The values of the shader’s uniform variables are going to be fed with these attributes. The tag valueof is used to express this relationship:

  • uniform: the name of the shader uniform variable
  • type: indicates the type of object from which we are retrieving the attribute value
  • context: identifies from which object the attribute is to be retrieved
  • component: identifies the attribute

Regarding the context, the object can be identified by its name or using the keyword CURRENT. In this latter case we are referring to the object that is part of the current state of the renderer. When we are using a material, the material becomes the current material, and its color the current color object.

Let’s start with the uniform diffuse. In this case we want to use the value defined in the color section of the material. To refer to the material’s own color we must define the context as CURRENT. The color component we are interested in is the DIFFUSE attribute.

As for the uniform PVM we must resort to the RENDERER object. This is always the current object, as there is only one renderer. It is the renderer object that provides the projection view matrix as well as other useful matrices in this context.

The full list of attributes for each object type is available in here.