Frontend Lab
← 回到所有效果
T063D006three

Shader Gradient

Shader 動態漸層

難度 ★★★★標籤 shader · glsl · gradient3 min read

效果簡述

第一個 fragment shader:在 plane 上跑自訂 GLSL,產生動態漸層。 比 CSS 漸層流暢、比 video 省頻寬。是入門 shader 的甜蜜起點。

預設|暖紅紫漸層

Claude Code Prompt

💬 Claude Code Prompt
參考:3D006 shader gradient
技術:shaderMaterial + uniforms uTime

具體行為:
- vertex 只算 uv pass 給 fragment
- fragment 用 sin/cos(uv + uTime) 混 3 色
- useFrame 更新 uniforms.uTime.value

限制:
- GLSL 是 ES1 語法,注意 vec3、mix 的型別
- uniforms 用 useMemo 包,不然每次 render new object
- 移動裝置 fragment 不要太重(avoid pow + log)

完整程式碼

ShaderGradient.tsx
'use client'

import { Canvas, useFrame } from '@react-three/fiber'
import { useMemo, useRef } from 'react'
import * as THREE from 'three'

const vert = `varying vec2 vUv; void main(){ vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0); }`
const frag = `uniform float uTime; varying vec2 vUv;
void main(){
  float t = uTime * 0.2;
  vec3 a = vec3(0.76,0.25,0.05);
  vec3 b = vec3(0.98,0.57,0.24);
  vec3 c = vec3(0.05,0.05,0.08);
  float mA = sin(vUv.x * 3.0 + t) * 0.5 + 0.5;
  float mB = cos(vUv.y * 3.0 + t * 1.3) * 0.5 + 0.5;
  vec3 col = mix(c, a, mA);
  col = mix(col, b, mB * 0.6);
  gl_FragColor = vec4(col, 1.0);
}`

function GradientPlane() {
const ref = useRef<THREE.ShaderMaterial>(null)
const uniforms = useMemo(() => ({ uTime: { value: 0 } }), [])
useFrame((s) => { if (ref.current) ref.current.uniforms.uTime.value = s.clock.getElapsedTime() })
return (
  <mesh>
    <planeGeometry args={[6,4]} />
    <shaderMaterial ref={ref} vertexShader={vert} fragmentShader={frag} uniforms={uniforms} />
  </mesh>
)
}

export function ShaderGradient() {
return (
  <Canvas camera={{ position: [0,0,3], fov: 55 }} dpr={[1,2]}>
    <GradientPlane />
  </Canvas>
)
}

何時用

  • ✅ Hero 背景(取代 CSS 漸層)
  • ✅ 品牌色運用展示
  • ✅ Loading 過場

何時別用

  • ❌ 內容區(背景動會分心)
  • ❌ 沒人想學 GLSL 但又趕時程
  • ❌ 簡單的兩色漸層(CSS 就夠)

我踩過的坑

  1. uniforms 沒 useMemo 每幀重建:值會被 reset 到 0。

  2. vec3 加減 float 要小心:GLSL 嚴格型別,vec3 * float 可以, vec3 + float 不行。

  3. gl_FragColor 是 ES1:新版有人寫 out vec4 fragColor (ES3), 別跟 ES1 混。

相關效果

搜尋

按 ⌘K 隨時開啟