헤더 배경 수정 + three.js 를 두 곳으로
헤더에 배경이 왜 있냐는 지적에서 시작했다. site-header 자체는 배경이 없었고, 안쪽 유리가 불투명 판으로 폴백된 것이었다. prefers-reduced-transparency 가 참이면 (윈도우 투명 효과 끄기 등) --surface-raised 단색이 깔린다. 투명도를 줄여달라는 요청은 "불투명한 판을 깔아라"가 아니다. 배경에 가까운 톤으로 낮추고 형태는 테두리와 그림자가 유지한다. 떠 있는 헤더는 더 가깝게 맞췄다. three.js - 공용 부트스트랩을 src/lib/shader-plane.ts 로 추출했다. references/three.md 가 권하는 구조를 그대로 구현한 것이다. 지연 로드 · DPR 클램프 1.5 · 화면 밖이면 정지 · 실패 시 CSS 폴백 - 히어로: 광원 두 개가 흐르고 하나가 포인터를 느리게 따라온다 - 재료: 좌표를 노이즈로 밀어 유리 너머의 결을 만든다 - 두 셰이더가 같은 three 청크를 공유한다. 네트워크 요청 1건 --glow-2 를 토큰으로 승격해 셰이더의 하드코딩 색을 없앴다.
This commit is contained in:
parent
be343cdab5
commit
ed9463c3c2
5 changed files with 247 additions and 114 deletions
|
|
@ -16,6 +16,8 @@ const { c } = Astro.props;
|
|||
|
||||
<div class="full stage glass">
|
||||
<div class="stage-fallback" aria-hidden="true"></div>
|
||||
{/* GPU 가 만드는 재질. WebGL 이 없으면 위 그라디언트가 그대로 결과물이다 */}
|
||||
<canvas id="mat-canvas" class="stage-canvas" aria-hidden="true"></canvas>
|
||||
|
||||
<ul class="tiles">
|
||||
{
|
||||
|
|
@ -87,11 +89,12 @@ const { c } = Astro.props;
|
|||
max-width: 1180px;
|
||||
width: 100%;
|
||||
margin-inline: auto;
|
||||
padding: var(--space-6) var(--space-4);
|
||||
padding: var(--space-5) var(--space-4);
|
||||
border-radius: var(--radius-shell);
|
||||
overflow: hidden;
|
||||
}
|
||||
.stage-fallback {
|
||||
.stage-fallback,
|
||||
.stage-canvas {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
|
|
@ -106,6 +109,9 @@ const { c } = Astro.props;
|
|||
var(--surface-raised);
|
||||
}
|
||||
|
||||
.stage-canvas { opacity: 0; transition: opacity var(--dur-slow) var(--ease-soft); }
|
||||
.stage-canvas.is-live { opacity: 1; }
|
||||
|
||||
/* 3개 항목에 3개 셀. 빈 칸이 생기지 않고 균등 3열도 아니다 */
|
||||
.tiles {
|
||||
list-style: none;
|
||||
|
|
@ -122,8 +128,8 @@ const { c } = Astro.props;
|
|||
.tile:nth-child(2) { grid-area: top; }
|
||||
.tile:nth-child(3) { grid-area: bottom; }
|
||||
/* 큰 셀은 더 넓은 화면을 갖는다 */
|
||||
.tile:nth-child(1) .swatch { aspect-ratio: 5 / 4; }
|
||||
.tile:nth-child(n + 2) .swatch { aspect-ratio: 16 / 7; }
|
||||
.tile:nth-child(1) .swatch { aspect-ratio: 16 / 11; }
|
||||
.tile:nth-child(n + 2) .swatch { aspect-ratio: 16 / 6; }
|
||||
.tile { display: grid; gap: var(--space-2); align-content: start; }
|
||||
.tile .shell { box-shadow: var(--glass-hi), var(--shadow-2); }
|
||||
.tile .core { overflow: hidden; }
|
||||
|
|
@ -156,3 +162,47 @@ const { c } = Astro.props;
|
|||
.tile:nth-child(n + 2) .swatch { aspect-ratio: 5 / 4; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// 무대 배경. 유리 표면을 지나는 빛의 굴절을 흉내낸다.
|
||||
// 히어로와 같은 모듈, 같은 three 청크를 쓴다. 새로 받는 것은 없다.
|
||||
import { mountShaderPlane, GLSL_NOISE } from "../lib/shader-plane";
|
||||
|
||||
const canvas = document.getElementById("mat-canvas") as HTMLCanvasElement | null;
|
||||
if (canvas) {
|
||||
mountShaderPlane({
|
||||
canvas,
|
||||
speed: 0.7,
|
||||
colors: { uA: "--accent", uB: "--glow-2" },
|
||||
fragment: `
|
||||
precision mediump float;
|
||||
varying vec2 vUv;
|
||||
uniform float uTime;
|
||||
uniform float uAspect;
|
||||
uniform vec3 uA;
|
||||
uniform vec3 uB;
|
||||
${GLSL_NOISE}
|
||||
|
||||
void main() {
|
||||
vec2 p = vUv;
|
||||
p.x *= uAspect;
|
||||
float t = uTime * 0.06;
|
||||
|
||||
// 좌표 자체를 노이즈로 밀어 굴절처럼 보이게 한다
|
||||
vec2 warp = vec2(fbm(p * 2.2 + t), fbm(p * 2.2 - t + 4.7));
|
||||
vec2 q = p + (warp - 0.5) * 0.42;
|
||||
|
||||
// 밀린 좌표 위에 얇은 띠를 얹는다. 유리 너머의 결이다
|
||||
float band = sin((q.x + q.y) * 7.0 + uTime * 0.35) * 0.5 + 0.5;
|
||||
band = smoothstep(0.35, 0.95, band);
|
||||
|
||||
float depth = smoothstep(0.1, 1.0, fbm(q * 1.6 - t * 0.5));
|
||||
|
||||
vec3 col = mix(uB, uA, depth);
|
||||
float alpha = (0.16 + band * 0.22) * (0.55 + depth * 0.45);
|
||||
gl_FragColor = vec4(col, alpha);
|
||||
}
|
||||
`,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue