맞춤 필터 (CSS 셰이더라고도 함) 소개

이전에는 호출되던 맞춤 필터(CSS 셰이더)를 사용하여 DOM 콘텐츠와 함께 WebGL 셰이더의 기능을 사용할 수 있습니다. 현재 구현에서 사용된 셰이더는 WebGL의 셰이더와 거의 동일하므로 한 걸음 물러서 몇 가지 3D 용어와 그래픽 파이프라인을 이해해야 합니다.

최근 LondonJS에 전달한 프레젠테이션의 녹화된 버전을 첨부했습니다. 이 동영상에서는 이해해야 할 3D 용어, 접할 수 있는 다양한 변수 유형, 맞춤 필터 사용 방법을 단계별로 안내합니다. 또한 슬라이드를 가져와서 직접 데모를 실행해 볼 수도 있습니다.

셰이더 소개

이전에 셰이더의 정의와 WebGL 관점에서 셰이더를 사용하는 방법을 자세히 설명하는 셰이더 소개를 작성했습니다. 셰이더를 사용해 본 적이 없다면 더 진행하기 전에 읽어야 합니다. 많은 맞춤 필터 개념과 언어가 기존 WebGL 셰이더 용어에 달려 있기 때문입니다.

그럼 이제 맞춤 필터를 사용 설정하고 시작해 보겠습니다.

맞춤 필터 사용 설정

맞춤 필터는 Chrome, Canary뿐만 아니라 Android용 Chrome에서 사용할 수 있습니다. about:flags로 이동하여 'CSS 셰이더'를 검색하고 사용 설정한 후 브라우저를 다시 시작하면 됩니다. 이제 준비가 끝났습니다.

문법

맞춤 필터는 blur 또는 sepia와 같이 DOM 요소에 이미 적용할 수 있는 필터 세트를 확장합니다. Eric Bidelman이 이러한 개발자를 위한 유용한 모의 도구를 작성하셨으니 꼭 확인해 보세요.

DOM 요소에 맞춤 필터를 적용하려면 다음 구문을 사용합니다.

.customShader {
    -webkit-filter:

    custom(
        url(vertexshader.vert)
        mix(url(fragment.frag) normal source-atop),

    /* Row, columns - the vertices are made automatically */
    4 5,

    /* We set uniforms; we can't set attributes */
    time 0)
}

여기에서 꼭짓점 및 프래그먼트 셰이더, DOM 요소를 분류할 행과 열 수, 전달할 유니폼을 선언합니다.

여기서 마지막으로 주의할 점은 혼합 모드 (normal) 및 복합 모드 (source-atop)와 함께 프래그먼트 셰이더 주위에 mix() 함수를 사용하는 것입니다. 프래그먼트 셰이더 자체를 살펴보고 mix() 함수가 필요한 이유를 살펴보겠습니다.

픽셀 푸시

WebGL의 셰이더에 익숙하다면 맞춤 필터의 내용이 약간 다르다는 것을 알 수 있습니다. 예를 들어 프래그먼트 셰이더가 픽셀을 채우는 데 사용하는 텍스처를 만들지 않습니다. 오히려 필터가 적용된 DOM 콘텐츠는 텍스처에 자동으로 매핑됩니다. 이는 다음 두 가지를 의미합니다.

  1. 보안상의 이유로 DOM 텍스처의 개별 픽셀 색상 값을 쿼리할 수 없습니다.
  2. Google에서는 최종 픽셀 색상을 직접 설정하지 않습니다 (최소한 현재 구현에서는). 즉, gl_FragColor는 허용되지 않습니다. DOM 콘텐츠를 렌더링하려고 하며 css_ColorMatrixcss_MixColor를 통해 간접적으로 픽셀을 조작한다고 가정합니다.

즉, 프래그먼트 셰이더의 Hello World는 다음과 같습니다.

void main() {
    css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
                            0.0, 1.0, 0.0, 0.0,
                            0.0, 0.0, 1.0, 0.0,
                            0.0, 0.0, 0.0, 1.0);

    css_MixColor = vec4(0.0, 0.0, 0.0, 0.0);

    // umm, where did gl_FragColor go?
}

DOM 콘텐츠의 각 픽셀에 css_ColorMatrix를 곱합니다. 위의 경우에는 항등식 행렬로 아무것도 하지 않으며 RGBA 값을 변경하지 않습니다. 예를 들어 다음과 같이 css_ColorMatrix를 사용할 빨간색 값을 그대로 유지합니다.

// keep only red and alpha
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 1.0);

4D (RGBA) 픽셀 값에 행렬을 곱하면 다른 쪽에서 조작된 픽셀 값을 얻게 되며, 이 경우에는 녹색과 파란색 구성요소를 0으로 만드는 것을 볼 수 있습니다.

css_MixColor는 주로 DOM 콘텐츠와 혼합하려는 기본 색상으로 사용됩니다. 믹싱은 오버레이, 화면, 컬러 닷지, 하드 라이트 등 아트 패키지에서 익숙한 블렌딩 모드를 통해 실행됩니다.

이 두 변수가 픽셀을 조작할 수 있는 다양한 방법이 있습니다. 혼합 모드와 합성 모드가 상호작용하는 방식을 더 잘 이해하려면 필터 효과 사양을 확인해야 합니다.

꼭짓점 생성

WebGL에서는 메시의 3D 포인트를 만드는 모든 작업을 담당하지만, 맞춤 필터에서는 원하는 행과 열의 수를 지정하기만 하면 됩니다. 그러면 브라우저가 자동으로 DOM 콘텐츠를 여러 개의 삼각형으로 분해합니다.

꼭짓점 만들기
행과 열로 분할되는 이미지

그런 다음 각 꼭짓점은 조작을 위해 꼭짓점 셰이더로 전달됩니다. 즉, 필요에 따라 꼭짓점을 3D 공간에서 이동할 수 있습니다. 이제 곧 놀라운 효과를 낼 수 있습니다.

아코디언 효과
아코디언 효과로 인해 뒤틀린 이미지

셰이더로 애니메이션

셰이더에 애니메이션을 가져오면 셰이더가 재미있고 매력적입니다. 이렇게 하려면 CSS에서 전환 (또는 애니메이션)을 사용하여 동일한 값을 업데이트하기만 하면 됩니다.

.shader {
    /* transition on the filter property */
    -webkit-transition: -webkit-filter 2500ms ease-out;

    -webkit-filter: custom(
    url(vshader.vert)
    mix(url(fshader.frag) normal source-atop),
    1 1,
    time 0);
}

    .shader:hover {
    -webkit-filter: custom(
    url(vshader.vert)
    mix(url(fshader.frag) normal source-atop),
    1 1,
    time 1);
}

위 코드에서 주목할 점은 전환 중에 시간이 0에서 1로 완화된다는 것입니다. 셰이더 내에서 균일한 time를 선언하고 현재 값을 사용할 수 있습니다.

    uniform float time;

uniform mat4 u_projectionMatrix;
attribute vec4 a_position;

void main() {
    // copy a_position to position - attributes are read only!
    vec4 position = a_position;

    // use our time uniform from the CSS declaration
    position.x += time;

    gl_Position = u_projectionMatrix * position;
}

함께 즐겨보세요.

맞춤 필터는 매우 재미있게 사용할 수 있으며, 맞춤 필터가 없으면 만들 수 있는 멋진 효과를 내기가 어렵고 때로는 불가능할 수도 있습니다. 아직 초기 단계이고 상황이 꽤 많이 바뀌고 있지만, 이러한 요소를 추가하면 프로젝트에 약간의 쇼비즈가 추가될 것입니다. 그러니 한번 시도해 보시는 건 어떠세요?

추가 리소스