3d-wood-material
Build convincing timber for Three.js as one procedural MeshPhysicalMaterial with growth rings, cathedral figure, pores, medullary rays, checks, tool marks, end grain, and oil, wax, or lacquer finishes, so the grain follows the form and survives macro close-ups without image textures.
Install / Use
npx skills add MengTo/Skills --skill 3d-wood-materialInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of 3d-wood-material
3d-wood-material scores 86/100 on our quality scale, 2450th of 4,588 Development & Engineering skills we index.
Its SKILL.md is 11 KB long, split into 7 sections and no code examples: a thorough specification that gives an agent plenty to work with.
With 6,252 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 16 days ago, so 3d-wood-material is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
3d-wood-material compared with similar skills
All 4 of these similar skills score higher than 3d-wood-material; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| 3d-wood-material (this skill)by MengTo | 86 | 6.3k | 16d ago | SKILL.md |
| ai-job-searchby MadsLorentzen | 100 | 45.4k | today | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.8k | 9d ago | CLAUDE.md |
| LocalAIby mudler | 100 | 49.4k | today | MCP Server |
| algorithmic-artby anthropics | 100 | 177.9k | 16d ago | SKILL.md |
Frequently asked questions
- How do I install 3d-wood-material?
- Run
npx skills add MengTo/Skills --skill 3d-wood-material. The install tabs above show the steps for each supported agent. - Which AI agents does 3d-wood-material work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is 3d-wood-material safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is 3d-wood-material still maintained?
- The repository was last updated 16 days ago, so 3d-wood-material is actively maintained.
Skill content
View source on GitHubname: 3d-wood-material description: Build convincing timber for Three.js as one procedural MeshPhysicalMaterial with growth rings, cathedral figure, pores, medullary rays, checks, tool marks, end grain, and oil, wax, or lacquer finishes, so the grain follows the form and survives macro close-ups without image textures. Use for wood boards, benches, carved panels, tool handles, joinery, floors, and any request to make 3D wood look real, detailed, or less like a tiled photo or plastic.
3D Wood Material
Mechanism: one small periodic noise field, mip-filtered, is read at several different stretches and scales inside the fragment shader, so ring position, latewood, pores, fibres, rays and tool marks all come from the same wandering grain and feed colour, roughness and relief together, each fading out by its own screen footprint.
Boundary. This skill is the wood surface itself. For whole-scene light, rays and scoring wood renders, use 3d-wood-lighting-scorecard. For image-based PBR sets (downloaded maps, texel budgets, KTX2 delivery) use 3d-high-resolution-textures; reach for it when you need a photographed or scanned species. For silhouette, bevel and LOD geometry use 3d-high-poly-models; this skill only needs a rounded arris (below). Cloth, metal and paper have their own siblings.
Run demo.html first (Kibori bench, four species, four finishes, macro views, and a switch that swaps in the failure). PROMPT.md recreates it.
Recipe
- Patch, do not replace. Build
MeshPhysicalMaterial({color:0xffffff, roughness:max(0.43,r), ior:1.43, specularIntensity:0.72})and edit it inonBeforeCompile:#include <map_fragment>multipliesdiffuseColorby the wood colour,#include <roughnessmap_fragment>setsroughnessFactor=clamp(roughness*W.rough,0.35,1),#include <normal_fragment_maps>replaces the normal with a screen-space bump of the wood heightW.h. Lighting, shadows, IBL and tone-mapping stay stock. The vertex stage only passes object-space positionvOPand the object normal. - Bake one field. A 1024²
RepeatWrapping,LinearMipmapLinear,NoColorSpacerender target of periodic gradient noise (period 64, three octaves:.rbase,.gfbm 0.60/0.27/0.13,.ba shifted copy). Reading it astexture(p/64)costs one tap. All timber shares it; per-board difference is a seed offset, not a texture. - Grain axis.
uAxis0/1/2 picks the log axis;alongis that coordinate andcross2the other two.endgrain = pow(|n·axis|, 6)flips pores from streaks to open cells and dulls the colour on cut faces. - Rings. Drift the pith with two slow fields,
radius=|(cross2+(-drift, offAxis+0.48))*(1,0.56)|,growth=radius*ringFreqplus fbm wobble (±1.25rings),ring=floor(growth),phase=fract. Each ring draws its own width fromannualnoise:lateWidth=0.065+annual*0.21. Latewood is a steepsmoothstep(0.94-w, 0.97-w, phase)cut off by1-smoothstep(0.965,1,phase). SmalloffAxisgives cathedral arcs; largeoffAxisgives straight quarter-sawn lines. - Detail layers, each faded by its own footprint (
fwidthof growth,length(dFdx,dFdy)of the pore, fibre and ray coordinates):
| layer | coordinates | strength |
| --- | --- | --- |
| pores (vessels) | (fiberX*96, along*7.5), cells at end grain cross2*88, smoothstep(0.59,0.75) | tone +0.25, rough +0.19, height -0.42 |
| fibres | (fiberX*230, along*2.4) | tone -0.16, height +0.09, x0.25 at end grain |
| rays | (across*13, along*115), smoothstep(0.64,0.78) | tone +0.26 towards pale, rough -0.075 |
| checks | curl.b smoothstep(0.70,0.82) x uChecks | tone toward dark*0.68, height -0.20 |
| knots | hash cell 1.85 x 4.6, 29% occupied, influence dies at the cell edge | tone +0.44 core, deflects fibres |
| tool marks | (along*17, across*0.4) | height +0.045 x uTool |
- Tone:
tone=0.075+late*0.40+early*0.070+pores*0.25-fibres*0.16+(broad.g-0.5)*0.23+knotCore*0.44, colourmix(pale,dark,clamp(tone,0.035,0.83)), then*(0.93+annual*0.095+…). Roughness0.91+late*0.13+pores*0.19+(broad.b-0.5)*0.20-rays*0.075+endgrain*0.14. - Bump, not normal map.
bumpNormaluses the derivative-based Mikkelsen bump and clamps the gradient to0.38*|det|, so a steep step never flips the normal.uBump=bump*0.020. - Finishes are parameters, not textures. Raw:
clearcoat 0. Oil:pow(rgb,1.16)andrough*0.88,clearcoat 0.10 / 0.55. Wax:clearcoat 0.22 / 0.38. Urushi: luminance curvepow(l,0.5), end grain darkened*(1-eg*0.55), warm tint, worn arrises rubbed back to the pale colour,clearcoat 0.42 / 0.40. - Round the arris.
chamferBoxon every board, radiusmin(w,h,d)*0.055(at most 0.24 of any side), 3 to 5 segments, with normals set from the rounded corner. A sharp box edge has no highlight and reads as a cut-out. - Give every board its own seed, and keep it stable when species or finish changes (save and restore
woodMaterialSerialaround the build, seedn*7.113). Offset the geometry through the field (woodBox(..., ox,oy,oz)) so merged or shared materials still differ.
Species constants (from the workshop)
| species | pale / dark | rough | grain | ringFreq | offAxis | notes |
| --- | --- | --- | --- | --- | --- | --- |
| keyaki | #8a5f38 / #3d2412 | 0.62 | 1.5 | 20 to 34 | 0.75 | rays 0.35, bump 0.10 |
| sugi | #c8a579 / #9b774d | 0.58 | 1.8 | 8 to 30 | 2.8 | crisp latewood, tool 0.30 |
| hinoki | #d8c096 / #8a6b40 | 0.44 to 0.50 | 2.2 | 6 to 42 | 1.6 | close-grained, low contrast |
| kuri | #6f4d2c / #2c1a0b | 0.55 | 3.0 | 5 to 22 | 1.4 | rays 0.5, checks 0.10 |
| charred siding | #1a1511 / #0e0b08 | 0.97 | 0.8 | 9 | 0.55 | rays 0, checks 0.30 |
ringFreq is per unit of the model, so set it from real ring spacing (about 2 to 5 mm at the scale you are modelling) rather than copying a number between scenes: the workshop's 7 to 8 read as bold stripes at demo scale until raised to 20 to 42.
Anchored failures
- A repeated tile is visible at the second board. A canvas tile with
repeatprints identical rings on every board and shows its seam in a raking light. Sample object-space position, seed per material, offset geometry through the field. - Flat roughness looks like plastic. Roughness must move with the grain: pores rougher (+0.19), latewood slightly rougher (+0.13), rays glossier (-0.075). A constant 0.3 gives a uniform bright sheen that never breaks along a ring.
- Colour only, no relief. Rings drawn only in albedo go flat when the light rakes. Feed the same
late,poresandfibresinto the height and bump it; and clamp the gradient or a hard ring edge turns the normal inside out. - Grain not following the form. Take
alongfrom the member's real axis, not from UV. UV on a chamfered box stretches the pores at the rounded edge and turns a board into a stripe test. With object-space sampling the grain runs straight through corners and end faces switch pores to cells automatically. - Detail shimmers or crawls at distance and on grazing faces. Every high-frequency layer must fade by its own screen footprint:
x *= 1 - smoothstep(a, b, fwidth-of-its-coordinate). Mip the field, and blendlateandearlytoward their averages whenfwidth(growth)passes0.16..0.72. Without this, rings moire into the wall of the board at 3 m. - Macro looks smeared, blobby, or a faint square lattice shows in the relief. The 1024² field is being magnified past about 2,500 to 4,000 px per unit at
grain 1.0: bilinear texel edges leak into the bump derivatives as a grid, pore cells go soft and ring edges dot at the boundary. RaiseuGrainScalefor a finer fibre size, or raise the bake to 2048 for hero surfaces; never rescale the mesh instead. - Colour-space slip. The field is data:
NoColorSpace, not sRGB. Tone-mapping is applied once at the end (the workshop does it in a hand-written final pass; the demo usesACESFilmicToneMapping). - The oil finish lit the raw finish. Materials that differ only by the
extrasnippet share one program cache key (onBeforeCompile.toString()), so the second material silently reuses the first program. Set a distinctcustomProgramCacheKeyper finish; the Urushi wrapper does. - Environment lights no roughness variation.
envMapIntensityis ignored when onlyscene.environmentis set (r163+); usescene.environmentIntensity. The wood needs a bright window card in the PMREM to show its roughness map; a grey dome hides it. - Cut faces read the same as the top. Multiply cut faces by
1 - endgrain*(0.045+pores*0.10)and raise their roughness+0.14: end grain drinks finish and stays matt, the fastest cue that this is a solid block. - Sharp boards float. A box with no arris and no contact shadow looks pasted. Rest each part exactly on its support (
y = h/2), bake the shadow map once (shadowMap.autoUpdate=false) and check the close-up for a gap.
Budgets
- Bake once, 1024² RGBA8 with mips (about 5.6 MB GPU), shared by every timber.
- Measured on this Apple GPU in headless Chrome, 13 draw calls and about 2,000 triangles (chamfered boxes, bench, wall) with MSAA on: 1.0 to 1.5 ms per frame at 1440 by 900, 3.4 to 4.5 ms at 2880 by 1800, against 0.65 ms and 4.2 ms for a plain tiled
MeshStandardMaterial. The procedural shader costs roughly 0.4 ms at 1x on this scene and vanishes into fill cost at 2x. Fill rate (DPR, MSAA) is the lever, not the noise. - Cap DPR at 2. Bake shadows once when the boards are static. Pause on
document.hiddenand reset the clock. Clampdtto 1/30 s. - Under
prefers-reduced-motionskip the slow orbit and snap camera moves; the still is the composed hero view. Controls stay live.
Self-score of this material (0 to 10, anchored)
Anchors: 2 tiled photo with flat roughness. 4 procedural stripes with albedo only. 6 rings plus relief plus varied roughness, holds at arm's length. 8 pores, rays and end grain hold at 5 cm, finish and wear are believable, no shimmer. 10 scanned-species photograph at every distance.
| dimension | score | why | | --- | --- | --- | | grain structure at arm's length | 7.5 | per-ring widths, cathedral arcs and knots; keyaki at default still reads a little ruled | | macro (3 to 5 cm) | 6.5 | pores, fibres and tool marks resolve; the 1024² field softens past 4,000 px per unit | | roughness and finish | 7.5 | oil, wax and urushi respond to rings and pores; no anisotropic highlight | | end grain and edges | 7 | open cells and matt cut faces; arris round, no true edge wear | | shimmer and grazing | 8 | footprint fades leave grazing and distance clean | | overall | 7.3 | |
Provenance
Extracted from the Kibori 木彫 workshop page, where one woodMat() timber shader dresses the walls, benches, tool handles, kumiko lattice and lacquered chests; the generators in demo.html are copied from that file unchanged. The wood was tuned for a close inspect camera, so every constant above is the workshop's own.
Related Skills
ai-job-search
45.4kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.8kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
LocalAI
49.4kLocalAI is the open-source AI engine. Run any model - LLMs, vision, voice, image, video - on any hardware. No GPU required.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
