「木漏れ日」を表現する
葉の間から落ちる光、揺れる影、舞う塵。木漏れ日の柔らかい時間を、CSS/SVGの軽量表現で再現するテクニック。
このページについて
表現の引き出し
🎨 揺れる光だまり
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
カフェ・オーガニックブランド・公園/植物園・ヨガ・写真館・絵本/教育系
🔧 実装手法
radial-gradient楕円 × screen合成 + 位置/明滅/形の3軸独立周期 + 擬似乱数ジッター
📄 コード例を見る
// 光斑9個。木漏れ日の光斑は「葉の隙間の形」ではなく
// 葉の隙間がピンホールになって投影した「太陽の像(丸い楕円)」。輪郭は必ずボケさせる
const patches = Array.from({ length: 9 }, (_, i) => {
const j1 = ((i * 7919) % 100) / 100;
const j2 = ((i * 104729) % 100) / 100;
const j3 = ((i * 1299709) % 100) / 100;
return {
left: 3 + ((i * 9973) % 85), // %
top: 6 + ((i * 6271) % 68), // %
w: 20 + j1 * 50, // 20〜70px
ratio: 0.7 + j2 * 0.6, // 縦横比 = 地面への投影角度の違い
peak: 0.38 + j3 * 0.3, // 明るさの基準値
dx: (j2 - 0.5) * 16, // 位置の揺れ ±8px
dy: (j3 - 0.5) * 16,
driftDur: 7 + j1 * 10, // 位置の揺れ 7〜17s(頭上の枝の大きな揺れ)
flickDur: 3.7 + j2 * 4.8, // 明滅 3.7〜8.5s(葉が光を遮ったり開けたり)
morphDur: 11 + j3 * 8, // 形の変化 11〜19s(隙間の形が変わる)
driftDelay: -(j2 * 15),
flickDelay: -(j3 * 8),
morphDelay: -(j1 * 12),
};
});
<div className="komorebi-stage">
{/* 午後の空気感(静止した薄い暖色オーバーレイ) */}
<div className="komorebi-air" />
{patches.map((p, i) => (
// 位置の揺れ/形の変化/明滅 の3軸を親子で分離し、独立周期で合成
<div key={i} className="patch-drift"
style={{
left: `${p.left}%`, top: `${p.top}%`,
width: p.w, height: p.w * p.ratio,
"--dx": `${p.dx}px`, "--dy": `${p.dy}px`,
animationDuration: `${p.driftDur}s`, animationDelay: `${p.driftDelay}s`,
}}>
<div className="patch-morph"
style={{ animationDuration: `${p.morphDur}s`, animationDelay: `${p.morphDelay}s` }}>
<div className="patch-glow"
style={{ "--peak": p.peak,
animationDuration: `${p.flickDur}s`, animationDelay: `${p.flickDelay}s` }} />
</div>
</div>
))}
</div>.komorebi-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 午後の森の地面。苔と土の緑褐色 */
background: linear-gradient(160deg, #4a5238 0%, #5c6344 40%, #6b7050 100%);
}
.komorebi-air {
position: absolute; inset: 0;
background: #d9c27a;
opacity: 0.08; /* 午後の空気(静止) */
}
/* 軸1: 位置の揺れ。±8pxを光斑ごとに違う方向・周期で */
.patch-drift {
position: absolute;
animation: patchDrift 10s ease-in-out infinite alternate;
}
@keyframes patchDrift {
from { transform: translate(calc(var(--dx) * -1), calc(var(--dy) * -1)); }
to { transform: translate(var(--dx), var(--dy)); }
}
/* 軸2: 形の変化。隙間の形が変わる気配 */
.patch-morph {
width: 100%; height: 100%;
animation: patchMorph 14s ease-in-out infinite alternate;
}
@keyframes patchMorph {
from { transform: scale(0.85, 1.12); }
to { transform: scale(1.15, 0.88); }
}
/* 軸3: 明滅(基準値±40%)。輪郭のないradial-gradient + screen合成で
光斑の重なりが加算的に明るくなる */
.patch-glow {
width: 100%; height: 100%;
border-radius: 50%;
background: radial-gradient(closest-side,
rgba(255,242,200,0.55), rgba(255,242,200,0.18) 55%, transparent 100%);
mix-blend-mode: screen;
animation: patchFlick 5s ease-in-out infinite;
}
@keyframes patchFlick {
0%, 100% { opacity: calc(var(--peak) * 0.6); }
50% { opacity: var(--peak); }
}
/* アクセント: 小さな隙間からの鋭い光。時々ふっと現れて消える */
.glint-dot {
position: absolute;
border-radius: 50%;
background: radial-gradient(closest-side, rgba(255,250,225,0.95), transparent);
mix-blend-mode: screen;
opacity: 0;
animation: glintPop 11s ease-in-out infinite;
}
@keyframes glintPop {
0%, 40%, 60%, 100% { opacity: 0; transform: scale(0.6); }
47%, 53% { opacity: 0.8; transform: scale(1); }
}🎨 逆光の葉(透過光)
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
植物EC・ハーブティーブランド・ボタニカル系サロン・環境系企業・初夏キャンペーン
🔧 実装手法
4層SVG構造の葉 + 透過光の色設計(透け強弱・multiplyによる重なりの暗化)+ 2段rotateのしなり
📄 コード例を見る
// 逆光に透ける葉。輪郭と葉脈が意味を持つので4層SVG構造で描き込む
function LeafShape({ len, tone }) {
const W = len * 0.3;
// 先の尖った楕円の葉形(base=原点、tip=上方向)
const d = `M0,0 C${-W},${-len * 0.3} ${-W * 0.92},${-len * 0.74} 0,${-len}
C${W * 0.92},${-len * 0.74} ${W},${-len * 0.3} 0,0 Z`;
return (
<>
{/* ① ベース形状。multiply合成で葉の重なりが暗くなる(透過光の物理) */}
<path d={d} fill={`url(#leaf-${tone})`} className="leaf-base" />
{/* ② 根元側の陰影(光は先端側から透ける想定) */}
<path d={rootHalfPath} fill="#3a5c2a" opacity={0.26} />
{/* ③ 中央〜先端の透過光ハイライト。逆光なので「明るい=薄い部分」 */}
<ellipse className="leaf-hi" cx={0} cy={-len * 0.62}
rx={W * 0.55} ry={len * 0.25} fill="url(#leaf-hi)" />
{/* ④ ディテール線: 主脈1本 + 側脈4対(濃い同系緑) */}
<path d={`M0,-3 L0,${-len + 4}`}
stroke="#3a5c2a" strokeWidth={0.9} opacity={0.6} fill="none" />
{[0.22, 0.4, 0.56, 0.72].map((t) => sideVeinPair(t, len, W))}
{/* 光源側の縁のリムライト */}
<path d={rightEdgePath} stroke="#fff8d0" strokeWidth={1} opacity={0.7} fill="none" />
</>
);
}
// 透けの強い葉(明るい黄緑)と弱い葉(深緑)を混ぜる
const leaves = [
{ x: 70, y: 186, angle: 14, len: 96, tone: "deep", swayDur: 8.5 },
{ x: 104, y: 192, angle: -8, len: 112, tone: "bright", swayDur: 6.1 },
{ x: 142, y: 194, angle: 5, len: 84, tone: "mid", swayDur: 7.3 },
// ...右側のクラスター3枚
];
<svg viewBox="0 0 400 180" preserveAspectRatio="none">
<defs>
{/* 逆光の透過色: 根元が濃く、先端へ透ける */}
<linearGradient id="leaf-bright" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stopColor="#6f9c3c" />
<stop offset="55%" stopColor="#9bc44a" />
<stop offset="100%" stopColor="#c8e06a" />
</linearGradient>
{/* leaf-mid / leaf-deep / leaf-hi(radial) も同様に定義 */}
</defs>
{leaves.map((lf, i) => (
<g key={i} transform={`translate(${lf.x},${lf.y}) rotate(${lf.angle})`}>
{/* 葉全体のrotate + 先端側の位相差rotateの2段で「しなり」 */}
<g className="leaf-sway" style={{ "--dur": `${lf.swayDur}s` }}>
<g className="leaf-bend">
<LeafShape len={lf.len} tone={lf.tone} />
</g>
</g>
</g>
))}
</svg>.backlit-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 光源=右上の白っぽい光から外側へ黄緑 */
background: radial-gradient(circle at 60% 20%, #f5edc8 0%, #d9e0a8 40%, #a8c47a 100%);
}
/* 光源の大きく柔らかいにじみ。ごくゆっくり明滅(17s) */
.backlit-bloom {
position: absolute;
top: -40px; right: -30px;
width: 200px; height: 170px;
background: radial-gradient(closest-side, rgba(255,255,255,0.55), transparent 70%);
animation: bloomPulse 17s ease-in-out infinite alternate;
}
@keyframes bloomPulse { from { opacity: 0.65; } to { opacity: 1; } }
/* 葉の重なりはmultiplyで暗くなる = 透過光ならではの重なり表現 */
.leaf-base { mix-blend-mode: multiply; }
/* 付け根支点の揺れ(±2deg)。葉ごとに周期を変える */
.leaf-sway {
transform-box: fill-box;
transform-origin: bottom center;
animation: leafSway var(--dur) ease-in-out infinite;
animation-delay: var(--delay);
}
@keyframes leafSway {
0%, 100% { transform: rotate(-2deg); }
50% { transform: rotate(2deg); }
}
/* 先端側の追加rotate。位相を-1.3sズラして「しなり」を出す */
.leaf-bend {
transform-box: fill-box;
transform-origin: center bottom;
animation: leafBend var(--dur) ease-in-out infinite;
animation-delay: calc(var(--delay) - 1.3s);
}
@keyframes leafBend {
0%, 100% { transform: rotate(-1deg); }
50% { transform: rotate(1deg); }
}
/* 透過光の明滅(±20%)。雲や上の枝が光を変化させる気配 */
.leaf-hi { animation: leafGlow var(--hdur) ease-in-out infinite alternate; }
@keyframes leafGlow { from { opacity: 0.72; } to { opacity: 1; } }🎨 林間の光と舞う塵
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
神社仏閣・ウェディング・写真スタジオ・高級旅館・自然保護系・朝活/モーニング系サービス
🔧 実装手法
斜めの光帯(screen+blur)+ 塵の「光帯内だけきらめく」明滅設計 + 幹シルエット + 朝靄
📄 コード例を見る
// 浮遊する塵12個。「光の帯の中にいる時だけ見える」のがリアルさの核
const dust = Array.from({ length: 12 }, (_, i) => {
const j1 = ((i * 7919) % 100) / 100;
const j2 = ((i * 104729) % 100) / 100;
const j3 = ((i * 1299709) % 100) / 100;
return {
left: 8 + ((i * 9973) % 80), // %
top: 10 + ((i * 6271) % 72), // %
size: 1.5 + j1 * 1.5, // 1.5〜3px
xDur: 7 + j2 * 16, // 漂い(横)7〜23s
yDur: 5 + j3 * 14, // 漂い(縦)5〜19s
xAmp: 6 + j1 * 12,
yAmp: 8 + j2 * 16,
twDur: 6 + j1 * 7, // きらめき 6〜13s
twDelay: -(j3 * 11),
};
});
// 斜めの光の帯(3本)。揺れ(rotate)と明滅(opacity)は別周期
const shafts = [
{ left: "30%", width: 84, tilt: 20, blur: 6, opacity: 0.34, swayDur: 17, flickDur: 19 },
{ left: "48%", width: 46, tilt: 21.5, blur: 4, opacity: 0.5, swayDur: 13, flickDur: 11 },
{ left: "64%", width: 60, tilt: 18.5, blur: 5, opacity: 0.42, swayDur: 23, flickDur: 13 },
];
<div className="forest-stage">
{/* 幹のシルエット(リムライト付き) */}
<svg className="forest-trunks" viewBox="0 0 400 180" preserveAspectRatio="none">
<path d="M22,0 Q30,40 24,90 Q20,140 28,180 L64,180 Q56,130 60,80 Q64,30 58,0 Z"
fill="#1f2a1c" />
<path d="M58,0 Q64,30 60,80 Q56,130 64,180"
stroke="rgba(233,219,160,0.16)" strokeWidth="2.5" fill="none" />
{/* ...右の幹・中央の細い幹 */}
</svg>
{shafts.map((s, i) => (
<div key={i} className="shaft-sway"
style={{ left: s.left, width: s.width, "--tilt": `${s.tilt}deg`,
animationDuration: `${s.swayDur}s` }}>
<div className="shaft"
style={{ "--so": s.opacity, filter: `blur(${s.blur}px)`,
animationDuration: `${s.flickDur}s` }} />
</div>
))}
{dust.map((d, i) => (
// 横の漂い × 縦の漂い × きらめき の3アニメを親子分離で合成
<div key={i} className="dust-x" style={{ left: `${d.left}%`, top: `${d.top}%`,
width: d.size, height: d.size, "--xamp": `${d.xAmp}px`,
animationDuration: `${d.xDur}s` }}>
<div className="dust-y" style={{ "--yamp": `${d.yAmp}px`,
animationDuration: `${d.yDur}s` }}>
<div className="dust-dot" style={{ animationDuration: `${d.twDur}s`,
animationDelay: `${d.twDelay}s` }} />
</div>
</div>
))}
<div className="morning-mist" />
</div>.forest-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 朝の林の深い緑。下端はわずかに明るく=地面の照り返し */
background: linear-gradient(170deg, #2e3a2a 0%, #3d4a34 50%, #5a6647 100%);
}
.forest-trunks { position: absolute; inset: 0; width: 100%; height: 100%; }
/* 光の帯。上端支点でゆっくり揺れる(±1.5deg) */
.shaft-sway {
position: absolute;
top: -50px;
height: 300px;
transform-origin: top center;
animation: shaftSway 17s ease-in-out infinite alternate;
}
@keyframes shaftSway {
from { transform: rotate(calc(var(--tilt) - 1.5deg)); }
to { transform: rotate(calc(var(--tilt) + 1.5deg)); }
}
/* 帯の中心が明るく縁へ溶ける + screen合成。明滅は±30% */
.shaft {
width: 100%; height: 100%;
background: linear-gradient(180deg,
rgba(255,248,224,0.55) 0%, rgba(255,248,224,0.18) 55%, transparent 90%);
mix-blend-mode: screen;
animation: shaftGlow 13s ease-in-out infinite alternate;
}
@keyframes shaftGlow {
from { opacity: calc(var(--so) * 0.7); }
to { opacity: var(--so); }
}
/* 塵の漂い: 横と縦を親子で分離(不規則な浮遊になる) */
.dust-x { position: absolute; animation: dustX 12s ease-in-out infinite alternate; }
@keyframes dustX {
from { transform: translateX(calc(var(--xamp) * -1)); }
to { transform: translateX(var(--xamp)); }
}
.dust-y { width: 100%; height: 100%; animation: dustY 9s ease-in-out infinite alternate; }
@keyframes dustY {
from { transform: translateY(calc(var(--yamp) * -1)); }
to { transform: translateY(var(--yamp)); }
}
/* リアルさの核: 塵は普段ほぼ見えず(opacity 0.05)、
光の帯を横切るタイミングだけ明るくきらめく(0.7 + scaleアップ) */
.dust-dot {
width: 100%; height: 100%;
border-radius: 50%;
background: #fff8e8;
animation: dustTwinkle 8s ease-in-out infinite;
}
@keyframes dustTwinkle {
0%, 34%, 66%, 100% { opacity: 0.05; transform: scale(1); }
47%, 53% { opacity: 0.7; transform: scale(1.4); }
}
/* 地面付近の朝靄。ゆっくり横流れ(29s) */
.morning-mist {
position: absolute;
bottom: 0; left: -30%;
width: 160%; height: 46px;
background: radial-gradient(ellipse 50% 100% at 50% 100%,
rgba(238,238,222,0.16), transparent 75%);
animation: mistDrift 29s ease-in-out infinite alternate;
}
@keyframes mistDrift {
from { transform: translateX(-12px); }
to { transform: translateX(24px); }
}🎨 壁に揺れる枝影
📝 表現の語彙
💬 AIへの指示テンプレ
🎯 似合うシーン
インテリア/家具EC・住宅/不動産・写真館・カフェ・ライフスタイルメディア・午後の時間帯訴求
🔧 実装手法
2層影(シャープ+ボケ)による半影 + 枝/葉の位相差揺れ + 環境色の影 + 光斑の焦点
📄 コード例を見る
// 枝影。本物の影は「1枚のくっきりした影」ではなく、
// シャープ層(blur 1px)+ ボケ層(blur 6px・少しずらす)の2層で半影(ペナンブラ)を作る
// 枝は制御点を数値で持ち、葉の付け根を曲線上に正確に置けるようにする
const SHADOW_BRANCH_PTS = [
[-12, 16, 48, 30, 108, 24, 176, 48], // 太い主枝(左上から)
[176, 48, 214, 62, 248, 60, 284, 78], // 先へ行くほど細く
[92, 22, 128, 8, 166, 8, 206, 0],
[222, 60, 248, 44, 278, 40, 306, 30],
];
const SHADOW_BRANCHES = SHADOW_BRANCH_PTS.map((p, i) => ({
d: `M${p[0]},${p[1]} C${p[2]},${p[3]} ${p[4]},${p[5]} ${p[6]},${p[7]}`,
w: [7, 4, 3, 2.2][i],
}));
// 3次ベジェ上の点と接線角度
function cubicAt(p, t) {
const mt = 1 - t;
const x = mt ** 3 * p[0] + 3 * mt ** 2 * t * p[2] + 3 * mt * t ** 2 * p[4] + t ** 3 * p[6];
const y = mt ** 3 * p[1] + 3 * mt ** 2 * t * p[3] + 3 * mt * t ** 2 * p[5] + t ** 3 * p[7];
const dx = 3 * mt ** 2 * (p[2] - p[0]) + 6 * mt * t * (p[4] - p[2]) + 3 * t ** 2 * (p[6] - p[4]);
const dy = 3 * mt ** 2 * (p[3] - p[1]) + 6 * mt * t * (p[5] - p[3]) + 3 * t ** 2 * (p[7] - p[5]);
return { x, y, deg: (Math.atan2(dy, dx) * 180) / Math.PI };
}
// 葉シルエット14枚。付け根(local原点)を必ず枝の曲線上に置き、
// 角度・サイズだけを擬似乱数でジッターする(葉が枝から浮かない)
const SHADOW_LEAF_SPOTS = [
{ b: 0, t: 0.78 }, { b: 0, t: 0.92 },
{ b: 1, t: 0.3 }, { b: 1, t: 0.55 }, { b: 1, t: 0.78 }, { b: 1, t: 1 },
{ b: 2, t: 0.45 }, { b: 2, t: 0.68 }, { b: 2, t: 0.88 }, { b: 2, t: 1 },
{ b: 3, t: 0.4 }, { b: 3, t: 0.66 }, { b: 3, t: 0.86 }, { b: 3, t: 1 },
];
const shadowLeaves = SHADOW_LEAF_SPOTS.map((s, i) => {
const j1 = ((i * 7919) % 100) / 100;
const j2 = ((i * 104729) % 100) / 100;
const { x, y, deg } = cubicAt(SHADOW_BRANCH_PTS[s.b], s.t);
const side = i % 2 ? 1 : -1;
// 枝先(t=1)の葉は枝の延長方向へ、途中の葉は左右交互に側方へ開く
const tipDeg = s.t === 1 ? deg + (j1 - 0.5) * 30 : deg + side * (50 + j2 * 45);
return {
x, y,
angle: tipDeg + 90, // 葉localは先端が上向き(-90°)なので+90
scale: 0.5 + j1 * 0.55,
};
});
// 影は黒ではなく「壁色の暗色」#8a7a62(影は環境色を含む)
function BranchShadow({ lag }) {
return (
<g className="shadow-branch" style={{ animationDelay: `${-lag}s` }}>
{SHADOW_BRANCHES.map((b, i) => (
<path key={i} d={b.d} stroke="#8a7a62" strokeWidth={b.w}
fill="none" strokeLinecap="round" />
))}
{/* 葉群は枝とは別グループ・位相差で揺らして「しなり」 */}
<g className="shadow-leaves" style={{ animationDelay: `${-1.3 - lag}s` }}>
{shadowLeaves.map((l, i) => (
<path key={i} d="M0,0 C-5,-8 -4,-17 0,-25 C4,-17 5,-8 0,0 Z" fill="#8a7a62"
transform={`translate(${l.x},${l.y}) rotate(${l.angle}) scale(${l.scale})`} />
))}
</g>
</g>
);
}
<div className="wall-stage">
<div className="wall-light" />
<div className="shadow-group">
{/* ボケ層: 同じ形を少しずらし、アニメは0.3s遅らせる → 空気の層を感じる */}
<svg className="shadow-layer shadow-soft" viewBox="0 0 400 180" preserveAspectRatio="none">
<BranchShadow lag={0.3} />
</svg>
<svg className="shadow-layer shadow-sharp" viewBox="0 0 400 180" preserveAspectRatio="none">
<BranchShadow lag={0} />
</svg>
</div>
{/* 影の中に1箇所だけ光斑(葉の隙間から漏れた光)= 画の焦点 */}
<div className="shadow-patch" />
</div>.wall-stage {
position: relative;
height: 180px;
border-radius: 8px;
overflow: hidden;
/* 午後の生成りの壁。下にいくほど暖色=西日 */
background: linear-gradient(165deg, #f7f0e3 0%, #efe4d0 60%, #e8dabf 100%);
}
/* 右上の窓からの光の気配 */
.wall-light {
position: absolute;
top: -50px; right: -40px;
width: 240px; height: 200px;
background: radial-gradient(closest-side, rgba(255,255,255,0.42), transparent 72%);
}
/* 影全体の明滅(±15%、23s)= 雲の通過 */
.shadow-group {
position: absolute; inset: 0;
animation: cloudPass 23s ease-in-out infinite alternate;
}
@keyframes cloudPass { from { opacity: 1; } to { opacity: 0.82; } }
.shadow-layer { position: absolute; inset: 0; width: 100%; height: 100%; }
/* 半影の2層: 光源に近い枝はシャープ、遠い葉はボケる */
.shadow-sharp { filter: blur(1px); opacity: 0.25; }
.shadow-soft { filter: blur(6px); opacity: 0.15; transform: translate(6px, 5px); }
/* 枝全体: 根元支点の±1.2deg(7s) */
.shadow-branch {
transform-box: fill-box;
transform-origin: left center;
animation: branchSway 7s ease-in-out infinite;
}
@keyframes branchSway {
0%, 100% { transform: rotate(-1.2deg); }
50% { transform: rotate(1.2deg); }
}
/* 葉群: 位相差の±0.8deg(5s、delay -1.3s)でしなり */
.shadow-leaves {
transform-box: fill-box;
transform-origin: center;
animation: leavesSway 5s ease-in-out infinite;
}
@keyframes leavesSway {
0%, 100% { transform: rotate(-0.8deg); }
50% { transform: rotate(0.8deg); }
}
/* 影の中の光斑(焦点)。ゆっくり明滅 */
.shadow-patch {
position: absolute;
left: 58%; top: 26%;
width: 46px; height: 32px;
border-radius: 50%;
background: radial-gradient(closest-side,
rgba(255,244,210,0.85), rgba(255,244,210,0.3) 60%, transparent);
animation: patchGlow 9s ease-in-out infinite alternate;
}
@keyframes patchGlow { from { opacity: 0.55; } to { opacity: 0.95; } }よくある質問
木漏れ日の光斑はなぜ丸いの?
葉の隙間がピンホールカメラの穴の役割をして、太陽の像(円形)を地面に投影しているため。隙間の形がどんなにギザギザでも、投影される光斑は丸みを帯びる。デモでも光斑は楕円で作るのが「本物らしさ」の鍵で、葉の形の光斑を作ると不自然になる。
木漏れ日表現と「癒し」表現の使い分けは?
木漏れ日は「自然・屋外・午後の時間」という具体的な情景を伴うモチーフ表現、癒しは情景を特定しない抽象的な印象表現。ブランドに自然や植物の文脈があるなら木漏れ日、文脈なしで穏やかさだけ欲しいなら癒しの表現(呼吸するグラデーション等)が向く。両方を組み合わせることも多い。
影の表現で黒を使わないのはなぜ?
現実の影は真っ黒ではなく、空や周囲からの環境光で照らされた「環境色を含む暗色」のため。白壁の影なら壁色の暗いトーン(ベージュ系の暗色)、緑の地面なら緑の暗色を使うと自然になる。黒い影は人工的・グラフィック的な印象になる。
AIに木漏れ日の演出を頼むコツは?
「木漏れ日風に」だけでは光の形や動きがバラつく。本ページの要素を分解して指示するのが確実: 「輪郭のボケた楕円の光斑をscreen合成で」「影はシャープ層とボケ層の2層で」「塵は光の帯の中だけきらめく」など。光学的な理屈(光斑は丸い・影は環境色)も添えるとAIの出力が安定する。