A material rendered with custom shaders. A shader is a small program written in GLSL that runs on the GPU. You may want to use a custom shader if you need to:
ShaderMaterial
:
ShaderMaterial
will only be rendered properly by WebGLRenderer,
since the GLSL code in the vertexShader
and fragmentShader properties must
be compiled and run on the GPU using WebGL.
for
loop in GLSL by the shader preprocessor.
The directive has to be placed right above the loop. The loop formatting has to correspond to a defined standard.
#pragma unroll_loop_start
for (int i = 0; i < 10; i++) {
// ...
}
#pragma unroll_loop_end
const material = new v3d.ShaderMaterial({
uniforms: {
time: { value: 1.0 },
resolution: { value: new v3d.Vector2() }
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
webgl / buffergeometry / custom / attributes / particles
webgl / buffergeometry / selective / draw
webgl / custom / attributes
webgl / custom / attributes / lines
webgl / custom / attributes / points
webgl / custom / attributes / points2
webgl / custom / attributes / points3
webgl / depth / texture
webgl / gpgpu / birds
webgl / gpgpu / protoplanet
webgl / gpgpu / water
webgl / interactive / points
webgl / video / kinect
webgl / lights / hemisphere
webgl / marchingcubes
webgl / materials / envmaps
webgl / materials / lightmap
webgl / materials / wireframe
webgl / modifier / tessellation
webgl / postprocessing / dof2
webgl / postprocessing / godrays
You can specify two different types of shaders for each material:
attributes
, calculates / manipulates
the position of each individual vertex, and passes additional data (varying
s) to the fragment shader.
There are three types of variables in shaders: uniforms, attributes, and varyings:
Uniforms
are variables that have the same value for all vertices - lighting, fog,
and shadow maps are examples of data that would be stored in uniforms.
Uniforms can be accessed by both the vertex shader and the fragment shader.
Attributes
are variables associated with each vertex---for instance, the vertex position,
face normal, and vertex color are all examples of data that would be stored in attributes.
Attributes can only
be accessed within the vertex shader.
Varyings
are variables that are passed from the vertex shader to the fragment shader.
For each fragment, the value of each varying will be smoothly interpolated from the values of adjacent vertices.
Note that within
the shader itself, uniforms and attributes act like constants;
you can only modify their values by passing different values to the buffers from your JavaScript code.
The WebGLRenderer provides many attributes and uniforms to shaders by default;
definitions of these variables are prepended to your fragmentShader
and vertexShader
code by the WebGLProgram when the shader is compiled; you don't need to declare them yourself.
See WebGLProgram for details of these variables.
Some of these uniforms or attributes (e.g. those pertaining lighting, fog, etc.) require properties to be set on the material in order for WebGLRenderer to copy the appropriate values to the GPU - make sure to set these flags if you want to use these features in your own shader.
If you don't want WebGLProgram to add anything to your shader code, you can use RawShaderMaterial instead of this class.
Both custom attributes and uniforms must be declared in your GLSL shader code
(within vertexShader
and/or fragmentShader
). Custom uniforms must be defined in both
the uniforms
property of your ShaderMaterial
, whereas any custom attributes must be
defined via BufferAttribute instances. Note that varying
s only need to
be declared within the shader code (not within the material).
To declare a custom attribute, please reference the BufferGeometry page for an overview,
and the BufferAttribute page for a detailed look at the BufferAttribute
API.
When creating your attributes, each typed array that you create to hold your attribute's data must be a multiple of your data type's size. For example, if your attribute is a v3d.Vector3 type, and you have 3000 vertices in your BufferGeometry, your typed array value must be created with a length of 3000 * 3, or 9000 (one value per-component). A table of each data type's size is shown below for reference:
GLSL type | JavaScript type | Size |
---|---|---|
float | Number | 1 |
vec2 | v3d.Vector2 | 2 |
vec3 | v3d.Vector3 | 3 |
vec3 | v3d.Color | 3 |
vec4 | v3d.Vector4 | 4 |
Note that attribute buffers are not
refreshed automatically when their values change. To update custom attributes,
set the needsUpdate
flag to true on the BufferAttribute of the geometry (see BufferGeometry
for further details).
To declare a custom Uniform, use the uniforms
property:
uniforms: {
time: { value: 1.0 },
resolution: { value: new v3d.Vector2() }
}
You're recommended to update custom Uniform values depending on object and camera in Object3D.onBeforeRender because Material can be shared among meshes, matrixWorld of Scene and Camera are updated in WebGLRenderer.render, and some effects render a scene with their own private cameras.
parameters - (optional) an object with one or more properties defining the material's appearance. Any property of the material (including any property inherited from Material) can be passed in here.
See the base Material class for common properties.
Defines whether this material supports clipping; true to let the renderer pass the clippingPlanes uniform. Default is false.
Custom preprocessing tokens - an object analogous to the .defines property, but
instead of adding a #define directive for every key/value pair they are manually
replaced in the GLSL code before shader compilation. Used for the #pragma unroll_loop
directive to define the loop initializer and the condition values the same way as
with a #define directive, but since unrolling is performed prior to compilation
these values also have to be known afore, that's why this property is a distinct
container for such values:
customPrepTokens: {
MAX_SIZE: 10
}
makes the following code:
for (int i = 1; i <= MAX_SIZE; i++) {
// ...
}
to be this before compilation:
for (int i = 1; i <= 10; i++) {
// ...
}
When the rendered geometry doesn't include these attributes but the material does,
these default values will be passed to the shaders. This avoids errors when buffer data is missing.
this.defaultAttributeValues = {
'color': [1, 1, 1],
'uv': [0, 0],
'uv2': [0, 0]
};
Defines custom constants using #define
directives within the GLSL code for both the
vertex shader and the fragment shader; each key/value pair yields another directive:
defines: {
FOO: 15,
BAR: true
}
yields the lines
#define FOO 15
#define BAR true
in the GLSL code.
An object with the following properties:
this.extensions = {
derivatives: false, // set to use derivatives
fragDepth: false, // set to use fragment depth values
drawBuffers: false, // set to use draw buffers
shaderTextureLOD: false // set to use shader texture LOD
};
Define whether the material color is affected by global fog settings; true to pass fog uniforms to the shader. Default is false.
Fragment shader GLSL code. This is the actual code for the shader. In the example above,
the vertexShader
and fragmentShader
code is extracted from the DOM; it could be passed
as a string directly or loaded via AJAX instead.
Defines the GLSL version of custom shader code. Only relevant for WebGL 2 in order to define whether to specify
GLSL 3.0 or not. Valid values are v3d.GLSL1
or v3d.GLSL3
. Default is null
.
If set, this calls gl.bindAttribLocation to bind a generic vertex index to an attribute variable. Default is undefined.
Read-only flag to check if a given object is of type ShaderMaterial.
Defines whether this material uses lighting; true to pass uniform data related to lighting to this shader. Default is false.
Controls wireframe thickness. Default is 1.
Due to limitations of the OpenGL Core Profile
with the WebGL renderer on most platforms linewidth will
always be 1 regardless of the set value.
Define whether the material is rendered with flat shading. Default is false.
An object of the form:
{ "uniform1": { value: 1.0 }, "uniform2": { value: 2 } }
specifying the uniforms to be passed to the shader code; keys are uniform names, values are definitions of the form
{ value: 1.0 }
where value
is the value of the uniform. Names must match the name of the uniform,
as defined in the GLSL code. Note that uniforms are refreshed on every frame,
so updating the value of the uniform will immediately update the value available to the GLSL code.
Can be used to force a uniform update while changing uniforms in Object3D.onBeforeRender(). Default is false
.
Defines whether vertex coloring is used. Default is false
.
Vertex shader GLSL code. This is the actual code for the shader. In the example above,
the vertexShader
and fragmentShader
code is extracted from the DOM; it could be passed
as a string directly or loaded via AJAX instead.
Render geometry as wireframe (using GL_LINES instead of GL_TRIANGLES). Default is false (i.e. render as flat polygons).
Controls wireframe thickness. Default is 1.
Due to limitations of the OpenGL Core Profile
with the WebGL renderer on most platforms linewidth will
always be 1 regardless of the set value.
See the base Material class for common methods.
Generates a shallow copy of this material. Note that the vertexShader and fragmentShader
are copied by reference
, as are the definitions of the attributes
; this means
that clones of the material will share the same compiled WebGLProgram. However, the
uniforms
are copied by value
, which allows you to have different sets of uniforms
for different copies of the material.
For more info on how to obtain the source code of this module see this page.