openGL Shading Language
셰이더라고 부름
yarn add babel-plugin-glsl
const ExampleShaderMaterial = shaderMaterial(
// Uniform
{},
// Vertex Shader
glsl`
void main() {
}
`,
// Fragment Shader
glsl`
void main() {
}
`
);
extend({ ExampleShaderMaterial });
glsl은 유니폼, 정점 셰이더, 프래그먼트 셰이더로 나뉨
유니폼(uniform)
자바스크립트에서 셰이더로 데이터를 보내는 방법을 제공.
정점 셰이더(Vector Shader)
먼저 실행되는 셰이더.
속성을 수신하고 각 개별 정점의 위치 조작.
도형의 정점 배치하며 모양 생성.
프레그먼트 셰이더(Fragment Shader)
정점 셰이더 다음으로 동작.
개별 조각이나 픽셀 색상 설정.
const ExampleShaderMaterial = shaderMaterial(
{},
glsl`
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
glsl`
void main() {
gl_FragColor = vec4(0.0, 0.4, 1.0, 1.0);
}
`
);
extend({ ExampleShaderMaterial });
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
는 기본 값이다. 중간에 놓아준다.
gl_FragColor
는 rgb 컬러 순서이며 0과 1사이의 범위이다. 1을 넘어가면 1의 컬러로 표시된다. 1이라고 표시하면 오류가 생기며 1. , 0. 이나 1.0 0.0 으로 표기해주야 한다.
저 사각형을 나타내려면 아래 코드도 써야 한다.
ExampleShaderMaterial
는 Material 상단에 써주면 된다.
import * as THREE from "three";
import { Suspense } from "react";
import { Canvas, extend } from "@react-three/fiber";
import { shaderMaterial } from "@react-three/drei";
import glsl from "babel-plugin-glsl/macro";
// ExampleShaderMaterial 이 곳
const Material = () => {
return (
<mesh>
<planeBufferGeometry args={[3, 5]} />
<exampleShaderMaterial/>
</mesh>
);
};
const Example = () => {
return (
<Canvas camera={{ position: [0, 0, 5] }}>
<Suspense fallback={null}>
<Material />
</Suspense>
</Canvas>
);
};
export default Example;
args={[3,5]}는 넓이와 높이다.
planeBufferGeometry는 평면 기하학이라는 뜻으로 평면 형상을 생성하기 위한 클래스이다.
참고로 Material
안에 ExampleShaderMaterial
이 들어갈 때는 앞이 대문자가 아닌 소문자로 써야한다. 이 부분 오류로 인해 엄청난 시간을 허비했다.
const ExampleShaderMaterial = shaderMaterial(
{ uColor: new THREE.Color(0.0,0.0,0.0) },
glsl`
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
glsl`
uniform vec3 uColor;
void main() {
gl_FragColor = vec4(uColor, 1.0);
}
`
);
extend({ ExampleShaderMaterial });
const Material = () => {
return (
<mesh>
<planeBufferGeometry args={[3, 5]} />
<exampleShaderMaterial uColor="#2991bc" />
</mesh>
);
};
uColor
로 지정해주면 색상코드로 색을 변경할 수 있다. 마지막 1.0은 opacity다.
uv좌표는 정점 셰이더(Vector Shader)에서만 사용할 수 있다.
하지만 프레그먼트 셰이더(Fragment Shader) 사용하려면 정점셰이더에서 먼저 써줘야 한다.
const ExampleShaderMaterial = shaderMaterial(
{ uColor: new THREE.Color(0.0,0.0,0.0) },
glsl`
varying vec2 uUv;
void main() {
uUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
glsl`
uniform vec3 uColor;
varying vec2 uUv;
void main() {
gl_FragColor = vec4(uUv.x * uColor, 1.0);
}
`
);
extend({ ExampleShaderMaterial });
uUv.y
로 설정을 하면 세로로 그라디언트가 된다.
precision mediump float
정밀도 설정. 정밀도는 값을 저장하는데 얼마나 많은 비트를 사용할지를 의미한다.
움직이는 그라데이션
const ExampleShaderMaterial = shaderMaterial(
{ uColor: new THREE.Color(0.0,0.0,0.0),
uTime: 0, },
glsl`
varying vec2 uUv;
void main() {
uUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
glsl`
precision mediump float;
uniform vec3 uColor;
uniform float uTime;
varying vec2 uUv;
void main() {
gl_FragColor = vec4(sin(uUv.x + uTime) * uColor, 1.0);
}
`
);
extend({ ExampleShaderMaterial });
const Material = () => {
const ref = useRef();
useFrame(({clock})=> (ref.current.uTime = clock.getElapsedTime()));
return (
<mesh>
<planeBufferGeometry args={[3, 5]} />
<exampleShaderMaterial uColor="#2991bc" ref={ref}/>
</mesh>
);
};