Defining a new material
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 {@link Material}.
Path tracer materials are use for photo realistic rendering. They should extend the class {@link PTMaterial}.
Note that {@link Material} and {@link PTMaterial} inherit from {@link Generic}, which defines methods various method to assign a UUID, a name, a scene ID, to the material. The constructor of {@link Material} and {@link 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 {@link Material} or {@link PTMaterial} but can be overwritten. Although they are very similar the exact lis of properties depend on the kind of material.
Basic material
[uniformType]{@link Generic#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 {@link 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).[usesNormal]{@link Material#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]{@link 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 {@link Solid} constructor throw an error if the shape on which the material is applied does not implement UV coordinates.
[usesLight]{@link Material#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]{@link Material#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]{@link Material#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]{@link Material#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]{@link Generic.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 {@link Generic} which throws an error.
If several instances of the same material are added to the scene, the {@link ShaderBuilder} makes sure that this code is inserted only once in the shader.
[glslRender]{@link Material#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 {@link 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 objectWrap this material into another material with the command
const material = phongWrap(base, params);
The {@link 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 objectWrap this material into another material with the command
const material = pathTracerWrap(specular, params);
The {@link 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
.