react three.js + glsl (shaer)

해적왕·2022년 8월 19일
0
post-custom-banner

glsl

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>
  );
};
profile
프론트엔드
post-custom-banner

0개의 댓글