We explain here the requirements to define a new material. For examples, we refer the reader to
- the definition of the Phong material in
src/commons/material/phong
; - the definition of the Checkerboard material in
src/commons/material/checkerboard
; - the definition of the BasicPTMaterial material in
src/commons/material/basicPTMaterial
.
Class inheritance
A material is a JS class. There are two kind of materials.
- Basic materials are use for real time rendering. They should extend the class Material.
- Path tracer materials are use for photo realistic rendering. They should extend the class PTMaterial.
Note that Material and PTMaterial inherit from Generic, which defines methods various method to assign a UUID, a name, a scene ID, to the material. The constructor of Material and PTMaterial do not take any argument.
Properties and methods
Any class defining a custom material should implement several methods/properties. Some of them are inherited by default from Material or PTMaterial but can be overwritten. Although they are very similar the exact lis of properties depend on the kind of material.
Basic material
-
uniformType : string(getter):
It says what is the GLSL type used to represent this material.
- If
uniformType
is non-empty, the data relative to the instance of this material are passed to the shader as uniform (as the given type). - If
uniformType
is the empty string, no data is passed to the shader for the instances of this material.
If the getter is not implemented, the class will inherit from the one of Generic which always return the empty string.
The GLSL type of a material can be a custom structure. In this case the structure should be defined in the code return by
glslClass()
(see below). - If
-
usesNormal : boolean (getter)
The property should be true, if the normal to the shape is needed to compute its color with this material.
In this case, the renderer will make sure that the normal is computed, before calling the color function of the material
-
usesUVMap : boolean (getter)
The property should be true, if the UV coordinates of the shape are needed to compute its color with this material.
In this case, the renderer will make sure that the UV coordinates are computed, before calling the color function of the material. In addition, the Solid constructor throw an error if the shape on which the material is applied does not implement UV coordinates.
-
usesLight : boolean (getter)
The property should be true, if the material is sensitive to the lights in the scene.
In this case, the property lights is an array with all the lights that affect the material. If
lights
is not already set up when the solid carrying the material is added to the scene, thenlights
is set up to the list of lights in the scene. -
isReflecting : boolean (getter)
The property should be true if the material is reflexive.
In this case, the reflectivity should be set up in the variable reflectivity. This property is a Three.js Color. Each channel (red, blue, green), interpreted as number between 0 and 1, is the reflectivity coefficient of the corresponding color (0 = no reflectivity, 1 = all light is reflected).
-
glslClass() -> {string} (static function):
It returns the chunk of GLSL code that is common to all instances of this material. If
uniformType
return a custom GLSL type, then this GLSL code should define the corresponding structure. To each property used in the GLSL structure, should correspond a property of the JS class with the same name. Indeed, when the instance of this material is passed to the shader, the JS sends the instance as a whole.If this function is not implemented, the class will inherit from the one of Generic which throws an error.
If several instances of the same material are added to the scene, the ShaderBuilder makes sure that this code is inserted only once in the shader.
-
glslRender() -> {string} (method)
It returns the chunk of GLSL code used to compute the color of this instance of the material. The GLSL should contain a function with one of the following signatures.
vec3 NAME_render(ExtVector v)
vec3 NAME_render(ExtVector v, RelVector normal)
vec3 NAME_render(ExtVector v, vec2 uv)
vec3 NAME_render(ExtVector v, RelVector normal, vec2 uv)
where
NAME
is the name of the instance of the object, computed by the gettername
(inherited from Generic) . The exact signature depends on whether the material requires a normal or UV coordinates. Herev
is the vector obtained when we hit the shape. It should return the color as a vec3 of the material at the given point, without taking into account the possible reflections. Reflections are automatically computed somewhere else in the shader.
Path tracer material
TODO…
Wrapping material.
Defining a material that is affected by the lights can be strenuous, as one needs to rebuild each time the functions handling interactions with lights. To avoid this process one can proceed as follows.
Basic material
- Build a material
base
whose only job is to return the intrinsic color of the object - Wrap this material into another material with the command
const material = phongWrap(base, params);
The phongWrap function takes a basic material and return a material. The material base
passed in argument
define the ambient color of the Phong model for the output material. The parameters of the Phong model are passed in the
object params
.
Path tracer material
- Build a material
specular
whose only job is to return the specular color of the object - Wrap this material into another material with the command
const material = pathTracerWrap(specular, params);
The pathTracerWrap function takes a basic material and return a material. The material specular
passed in
argument define the specular color for the output material. The other parameters of the path tracer are passed in the
object params
.