THREE-CustomShaderMaterial icon indicating copy to clipboard operation
THREE-CustomShaderMaterial copied to clipboard

Extend Three.js standard materials with your own shaders!


Logo

Custom Shader Material

Extend Three.js standard materials with your own shaders!


Waves Waves Caustics

The demo is real, you can click it! It contains full code, too. 📦


Chat on Twitter


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 */ ` ... `,
    fragmentShader: /* glsl */ ` ... `,
    uniforms: {
      uTime: {
        value: 0,
      },
    },
    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 (
    <mesh>
      <boxGeometry />
      <CustomShaderMaterial
        ref={materialRef}
        baseMaterial={THREE.MeshPhysicalMaterial}
        vertexShader={/* glsl */ ` ... `}
        fragmentShader={/* glsl */ ` ... `}
        uniforms={{
          uTime: {
            value: 0,
          },
        }}
        flatShading
        color={0xff00ff}
        // ...
      />
    </mesh>
  )
}

Installation

npm install three-custom-shader-material
yarn add three-custom-shader-material

Output Variables

CSM 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
csm_Position vec3 Custom vertex position. Vertex Shader csm_Position will be projected furthur down the line. Thus, no projection is needed here.
csm_DiffuseColor vec4 Custom diffuse color. Fragment Shader
csm_Normal vec3 Custom vertex normals. Vertex Shader
csm_PointSize float Custom gl_PointSize. Vertex Shader Only available in PointsMaterial
csm_FragColor vec4 Custom 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_Emissive vec3 Custom emissive color. Fragment Shader Only available in MeshPhysicalMaterial and MeshStandardMaterial
csm_Roughness float Custom roughness. Fragment Shader Only available in MeshPhysicalMaterial and MeshStandardMaterial
csm_Metalness float Custom metalness. Fragment Shader Only available in MeshPhysicalMaterial and MeshStandardMaterial
// gl_Position = projectionMatrix * modelViewPosition * position * vec3(2.0);
csm_Position = position * vec3(2.0);

Custom overrides

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={{
      "<KEYWORD>": {        // 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`
      }
   }}
})