Extend Three.js standard materials with your own shaders!
Extend Three.js standard materials with your own shaders!
Custom Shader Material
Extend Three.js standard materials with your own shaders!
These demos are real, you can click them! They contains full code, too. More demos here!
Custom Shader Material (CSM) lets you extend Three.js' material library with your own Vertex and Fragment shaders. It Supports both Vanilla and React!
Show Vanilla example
import CustomShaderMaterial from "three-custom-shader-material/vanilla";
function Box() {
const geometry = new THREE.BoxGeometry();
const material = new CustomShaderMaterial({
baseMaterial: THREE.MeshPhysicalMaterial,
vertexShader: /* glsl */ ` ... `, // Your vertex Shader
fragmentShader: /* glsl */ ` ... `, // Your fragment Shader
// Your Uniforms
uniforms: {
uTime: { value: 0 },
...
},
// Base material properties
flatShading: true,
color: 0xff00ff,
...
});
return new THREE.Mesh(geometry, material);
}Show React example
import CustomShaderMaterial from 'three-custom-shader-material'
function Cube() {
const materialRef = useRef()
useFrame((state) => {
if (materialRef.current) {
materialRef.current.uniforms.uTime.value = state.clock.elapsedTime
}
})
return (
)
}Show Vue (Tresjs) example
Moved to Cientos' Docs
npm install three-custom-shader-material
yarn add three-custom-shader-materialCSM provides the following output variables, all of them are optional but you MUST use these variables like you would use standard GLSL output variables to see results.
| Variable | Type | Description | Available In | Notes |
|---|---|---|---|---|
| Vertex Shader |
| - | - | - | - |
| csm_Position | vec3 | Custom vertex position. | Vertex Shader | csm_Position will be projected furthur down the line. Thus, no projection is needed here. |
| csm_PositionRaw | vec4 | Direct equivalent of gl_Position. | Vertex Shader | |
| csm_Normal | vec3 | Custom vertex normals. | Vertex Shader |
| csm_PointSize | float | Direct equivalent of gl_PointSize. | Vertex Shader | Only available in PointsMaterial |
|
Fragmet Shader
| - | - | - | - |
| csm_DiffuseColor | vec4 | Custom diffuse color. | Fragment Shader | Base material's shading will be applied to this color. |
| csm_FragColor | vec4 | Direct equivalent of gl_FragColor. | Fragment Shader | csm_FragColor will override any shading applied by a base material. To preserve shading and other effects like roughness and metalness, use csm_DiffuseColor |
| csm_Roughness | float | Custom roughness. | Fragment Shader | Only available in materials with an roughnessMap. |
| csm_Metalness | float | Custom metalness. | Fragment Shader | Only available in materials with an metalnessMap. |
| csm_AO | float | Custom AO. | Fragment Shader | Only available in materials with an aoMap. |
| csm_Clearcoat | float | Custom clearcoat factor. | Fragment Shader | Only available in materials with a clearcoat. |
| csm_ClearcoatRoughness | float | Custom clearcoat roughenss factor. | Fragment Shader | Only available in materials with a clearcoat. |
| csm_ClearcoatNormal | vec3 | Custom clearcoat normal. | Fragment Shader | Only available in materials with a clearcoat. |
| csm_Transmission | float | Custom transmission factor. | Fragment Shader | Only available in materials with a transmission. |
| csm_Thickness | float | Custom transmission thickness. | Fragment Shader | Only available in materials with a transmission. |
| csm_Iridescence | float | Custom iridescence factor. | Fragment Shader | Only available in materials with a iridescence. |
| csm_Emissive | vec3 | Custom emissive color. | Fragment Shader | Only available in materials with a emissive. |
| csm_FragNormal | float | Custom fragment normal. | Only available in materials with a normalMap. |
|
Fragmet Shader (Special)
| - | - | - | - |
| csm_DepthAlpha | float | Custom alpha for MeshDepthMaterial. | Fragment Shader | Useful for controlling customDepthMaterial with same shader as the shader material. |
| csm_UnlitFac | float | Custom mix between csm_DiffuseColor and csm_FragColor. | Fragment Shader | Can be used to mix lit and unlit materials. Set to 1.0 by default if csm_FragColor is found in shader string. |
Bump mapping was removed in v6.4.0. This is becasue it cannot be implimented with a singular clean output variable. You can still impliment bump mapping by using csm_FragNormal output variable. See the Bump example for a full working example.
CSM infers prop types based on the baseMaterial prop. However, if this does not work for what ever reason, you can pass your base material type as a generic to CustomShaderMaterial.
// Vanilla
const material = new CustomShaderMaterial({
baseMaterial: THREE.MeshPhysicalMaterial,
//...Any props
});
// React
baseMaterial={THREE.MeshPhysicalMaterial}
//...Any propsYou can type the ref of CustomShaderMaterial as follows:
// NOTE: import from /vanilla module
import CSM from "three-custom-shader-material/vanilla";
import { MeshPhysicalMaterial } from "three";
const ref = useRef>(null!);You can define any custom overrides you'd like using the patchMap prop. The prop is used as shown below.
const material = new CustomShaderMaterial({
baseMaterial: THREE.MeshPhysicalMaterial,
vertexShader: ` ... `,
fragmentShader: ... `,
uniforms: {...},
patchMap={{
"": { // The keyword you will assign to in your custom shader
"TO_REPLACE": // The chunk you'd like to replace.
"REPLACED_WITH" // The chunk you'd like put in place of `TO_REPLACE`
}
}}
})Note: If `` is not found in shader string, the patch map will not be applied. To ALWAYS apply a patch map, use the special keyword -
*(star).patchMap={{ "*": { "TO_REPLACE": "REPLACED_WITH" } }}
CSM allows you to extend other CSM instances. Values set in the first shader will affect the next.
Note: Extending of other materials that use
onBeforeCompilemay or may not work depending on if the default#includesare mangled.
Show Vanilla example
import CustomShaderMaterial from "three-custom-shader-material/vanilla";
function Box() {
const material1 = new CustomShaderMaterial({
baseMaterial: THREE.MeshPhysicalMaterial,
//...Any props
});
const material2 = new CustomShaderMaterial({
baseMaterial: material1,
//...Any props
});
}Show React example
import CustomShaderMaterial from "three-custom-shader-material";
import CustomShaderMaterialImpl from "three-custom-shader-material/vanilla";
function Cube() {
const [materialRef, setMaterialRef] = useState();
return (
<>
{materialRef && (
)}
);
}csm_Position MUST be a non-projected vector. i.e., no need to multiply projectionMatrix or modelViewPosition withNo open issues yet, or sync has not completed.