My favorites | English | Sign in

Materials

This chapter describes how to assign a material to a shape primitive in the transform graph and how to assign an effect to a material. It also covers how to create parameters on materials that are required by the shader, and it introduces the concept of transform semantics, described in detail in Shading Language.

The Hello, Cube Colors sample creates a red cube with a button that allows the user to change the color of the cube. (To view the code for Hello, Cube Colors in a new window, click here).

Contents

  1. Creating the Shape and Primitive
  2. Creating the Material and Setting Parameters
  3. Setting Up the Transform Graph
  4. Render Callback Function
  5. See Also: Instance Override Sample
  6. Next: Textures

Creating the Shape and Primitive

In the Hello, Cube Colors sample, the createCube() function creates the shape, primitive, and stream bank objects. It then constructs the cube primitive using arrays, buffers, streams, and stream banks, as discussed in Shapes. Here is the code for creating the objects and setting up the relationships between them:

function createCube(material) {
  var cubeShape = g_pack.createObject('Shape');
  var cubePrimitive = g_pack.createObject('Primitive');
  var streamBank = g_pack.createObject('StreamBank');
  
  cubePrimitive.material = material;
  cubePrimitive.owner(cubeShape);
  cubePrimitive.streamBank = streamBank;

  //followed by code that sets up the arrays, buffers, streams, and stream banks (see chapter on "Shapes")
  .
  .
  .
}

Creating the Material and Setting Parameters

The next step is to create a material, set its draw list, and assign an effect to it. The cubeMaterial is set to the performance draw list, which handles draw elements for primitives that have opaque materials.

// Create a Material for the mesh. 
var cubeMaterial = g_pack.createObject('Material');
// Set the material's drawList.
cubeMaterial.drawList = viewInfo.performanceDrawList;
 
// Apply our effect to this material. The effect tells the 3D hardware
// which shaders to use.
cubeMaterial.effect = cubeEffect;
 
// Create an O3D Param on the material for every uniform parameter used by the
// shader.
cubeEffect.createUniformParameters(cubeMaterial);
 
// Get the color parameter from the material and set its value to red.
g_cubeColorParam = cubeMaterial.getParam('color');
g_cubeColorParam.value = [1, 0, 0, 1];

Parameters

A shader defines a number of parameters whose values are supplied by objects in the transform graph (usually by the Material) or by O3D, depending on the whether the parameter falls into one of the following two general categories:

  • Parameters that are associated with standard semantics (see the section on SAS Parameters)
  • Parameters without standard semantics (see the section on Non-SAS Parameters)

Shader parameters are defined at the start of the shader code, contained in the <textarea> element at the end of the sample program. The Hello, Cube Colors example declares two parameters (worldViewProjection and color):

<textarea id="effect">
// World View Projection matrix that will transform the input vertices
// to screen space.
float4x4 worldViewProjection : WorldViewProjection;

// This specifies the color of the triangles.  A Param with the same name will
// be created on the material that uses the effect.
float4 color;
...

When the parameter name is followed by a colon (:) and another string, the string is a semantic that explains how to use this parameter value. If the string is contained in the list defined in Standard Annotations and Semantics (SAS), then it is treated specially by the system.

SAS Parameters

If the shader specifies an SAS semantic value for the parameter, O3D automatically computes the value for this parameter and supplies it to the shader behind the scenes. This is the case for the worldViewProjection parameter:

float4x4 worldViewProjection : WorldViewProjection;

In this piece of code, the colon (:) is followed by this parameter's semantic, which is WorldViewProjection. The Shading Language chapter describes the meaning of all standard transform semantics used by O3D. For example, it explains that a WorldViewProjection is a concatenation of the world, view, and projection matrices. The transform semantics used by O3D are based on NVidia's Standard Annotations and Semantics (SAS) which describe standard transformation matrices.

If you explicitly create an SAS parameter, you are also responsible for setting the value's parameter; the system will not supply a value in this case. For example, if you explicitly create a worldViewMatrix parameter, O3D will not specify its value:

material.createParam('worldViewMatrix', 'ParamMatrix4');

Non-SAS Parameters

The createUniformParameters() function creates a parameter on the material for every non-SAS parameter required by the shader. Values for these parameters must be explicitly set within your program.

In this example, the color parameter is a non-SAS parameter. The function call cubeEffect.createUniformParameters(cubeMaterial); creates this parameter on the material. Parameters such as color, intensity, shininess, and so on are called uniform parameters because they are the same for every vertex and pixel that uses this material.

The value for the color parameter is set with the call g_cubeColorParam.value = [1, 0, 0, 1];. When this program is running, the user can change the value of this parameter by pressing the button on the page. This action invokes the changeColor() function.

Custom Semantics

There may also be cases where you want to supply your own semantic, for use in a custom, high-level framework. For example:

float4x4 decoration : flower;

The semantic of decoration is now flower. In this case, O3D will not supply a value for the parameter since it is not a standard semantic, but you can look up the semantic with effect.getParameterInfo().

Setting Up the Transform Graph

The initStep2() function calls createCube() to create the shape object, the cube triangle mesh, and the material. Then initStep2() constructs the small transform graph, which contains the client root object, a Transform, and the cubeShape.

// Create the Shape for the cube mesh and assign its material.
var cubeShape = createCube(cubeMaterial);

// Create a new transform and parent the Shape under it.
g_cubeTransform = g_pack.createObject('Transform');
g_cubeTransform.addShape(cubeShape);

// Parent the cube's transform to the client root.
g_cubeTransform.parent(g_client.root);
	

Here is the Transform graph for this sample:

Render Callback Function

The scene is automatically rendered each time the hardware refreshes the screen. In this example, the setRenderCallback()function calls renderCallback(), which causes the cube to spin by updating the transform values.

// Set our render callback for animation.
// This sets a function to be executed every time a frame is rendered.
g_client.setRenderCallback(renderCallback);

See Also: Instance Override Sample

The instance-override.html sample creates one sphere object that is instanced multiple times with a different Transform for each instance. A colorMult parameter is set on each Transform. This is an efficient technique to give each sphere a different color without creating a thousand different spheres.

Next: Textures

Textures describes how to set up a texture sampler. It explains texture coordinates, address modes, magnification and minification filters and mip filtering using mipmaps.

Back to top