🧱 Easily extend native three.js materials with modular and composable shader units and effects

Overview

three-extended-material

Easily extend native three.js materials with modular and composable shader units and effects.

image

Usage

npm install three-extended-material

Then, create your extended material:

import { ExtendedMaterial } from "three-extended-material"

const material = new ExtendedMaterial(

    superMaterial,  // the threejs material class to extend

    extensions,     // the extension (or an array of extensions) 
                    // object to extend the material with

    parameters,     // the properties to pass the material 
                    // (can be either properties from the original material, 
                    // or uniforms from the extensions)

    options         // additional options (explained later)
)

An extension is a simple object with the following signature:

const extension = {

  name: "",         // string defining the name of the extension
                    // used to generate a unique shader program code

  uniforms: {},     // uniforms to pass to the materials, in a { uniform: value } format.
                    // note that uniforms are not automatically prepended to the shader code.
                    // be careful about not repeating uniform names when chaining extensions

  defines: {},      // defines to pass to the materials, in a { define: 1 or 0 } format.

  vertexShader: (shader) => shader,     // a function which takes the original vertex
                                        // shader code, and returns the modified cone

  fragmentShader: (shader) => shader,   // a function which takes the original fragment
                                        // shader code, and returns the modified cone
};

The name of each extension is hashed alongside the name of the original material in order to generate a unique shader program cache key for that combination.

The ExtendedMaterial will provide property accessors to all uniforms, so you can use extension.myUniform to set or get the value. This means that when using multiple extension, each uniform name should be unique.

The vertexShader and fragmentShader functions provide you with the original material shaders code, and should return the modified shader code to replace the original shaders code with. A common pattern is to prepend the uniforms definition to the code, and then run a string replace function to add extra shader code in specific places.

Note that when chaining multiple extensions, the shader code is modified for each extension, and passed to the next one - so be careful about not removing pieces of shader which might be queried by later extensions.

You can also pass an options object with any of the following parameters to the ExtendedMaterial constructor as the last argument:

{
  debug: false,           // if true, prints the material's shader code after being patched
  programCacheKey: null   // if not null, sets the customProgramCacheKey 
                          // for the material to this value instead of hashing it.
}

three.js materials' shaders are pretty opinionated - a good starting point would be to use the debug option to print the original shader code, then exploring the ShaderChunks definitions on GitHub to figure out a good injection point for your logic.

Example

Here's a basic setup where we extend the MeshStandardMaterial with an extension which overlays a screen-space checkerboard:

const checkerBoardExtension = {
  name: "checkerboard",
  uniforms: {
    checkersSize: 5.0,
  },
  // no defines or vertex shader modifications needed
  // in this extension, so we can leave them out
  fragmentShader: (shader) => {
    shader = `
      uniform float checkersSize;
      ${shader.replace(
        "#include <output_fragment>",
        // here we inject the checkerboard logic right before the <output_fragment>,
        // where gl_FragColor is set according to the lighting calculation
        // https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/output_fragment.glsl.js
        `
        vec2 pos = floor(gl_FragCoord.xy / checkersSize);
        float pattern = mod(pos.x + mod(pos.y, 2.0), 2.0);
  
        outgoingLight = outgoingLight * pattern;
        #include <output_fragment>
        `
      )}
    `;
    return shader;
  },
};

const material = new ExtendedMaterial(MeshStandardMaterial, [checkerBoardExtension], {
  color: 0x00aaff,
  checkersSize: 8.0, // we can pass different values than the default one...
});

const box = new Mesh(new BoxGeometry(), material);
box.material.checkersSize: 10.0; //... or use the property accessor to set / get its value

Demos

Support Buy me a coffee

If this tool has proven useful to you, consider buying me a coffee to support development of this and many other projects.

You might also like...

Fully typed hooks and utility functions for the React Native StyleSheet API

react-native-style-utilities Fully typed hooks and utility functions for the React Native StyleSheet API npm i react-native-style-utilities ESLint Set

Dec 17, 2022

Further split the React Native code based on Metro build to improve performance, providing `Dll` and `Dynamic Imports` features

Further split the React Native code based on Metro build to improve performance, providing `Dll` and `Dynamic Imports` features

React-Native Code Splitting Further split the React Native code based on Metro build to improve performance, providing Dll and Dynamic Imports feature

Dec 29, 2022

A personal project, made with React, React Native, Typescript and some of the most used front-end libraries.

A personal project, made with React, React Native, Typescript and some of the most used front-end libraries.

A personal project, made with React, React Native, Typescript and some of the most used front-end libraries.

Jul 23, 2022

Easy and simple to use Radio Buttons for your React Native Application.

Easy and simple to use Radio Buttons for your React Native Application.

React Native Simple Radio Buttons Easy and simple to use Radio Buttons for your React Native Application. Installation npm i react-native-custom-radio

Feb 8, 2022

React Native's Global Alert Component that can be fully customized and without the need of a state.

React Native's Global Alert Component that can be fully customized and without the need of a state.

🚩 React Native Easy Alert React Native Easy Alert Component. Watch on youtube Easy Alert example app. React Native's Global Alert Component that can

Feb 21, 2022

📋 React Hooks for forms validation (Web + React Native)

📋 React Hooks for forms validation (Web + React Native)

English | 繁中 | 简中 | 日本語 | 한국어 | Français | Italiano | Português | Español | Русский | Deutsch | Türkçe Features Built with performance and DX in mind

Dec 29, 2022

Free React Native library to display local notifications.

Free React Native library to display local notifications.

React-Native NotiFREE ⚛ React Native library to display local notifications. A FREE alternative to React Native NotiFEE. Why? Nobody can remove the gr

Nov 10, 2022

React Native popup tip utility

React Native popup tip utility

react-native-tip React Native Tip is a simple package inspired in MaterialUI-Tooltip that helps you to show a quick tip to the user and highlight some

Jan 5, 2023

A social app concept with React Native

A social app concept with React Native

Social App Concept-React Native 🔥 A simple social app concept with react native. Improving day by day. Star ⭐ the repo if you like what you see 😉 .

Dec 31, 2022
Comments
  • Bump three from 0.136.0 to 0.137.0

    Bump three from 0.136.0 to 0.137.0

    Bumps three from 0.136.0 to 0.137.0.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 1
A collection of composable React components for building interactive data visualizations

an ecosystem of composable React components for building interactive data visualizations. Victory Contents Getting Started Victory Native API Document

Formidable 10.1k Jan 3, 2023
🎉 toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense!

toastify-react-native ?? toastify-react-native allows you to add notifications to your react-native app (ios, android) with ease. No more nonsense! De

Zahid Ali 29 Oct 11, 2022
null 136 Dec 30, 2022
⚡️ Simple, Modular & Accessible UI Components for your React Applications

Build Accessible React Apps with Speed ⚡️ Chakra UI provides a set of accessible, reusable, and composable React components that make it super easy to

Chakra UI 30.5k Jan 4, 2023
This is a single page application that includes three pages; Home, Calculator and Quotes. You can do Math Calculations and read quotes.

Math magicians app This is a single page application that includes three pages; Home, Calculator and Quotes. You can do Math Calculations and read quo

Lynette Acholah 12 Jun 7, 2022
React components and hooks for creating VR/AR applications with @react-three/fiber

@react-three/xr React components and hooks for creating VR/AR applications with @react-three/fiber npm install @react-three/xr These demos are real,

Poimandres 1.4k Jan 4, 2023
🇨🇭 A React renderer for Three.js

react-three-fiber react-three-fiber is a React renderer for threejs. npm install three @react-three/fiber Why? Build your scene declaratively with re-

Poimandres 20.9k Jan 9, 2023
✂ Multiple scenes, one canvas! WebGL Scissoring implementation for React Three Fiber.

react-three-scissor Multiple scenes, one canvas! WebGL Scissoring implementation for React Three Fiber. scissor lets you render an infinite number of

Poimandres 79 Dec 28, 2022
A collection of sample apps built using GetStream and React Native

React Native samples [ Built with ♥ at Stream ] This repo contains projects and samples developed by the team and Stream community, using React Native

Stream 93 Jan 8, 2023
Boilerplate to build Cross-Platform Apps with Expo and React Native

Expo and React Native Boilerplate Boilerplate to build Cross-Platform Apps with Expo and React Native What are you going to find in this boilerplate E

José Ferrer 26 Apr 29, 2022