Three.js faceVertexUvs를 이용한 텍스처 애니메이션

10828 단어 minecraftthree.jsWebGL
이 문서는 Three.js 텍스처의 부분 자르기 및 회전, 반전, 신축의 속편입니다. Three.js와 WebGL 텍스처의 구조는 이전에 자세하게 쓰고 있으므로 읽어보십시오.



마이크라의 애니메이션하는 블록의 텍스처 파일을 보면, 세로로 타일 형태로 늘어선 텍스처가 사용되고 있는 것을 알 수 있습니다.

이러한 이미지를 사용하여 애니메이션하는 경우 물리적으로 잘라 붙여 텍스처 이미지를 동적으로 다시 읽지 않고 CSS의 background-image offset처럼 보이는 부분만을 어긋나게 표시시킨다. 그리고 메모리 완화됩니다.

See the Pen Minecraft Smoker Animation by Urushibara ( ㅎㅎ )
on CodePen .


CodePen - Minecraft Smorker Animation



여기서 표시하고 있는 것은, 실제로 Minecraft에서 사용되고 있는 models/smoker.json (읽기용으로 Blockbench로 변환)을 사용해 생성한 3D 객체입니다.

3D 오브젝트는 독자 클래스화한 코드로 작성한 것이므로 생략합니다만, 기본적으로는 THREE.BoxGeometry등과 같은 구조라고 생각해 주세요.



faceVertexUvs의 Vector2 값만 이동합니다.



보고 싶은 것은이 애니메이션을 실현시키는 부분입니다.




발신자


    let animate = (mesh) => {
        vectorAdd(mesh.geometry.faceVertexUvs[0][10], 16, 48, 0, 16);
        vectorAdd(mesh.geometry.faceVertexUvs[0][11], 16, 48, 0, 16);
        mesh.geometry.uvsNeedUpdate = true;
    }




Vector2를 지정된 픽셀로 이동하는 함수

function vectorAdd(face, width, height, x, y)
{
    //Vector2をリアル座標系に変換してから座標を加算する関数
    let add = vector => {
        let xx = vector.x * width + x;
        let yy = (1 - vector.y) * height + y;

        return {x: xx, y: yy};
    }

    //すべての座標をリアル座標になおして加算
    let vexs = []; //Vector2の配列
    let maxX = 0, maxY = 0;
    face.forEach(vector => {
        let pos = add(vector)
        vexs.push(pos)
        //はみ出しチェック用
        maxX = Math.max(maxX, pos.x)
        maxY = Math.max(maxY, pos.y)
    });

    //最大幅よりもはみ出してたらマイナスする
    let minusX = maxX > width ? width: 0;
    let minusY = maxY > height ? height: 0;

    //座標系を変換して実際のfaceVertexUvsに代入
    for(let i=0; i < face.length; i++){
        face[i].x = (vexs[i].x - minusX) / width
        face[i].y = 1 - (vexs[i].y - minusY) / height
    }
}



조금 복잡해 보일지 모르지만 실제로 하는 일은 이런 느낌입니다.



  • 텍스처 좌표계에서 실제 좌표로 되돌립니다 (실제 텍스처의 Width/Height를 곱합니다).
  • 지정된 픽셀을 가산
  • 텍스처 좌표계로 돌아가기 (실제 텍스처의 Width/Height로 나눕니다)
  • faceVertexUvs에 대입


전회에 설명했습니다만, 텍스처 좌표계의 경우는 y축이 상하 반대가 되므로 주의.



크로스 페이드?





마이크라에서는 이것을 여러 레이어에서 사용하여 크로스 페이드까지 하고 있습니다.

Three.js는 아무것도 레이어 개념이 없다? (faceVertexUvs[Layers]는 존재하지만 머티리얼을 개별 지정할 수 없다) 때문에 어떻게 하고 있는지 조금 모릅니다. → 아래 참조

같은 형상의 Geometry를 겹쳐서, 2개의 지오메트리의 Opacity(투명도)를 애니메이션해 똑같이 할 수 있습니다.





+ merge



추가:

복수의 텍스처의 합성은 현재(rev120 시점)의 THREE.js가 제공하는 기능으로는 재현할 수 없는 것 같습니다.

이것을 실현하기 위해서는 Canvas 객체에 webgl로 2장의 이미지를 지정한 값으로 합성하는 fragment shader를 써, THREE.CanvasTexture로 텍스처에 할당하는 방법이 생각됩니다.

THREE.ShaderMaterial에서도 fragment shader를 취급할 수 있습니다만, 이쪽은 라이팅 처리도 자력으로 쓸 필요가 있기 때문에 텍스처의 합성을 실시만의 경우에는 적합하지 않을 것 같습니다.


좋은 웹페이지 즐겨찾기