본문으로 건너뛰기
cccskills
무료GitHub에 공개

3d-wood-lighting-scorecard

Refine wood materials and lighting in three.js interiors using procedural grain, window light, contact shadows, rays, and dust. A runnable scorecard measures eight aspects of the rendered image, helping guide revisions toward a chosen target score.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

원문원문 설명 보기

Light carved wood in a dark room in three.js, with procedural grain and pores, one warm key through a window, soft shadows that touch, light shafts, background rays and dust, then score the render out of 10 on an anchored rubric with a runnable headless scorecard and iterate until each item reaches the target. Use for oiled timber, kumiko, joinery and workshop scenes; wood that reads flat, plastic or washed out; volumetrics that lift the blacks; "score this out of 10"; or "get the lighting to 8".

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • Lighting carved wood, kumiko, and workshop scenes
  • Fixing wood that looks flat, plastic, or washed out
  • Adjusting light shafts while preserving dark tones
  • Scoring renders and iterating toward a target

포함된 파일(9)

  • SKILL.md11.1 KB
  • agents/openai.yaml378 B
  • demo.html64.1 KB
  • preview.jpg143.6 KB
  • PROMPT.md5.5 KB
  • references/last-scorecard.json11.4 KB
  • references/metrics.js16.2 KB
  • references/rubric.md7.6 KB
  • references/scorecard.mjs9.5 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

3D Wood Lighting Scorecard

Wood only looks like wood under one directional key raking across a dark room, so the grain, the shadow seam and the light shafts are lit by the same window, tone-mapped once at the end, and each is measured on the finished frame instead of judged by mood.

Verified stack: Three.js r169 (unpkg), WebGL2, GLSL patched into MeshPhysicalMaterial.onBeforeCompile, a half-float MSAA target and a hand-written ACES pass. The demo is demo.html; the numbers are references/.

Boundaries. This is the lighting-and-material layer for one lit interior. For sun shafts that must be cut by real trees and rooflines use 3d-sky-rays (screen-space occlusion); here the shafts are authored planes. For scanned or painted PBR maps, texel budgets and delivery use 3d-high-resolution-textures; here the wood is procedural from one shared 1024 noise field. For a bright rim on dark metal use 3d-specular-rim-glow; for glass use the studio-box ladder, not this. For the scoring habit alone use workflow-score-to-target; this skill supplies the wood rubric and the machine that measures it.

Extracted from Kibori (木彫), a scroll-driven WebGL woodworking page: its woodMat, buildEnvironment, key rig, shaft planes, dust and final pass are ported, with the window moved to where the shafts need it.

Build order

  1. Renderer: NoToneMapping, LinearSRGBColorSpace, HalfFloatType target with samples: 4, autoClear = false. Draw everything, additive shafts and dust included, into that target. Tone-map once in a last full-screen pass.
  2. One window. Put the emissive paper, the key light's direction, the shaft planes, and the window card in the PMREM environment on the same line. Nothing else.
  3. Key DirectionalLight 0xfff2df, intensity 2.0, 4096 shadow map (2048 under 820 px), normalBias 0.0045 (0.0085 at 2048), bias -0.00025, shadowMap.autoUpdate = false for a static room. Let a real wall with a real opening cast: the pool of light on the bench is then the window's shape.
  4. Fill 0xaec7df 0.60-0.76 from the camera side, rim 0xffdeb4 0.72 from behind, hemisphere 0xb5c5d7 / 0x35281c 0.19. These only keep the shaded flank alive; they are not the look.
  5. Wood: MeshPhysicalMaterial ior 1.43, specularIntensity 0.72, roughness clamp(base * W.rough, 0.35, 1), procedural albedo/roughness/bump from one periodic noise field baked once (1024x1024 RGBA8, 64 cells, three octaves, mipmapped, repeat).
  6. Shafts, then dust, then the last pass, then run references/scorecard.mjs.

Rules, each with the failure it prevents

Grain vanishes under flat light. A hemisphere or environment that is bright enough to see the room fills every pore and the board reads as painted. Keep the key at 2.0 and the ambient terms low; measured here, turning the studio reflections off raised the total score by 0.14 because they lifted the shadows. Per-material envMapIntensity 0.25 for the bench, 0.45 for the carved board, 0.40 default.

envMapIntensity does nothing and tuning "works" on paper. With three r163+ the material value is only read when material.envMap is set; scene.environment alone ignores it. Set mat.envMap = env on every wood material, and toggle a layer through the intensity, not by nulling the map (that recompiles).

The sheen mirrors a window that is not there. Kibori hung its environment window at front-left; a scene whose window is behind-left reflects a light that does not exist. Place the environment window pane group where the real window is (here (-2.3, 4.3, -3.2), scale 0.5, 12 panes 1.24x1.38 at radiance 3.8/3.55/3.05). Tilt the board so the mirror direction lands a little off the window (0.27 rad here; at exactly the mirror angle the whole board turns milky).

Volumetrics wash the blacks and the grain. Additive planes add light to everything behind them, including the top of the timber they cross. Fade each shaft by world height (smoothstep(0.02, 0.34, y)), keep the gain at 0.13 (Kibori 0.12) and the brightness above the reference strip under 35 levels, and read the black point: p1 must stay under 7. Before the height fade, gain 0.14 laid a milky haze across the plaque and the grain went with it.

A hard wedge where a shaft plane cuts a solid. The plane intersects the bench or the post and draws a bright line. Kibori kept planes behind the benches; the height fade above does it without moving them. Also clamp before pow: pow(1.0 - across, 2.2) with a hair-negative edge coordinate is NaN and NaN through additive blending is a black wedge.

God rays clip. If the renderer tone-maps, or the shaft pass is added after ACES, the beams either double-map or hit 1.0 flat. Sum them in linear HDR, then run ACES once (a=2.51 b=0.03 c=2.43 d=0.59 e=0.14). The window paper is toneMapped:false linear (1.15, 0.86, 0.52); at (3.9, 3.35, 2.55) it clipped to white paper.

Additive alpha. AdditiveBlending adds alpha too. On an opaque canvas it is invisible; if the scene is ever drawn into an alpha-composited layer, use CustomBlending with blendSrc One, blendDst One, blendSrcAlpha Zero, blendDstAlpha One.

Shadow acne on the bench, or a gap under the plaque. Acne comes from a small negative bias alone; use normalBias scaled to the map (0.0045 at 4096, 0.0085 at 2048). A gap between object and shadow (peter-panning) is normalBias too high. The scorecard reads it as contactGap. Add a baked contact pool under each object (radial alpha 0.78, r = 0.30..1.0 smoothstep, y 0.0012); the shadow map alone leaves the seam light.

A single-band texture shimmers at grazing angles. Fine bands (pores at 96/88 cycles per metre, fibres 230, rays 13/115) must fade with fwidth of their own coordinate, and the bump must give up before the colour does (1 - smoothstep(0.05, 0.18, vesselPx)), or dFdx(h) beats into moire. The scorecard's shimmer is a half-pixel view shift; 1.1 here, 3+ is aliasing.

A carved relief turns to noise. Grooves under 12 px per period alias in the bump and sparkle against a bright environment. The seigaiha carving here uses 0.15 m cells and two rings per circle (about 16 px at 1440 wide); at 0.062 m it was noise at 1x and fine at 2x. Size carving to the pixel budget, not the model.

Bricks in the grain. Medullary-ray flecks (rays) on a flat-sawn top face read as a tiled grid. Kibori's 0.8 default is for quartersawn faces; on the plaque it is 0, on others 0.15.

Banding in the dark wall. 8-bit steps in a vignetted gradient. A +-0.0015 hash dither ((hash - 0.5) * 0.003) after the sRGB encode removes it; the scorecard counts runs of 6+ identical pixels (flatRun 0.019).

The metric moves when the camera does. Freeze the sway and time (KiboriScore.freeze(true)), render and read the canvas in the same task (no preserveDrawingBuffer), capture at a fixed size and DPR, and use headless Chromium; the in-app pane backgrounds itself and shares the GPU.

Constants

ItemValue
Camera34 deg vertical, (0.60, 1.25, 2.55) looking at (0.05, 0.50, -0.30); wider FOV below aspect 1
Light direction(0.40, -0.75, 0.45) normalised, window centre (-0.60, 1.40, -1.0), opening 1.5 x 1.5
TargetHalfFloat, MSAA 4, DPR cap 2
Key / fill / rim / hemi2.0 / 0.60 / 0.72 / 0.19 (Kibori fill 0.76)
Shafts5 planes 0.44-0.52 wide, length 2.75, gain 0.13, foot fade 0.22 (Kibori 0.30), fbm 3 octaves
Wall rays10 planes, 0.20-0.90 wide, length 2.2, gain 0.08
Dust1900 points, size 17 / depth px clamped 3.4-46, 1 - smoothstep bokeh, gated to within ~0.33 m of a beam axis
Field1024^2 RGBA8, 64 periodic cells (n, f, second n), mipmapped; 16 px for the "low" toggle
Last passunsharp 0.10, vignette 0.42 + 0.58 v, ACES, sRGB, dither 0.003

Cost (measured, headless Chromium on Apple Silicon, Metal)

Full pipeline, one frame plus a 1 px readback: 7.4-7.9 ms at 1440x900 x1, 16.5 ms at 2880x1800 (DPR 2), 7.2 ms at 390x844 DPR 2. The shaft and wall-ray planes are the dearest layer (a 3-octave fbm per additive pixel: about 1 ms at x1, 5 ms at x2); the shadow map is free after the first frame because it is static; grain, env, key and dust are each about 0.2-0.7 ms. The cheap lever is the fbm octave count on the shafts (or drawing them at half resolution), not fewer planes. Do not conclude from one toggle: at 2x the noise between runs is about 1 ms.

Scoring loop

  1. Serve the page, npm i playwright-core, run node references/scorecard.mjs (--url, --size 1440x900, --dpr 1, --target 8, --no-ablate, --sync). It captures headless, freezes time, scores the eight items in references/rubric.md, ablates each layer and writes JSON; exit code 1 if any item is short.
  2. Score the baseline before changing anything (all layers off: 3.7 here) and keep the file. The ablation is the check on the metrics: a layer whose removal raises the total is either measured wrongly or not earning its cost.
  3. Fix the lowest item's cheapest sub-metric first, re-run at the same size and DPR, and keep only what the picture confirms. Look at a 2x crop after every metric-driven change; three of this demo's "improvements" raised a number and made the board look worse (full-board clearcoat, anisotropy 0.3, per-pixel tone gain 2.4) and were reverted.
  4. For a score that means "looks right", hand the captures and the rubric to a fresh judge that has not seen the numbers, and take the lower of the two.
  5. Report honestly. Demo, 1440x900 x1: 8.8 average; grain 8.1, key/fill 10, shadows 9.6, shafts 8.0, rays 8.8, tone 9.8, texture 9.7, specular 6.5 (short of 8: the sheen is broad, not a distinct highlight, and the fixes that added one damaged the grain). At DPR 2 the specular item is 7.4 and shafts 7.3 (dust specks finer than the measuring window).

Accessibility and lifecycle

  • prefers-reduced-motion: a designed still (time fixed at 5.2, no sway, no dust drift), rendered on demand; the layer switches and the score still work.
  • Pause on document.hidden and when the canvas leaves the viewport; dt clamped to 1/30 s, and the first frame after a pause has dt = 0.
  • Size from a ResizeObserver; DPR capped at 2; target and dust point size follow it.
  • Layer switches are real checkboxes with visible focus; the score is an aria-live region.
  • Below 820 px the panel moves under the canvas and a score chip sits on it.

Verify

  • The metrics block in demo.html equals references/metrics.js (node scorecard.mjs --sync).
  • 1440x900 and 390x844, console clean, reduced motion shows a composed frame, tab order reaches every switch.
  • A scorecard JSON with baseline, all-on, ablation and cost exists and matches the claims above.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Build woven fabric in Three.js with visible threads, realistic sheen, seams, and thick hems. The skill covers folds that preserve texture proportions, light passing through thin cloth, and variations in dye and wear.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Creating backlit curtains
  • Differentiating linen, silk, and wool
  • Adding hems and stitches for close-up views
MengTo/Skills7천2026년 10월 18일 업데이트

Build falling leaves in Three.js and similar 3D scenes, with visible front, edge, and back views as they tumble and drift. Coordinate wind, scene depth, camera-aware recycling, and performance checks for a convincing autumn effect.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Adding falling autumn leaves to a 3D scene
  • Coordinating leaf tumble, sideways drift, and wind
  • Managing leaves around buildings and camera movement
MengTo/Skills7천2026년 10월 18일 업데이트

Add coordinated seasonal transitions to an existing 3D scene. Blend foliage, lighting, sky, ground, snow, and particles from one shared state while preserving camera controls and interactions, so the same place remains recognizable throughout spring, summer, fall, and winter.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Add a four-season selector to an outdoor 3D scene
  • Show seasonal changes in an architectural walkthrough
  • Coordinate foliage, sunlight, sky, and ground appearance
MengTo/Skills7천2026년 10월 18일 업데이트

Create or integrate detailed 3D models with smooth outlines and believable edges for close-up views. Prepare lower-detail versions for distant viewing, prioritize loading, and measure rendering costs in the actual scene.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Creating a detailed 3D model for close-up views
  • Replacing visibly faceted curves with smoother geometry
  • Preparing detailed architectural assets for rendering
MengTo/Skills7천2026년 10월 18일 업데이트

Prepare detailed 3D materials that remain clear in close-up views. The skill guides texture resolution, physically based material maps, surface mapping, filtering, and progressive loading while checking download size and GPU memory use.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Prepare wood, stone, and fabric materials for close-up views
  • Fix texture seams, grain direction, and normal map orientation
  • Preserve floor and foliage detail at oblique or distant views
MengTo/Skills7천2026년 10월 18일 업데이트

Create realistic metal surfaces in Three.js by combining structured reflections, studio lighting, scratches, fingerprints, and beveled edges. Includes polished, brushed, and aged finishes for objects such as tools, rings, and metal product parts.

한국어 요약은 준비 중입니다. 영어 요약을 표시하고 있습니다.

  • Fixing metal that looks like gray plastic
  • Creating polished or brushed metal finishes
  • Adding patina and worn edges
MengTo/Skills7천2026년 10월 18일 업데이트

MengTo의 스킬 모두 보기

이 스킬의 문제 신고