{"id":13773232,"url":"https://github.com/pmndrs/component-material","last_synced_at":"2025-10-08T00:31:52.764Z","repository":{"id":49726760,"uuid":"318274401","full_name":"pmndrs/component-material","owner":"pmndrs","description":"🧩 Compose modular materials in React","archived":true,"fork":false,"pushed_at":"2021-06-10T09:49:05.000Z","size":4048,"stargazers_count":162,"open_issues_count":9,"forks_count":10,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-10-29T23:50:18.173Z","etag":null,"topics":["react","react-three-fiber","shaders","threejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pmndrs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-03T17:46:51.000Z","updated_at":"2024-10-28T21:45:06.000Z","dependencies_parsed_at":"2022-09-12T15:13:23.334Z","dependency_job_id":null,"html_url":"https://github.com/pmndrs/component-material","commit_stats":null,"previous_names":["emmelleppi/component-material"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fcomponent-material","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fcomponent-material/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fcomponent-material/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pmndrs%2Fcomponent-material/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pmndrs","download_url":"https://codeload.github.com/pmndrs/component-material/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234933094,"owners_count":18909405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["react","react-three-fiber","shaders","threejs"],"created_at":"2024-08-03T17:01:13.184Z","updated_at":"2025-10-08T00:31:47.398Z","avatar_url":"https://github.com/pmndrs.png","language":"TypeScript","funding_links":[],"categories":["3D"],"sub_categories":[],"readme":"![](https://raw.githubusercontent.com/emmelleppi/component-material/master/logo.jpg)\n\n[![Version](https://img.shields.io/npm/v/component-material?style=flat\u0026colorA=000000\u0026colorB=000000)](https://www.npmjs.com/package/component-material)\n[![Downloads](https://img.shields.io/npm/dt/component-material.svg?style=flat\u0026colorA=000000\u0026colorB=000000)](https://www.npmjs.com/package/component-material)\n[![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat\u0026colorA=000000\u0026colorB=000000\u0026label=discord\u0026logo=discord\u0026logoColor=ffffff)](https://discord.gg/ZZjjNvJ)\n\n# Component Material\n\nMaterial is a React utility that helps you compose and modify materials in [react-three-fiber](https://github.com/pmndrs/react-three-fiber) and threejs.\n\n### Examples\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://codesandbox.io/embed/component-material-distortion-example-p4cly?fontsize=14\u0026hidenavigation=1\u0026theme=dark\"\u003e\u003cimg width=\"274\" height=\"150\" src=\"https://raw.githubusercontent.com/emmelleppi/component-material/master/readme/distortion.jpg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codesandbox.io/embed/component-material-voronoi-example-cuq2n?fontsize=14\u0026hidenavigation=1\u0026theme=dark\"\u003e\u003cimg width=\"274\"  height=\"150\" src=\"https://raw.githubusercontent.com/emmelleppi/component-material/master/readme/voronoi.jpg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codesandbox.io/embed/component-material-multiple-instances-bxr5u?fontsize=14\u0026hidenavigation=1\u0026theme=dark\"\u003e\u003cimg width=\"274\"  height=\"150\" src=\"https://raw.githubusercontent.com/emmelleppi/component-material/master/readme/multiple-instances.jpg\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Quick start\n\n```bash\nyarn add component-material\n```\n\n```jsx\nimport Material from 'component-material'\n\nfunction CustomMaterial(props) {\n  return (\n    \u003cMaterial\n      {...props}\n      // 1️⃣ declare uniforms with the correct type\n      uniforms={{\n        r: { value: 1, type: 'float' },\n        g: { value: 0.5, type: 'float' },\n        b: { value: 0, type: 'float' },\n      }}\u003e\n      \u003cMaterial.Frag.Body\n        // 2️⃣ Access the uniforms in your shader\n        children={`gl_FragColor = vec4(r, g, b, 1.0);`}\n      /\u003e\n    \u003c/Material\u003e\n  )\n}\n\nfunction Sphere() {\n  return (\n    \u003cmesh\u003e\n      \u003csphereBufferGeometry /\u003e\n      \u003cCustomMaterial /\u003e\n    \u003c/mesh\u003e\n```\n\n## Features\n\n- Create custom shaders on top of existing threejs Shaders and shader-chunks\n- Compose your shader code with modular injects\n- Auto-completion, intellisense and typechecking\n- Syntax-highlighting with either [tagged glsl-literals](https://marketplace.visualstudio.com/items?itemName=boyswan.glsl-literal) or [comment-tagged templates](https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates)\n- Glslify and imports via [babel-plugin-glsl](https://github.com/onnovisser/babel-plugin-glsl)\n\n## `\u003cMaterial/\u003e`\n\n#### `from`\n\nBy default Material extends three's MeshPhysicalMaterial. If you want to extend a different material just use the `from` prop passing the desired material constructor.\n\n```jsx\n\u003cMaterial from={THREE.MeshPhongMaterial} /\u003e\n```\n\n#### `uniforms`\n\nUniforms used inside shaders can be defined via the `uniforms` prop as follows\n\n```jsx\n\u003cMaterial\n  uniforms={{\n    myUniform1: { value: 0, type: 'float' },\n    myUniform2: { value: [0, 1], type: 'vec2' },\n  }}\n/\u003e\n```\n\nThis will also create setters and getters for the uniforms automatically, allowing you to mutate them using props and effectively making the material reactive:\n\n```jsx\nfunction CustomMaterial({ color }) {\n  return (\n    \u003cMaterial\n      uniforms={{ color: { value: color, type: 'vec3' } }}\n      color={color} // color uniform will have the value of the color prop\n    /\u003e\n```\n\n- The correspondences between glsl and javascript types can be seen [here](https://threejs.org/docs/#api/en/core/Uniform)\n- Uniforms cannot be defined twice in the same shader. So be careful not to define the same uniforms inside the `head` tag.\n\n#### `varyings`\n\nVarying variables can be defined directly inside the shader `head` tag or they can be declared as prop:\n\n```jsx\n\u003cMaterial\n  varyings={{\n    myVarying1: { type: 'float' },\n    myVarying2: { type: 'vec2' },\n  }}\n/\u003e\n```\n\nThis is equivalent to adding this code to both your vertex and fragment shaders heads:\n\n```glsl\nfloat myVarying1;\nvec2 myVarying2;\n```\n\n- Varyings don't have an initial value, only a type definition\n- As uniforms, varyings cannot be defined twice in the same shader, this will give a glsl error. So be careful not to define the same varyings inside the `head` tag.\n\n## Fragment- and vertex-shader composition\n\nThe `Frag` and `Vert` tags have the function of injecting the shader text, passed as children, into the preconfigured shader of the threejs material. Let's see what it means with an example:\n\n```jsx\n\u003cMaterial uniforms={{ time: { value: 0, type: 'float' } }}\u003e\n  \u003cMaterial.Frag.Head\n    children={`\n    float quadraticInOut(float t) {\n      float p = 2.0 * t * t;\n      return t \u003c 0.5 ? p : -p + (4.0 * t) - 1.0;\n    }`}\n  /\u003e\n  \u003cMaterial.Frag.Body\n    children={`\n    gl_FragColor.a = gl_FragColor.a * quadraticInOut((sin(time) + 1.0) / 2.0);`}\n  /\u003e\n```\n\nIn the code above the `Frag.Head` component adds an easing function `quadraticInOut` to the fragment shader of the material, prepending it before the `main` function of the shader.\n\nThe `Frag.Body` component instead adds a line of code that modify the `gl_FragColor` alpha value, appending it after the last operation of the main function.\n\nIn particular, if we take as an example the fragment shader of the `MeshPhysicalMaterial`, `Frag.Head` prepends the code before [this shader line](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js#L2), `Frag.Body` instead posts the code after [this shader line](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js#L124) (the `dithering_fragment` chunk).\n\nThe same goes for the `Vert` component, which however acts on the vertex shader. In particular, `Vert.Head` prepends the code to [this shader line](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js#L2), while `Vert.Body` appends the code to [this shader line](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js#L60) (the `project_vertex` chunk).\n\nIt is possible to inject the code after a particular chunk just by doing\n\n```jsx\n\u003cMaterial.Frag.my_chunk children={`// my custom shader`} /\u003e\n```\n\nwhere `my_chunk` must be replaced with the name of the chunk concerned.\n\nIf we wanted to insert some code just after the `emissivemap_fragment` chunk ([here the reference for the MeshPhysicalMaterial](https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js#L99)) then just use the following code\n\n```jsx\n\u003cMaterial.Frag.emissivemap_fragment children={`// my custom shader`} /\u003e\n```\n\n#### `replaceChunk`\n\nThe `replaceChunk` prop is a boolean that allows you to completely replace the chosen chunk, so instead of append the custom shader code after the chunk it will be replaced directly.\n\n```jsx\n\u003cMaterial.Frag.emissivemap_fragment replaceChunk children={`// my custom shader`} /\u003e\n```\n\n## Common chunks\n\nThe `Common` tag is useful in case vertex shader and fragment shader share some functions.\n\n❌ If both the fragment shader and the vertex shader share the easing function `quadraticInOut`, instead of writing\n\n```jsx\n\u003cMaterial.Vert.Head\n  children={`\n  float quadraticInOut(float t) {\n    float p = 2.0 * t * t;\n    return t \u003c 0.5 ? p : -p + (4.0 * t) - 1.0;\n  }`}\n/\u003e\n\u003cMaterial.Frag.Head\n  children={`\n  float quadraticInOut(float t) {\n    float p = 2.0 * t * t;\n    return t \u003c 0.5 ? p : -p + (4.0 * t) - 1.0;\n  }`}\n/\u003e\n```\n\n✅ we will write\n\n```jsx\n\u003cMaterial.Common\n  children={`\n  float quadraticInOut(float t) {\n    float p = 2.0 * t * t;\n    return t \u003c 0.5 ? p : -p + (4.0 * t) - 1.0;\n  }`}\n/\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fcomponent-material","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpmndrs%2Fcomponent-material","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpmndrs%2Fcomponent-material/lists"}