티스토리 뷰

 

[ Post Process ]

복습

1. graphics pipeline에 대해 2가지 배웠다. Geometry Calcuation, Fragment fill이다.

2. reflow 비용은 크다. geometry가 변했으므로 모두 repaint 해야 하기 때문이다.

 

 Post Process는 graphics pipeline에 추가된 것으로 geometry 계산과 fragment가 끝났을 때 바로 그리지 않고 한 번 더 가공할 수 있는 기회를 주는 것이다.

 계산해서 바로 그래픽 비트맵에 쓰는 것이 아니라 이걸 메모리에 떠놓고서 메모리 안에서 조작한 이후에 그림을 그리도록 하는 것. 이러려면 버퍼가 있어야 한다.

 예전에는 그림을 그리면 CPU pipeline을 타고 바로 그려졌다. 지금은 그림을 GPU가 그린다. 모던 브라우저는 CPU를 이용해서 geometry를 계산하고 기본 fragment를 채운다. 그 이후에 가공한 버퍼를 GPU에 넘겨준 다음에 GPU에서 post process를 처리한다.

 우리가 사용하는 CSS의 여러 키워드 중의 일부는 CPU가 처리하고 또 일부는 GPU가 처리한다. 따라서 어떤 키워드를 사용하느냐에 따라서 post process로 넘기느냐 아니면 cpu에 부하를 가지느냐를 정할 수 있다.

 post process를 사용하고 있는 대표적인 속성으로 transform, animation 등이 있다.

 geometry를 그리고 fragment 영역을 칠하고 나면 GPU 입장에선 각각의 영역을 하나의 이미지로 보고 변형할 수 있다. CSS에서 3D와 관련된 모든 처리는 모두 GPU가 한다.

 

 

[ Transform 3D ]

perpective : 3D를 나타내는 CSS 속성 중 하나로 원근의 거리를 나타낸다. 어안 렌즈 효과로 인해 왜곡에 대한 정도를 나타내기도 한다.

 * 원근의 거리 : 모니터와 눈 사이의 거리

 * 어안 렌즈 효과 : 앞에 있는 건 엄청 크게 보이는데, 조금만 옆에 있어도 엄청 작아 보이는 효과

 

perspective-origin : 우리 눈이 보는 방향을 의미한다. 0 0 값을 주면 좌상단, 50% 50%를 주면 중앙, 100% 100%를 주면 우하단을 바라본다. 기본값은 중앙이다.

 

transform-style : 자식 요소를 3D 공간에 배치한다. 자식들이 부모의 3D 속성을 상속받는 특징이 있다.

 * DOM의 계층 구조는 fragment 단계까지만 영향을 준다. 3D 관련 속성은 post process 단계이기 때문에 영향을 받지 않는다. 이걸 해결하기 위한 속성이다.

 

transform-origin : 실제 변형이 일어날 때 위치. 값 각각이 x-offset, y-offset, z-offset을 의미한다.

 

backface-visibility : 3D 상에서 뒷면(가려진 면)이 보일지 말지 결정하는 속성. 기본값은 보이도록 되어 있다. 실제로 가려진 면을 볼 일이 없으므로 hidden으로 바꿔야 한다. 그러면 컴퓨터가 할 일이 반으로 줄어든다. 이러한 처리르 은면 처리(back face culling)이라 한다.

 ex) 은면의 예 - 축구공 안쪽 면 등

 

 * rotateX(0) 같은 속성을 일부러 넣어 GPU가 그리도록 강제할 수 있다.

 * image sprite 기법 : 레이아웃 구성에 필요한 다수의 이미지를 하나의 이미지로 합친 뒤 필요한 이미지만 좌표와 크기를 이용해 추출해내는 기법.

 * sprite : 다수의 이미지를 하나의 이미지로 합친 것. 3D에서는 아틀라스라고 부른다.

 * 3D에서 하나의 면을 surface가 아니라 face라 한다.

 * 3D에서 컴퓨터 그래픽 표면에 적용되는 비트맵 이미지를 텍스처라 한다.

 

예제 - 드럼 만들기

<style>
  @keyframes spin {
    to { transform: rotateY(360deg) rotateX(360deg) rotateZ(720deg) }
  }
  html, body { height: 100%;}
  body { perspective: 600px; background-color: #404040;}
  .ani { animation: spin 4s linear infinite; }
  .drum { background: url('http://keithclark.co.uk/labs/css-fps/drum2.png');}
</style>
<script> 
  const El = class {
    constructor() { this.el = document.createElement('div'); }
    set class(v) { this.el.className = v; }
  };

  const Face = class extends El {
    constructor(w, h, x, y, z, rx, ry, rz, tx, ty) {
      super();
      this.el.style.cssText = `
        position:absolute; 
        width:${w}px; 
        height:${h}px;
        margin:-${h/2}px 0 0 -${w/2}px;
        transform: translate3d(${x}px, ${y}px, ${z}px)
          rotateX(${rx}rad) rotateY(${ry}rad) rotateZ(${rz}rad);
        background-position: -${tx}px ${ty}px;
        backface-visibility: hidden;
      `;
    }
  };

  const Mesh = class extends El {
    constructor(l, t) {
      super();
      this.el.style.cssText = `
        position: absolute;
        left:${l};
        top:${t};
        transform-style:preserve-3d;
      `;
    }
    add(face) {
      this.el.appendChild(face.el);
      return face;
    }
  }

  const mesh = new Mesh('50%', '50%');

  const r = 100, height = 196, sides = 20;
  const sideAngle = (Math.PI / sides) * 2;
  const sideLen = r * Math.tan(Math.PI / sides);

  for (let c = 0; c < sides; c++) {
    const x = Math.sin(sideAngle * c) * r / 2;
    const z = Math.cos(sideAngle * c) * r / 2;
    const ry = Math.atan2(x, z);
    const face = new Face(sideLen + 1, height, x, 0, z, 0, ry, 0, sideLen * c, 0);
    face.class = 'drum';
    mesh.add(face);
  }

  const topFace = new Face(100, 100, 0, -98, 0, Math.PI/2,0,0,0,100);
  const bottomFace = new Face(100, 100, 0, 98, 0, -Math.PI/2,0,0,0,100);
  topFace.class = 'drum';
  bottomFace.class = 'drum';
  mesh.add(topFace);
  mesh.add(bottomFace);
  mesh.class = 'ani';
  document.body.appendChild(mesh.el);
</script>

 

 예제 - Skybox

<style>
  @keyframes spin {
    to {transform: rotateY(360deg)}
  }
  html, body { height: 100%; }
  body { perspective: 450px; background: #404040; overflow: hidden; }

  .env {
    animation: spin 20s linear infinite;
    position: absolute;
    left: 50%; top: 50%;
    transform-style: preserve-3d;
  }

  .env>div {
    background-image: url("pngwing.png");
    position: absolute; margin: -450px 0 0 -450px; width: 900px; height: 900px;
    backface-visibility: hidden;
  }
</style>
  
<body>
  <div class="env">
    <div class="top" style="transform:translate3d(0, -450px, 0) rotateX(-90deg); background-position: -900px 0;"></div>
    <div class="bottom" style="transform: translate3d(0, 450px, 0) rotateX(90deg); background-position: -900px -1800px;"></div>
    <div class="front" style="transform:translate3d(0, 0, -450px); background-position: -900px -900px;"></div>
    <div class="back" style="transform:translate3d(0, 0, 450px) rotateY(180deg); background-position: -2700px -900px;"></div>
    <div class="left" style="transform:translate3d(-450px, 0, 0) rotateY(90deg); background-position: 0 -900px;"></div>
    <div class="right" style="transform:translate3d(450px, 0, 0) rotateY(-90deg); background-position: -1800px -900px;"></div>
  </div>
</body>

 

  * Skybox : 3D에서 배경을 만들어주는 box를 의미. 큐브를 크게 만들어서 각 면을 회전시킨다는 개념으로 접근하면 된다.

 image link : https://www.pngwing.com/ko/free-png-dcabk/download

 

 

[ SASS ]

 * Modern CSS Work Process를 알아보는 것에 의미를 둬야 하는 부분. modern UI를 구현하는 데 있어서 한땀 한땀 CSS를 다 짜지 말고 수학으로 구하도록 노력한다.

 * 기존 라이브러리에 의존해서는 만들 수 없는 것을 만들 수 있다. 일반적인 툴에서 깨작깨작 만드는 것으론 한계가 있다.

 

 SASS도 새로운 언어로 보고 배워야한다. 이러한 pre-compiler를 사용하는 이유는 브라우저의 부하를 줄이고 런타임의 스크립트의 작동의 의존성을 낮추기 위해 사용한다.

 

특성

1. CSS의 문법을 최대한 살리면서 제어문, 함수가 들어있다. 함수는 function과 mixin이 있다.

2. SASS에서 function은 어떤 값이 return 되는 것을 의미한다.

3. 변수명 앞에 $를 붙인다.

4. 콜론(:)을 이용해 할당한다.

5. 숫자 리터럴은 숫자 그대로 쓴다. CSS와 똑같이 돌아간다.

 

6. 키워드를 사용할 땐 앞에 @를 붙인다.

7. 어떤 함수도 제공하지 않고 오직 문법만 지원한다. 따라서 필요한 함수는 외부 라이브러리를 받아야한다.

8. CSS 속성을 만들어내는 과정을 function이라고 부르지 않고 특별히 mixin이라고 부른다. mixin은 CSS style 세트 전체를 반환한다.

9. #{} 내에 변수를 넣으면 문자열을 넣은 것처럼 값이 들어온다.

10. 컴파일해서 CSS 파일을 만들어낸다.

 

 Function 예제

$pi: 3.14159265359;
@function atan2($y, $x) {
  @if $x > 0 { @return atan($y / $x); }
  @if $x < 0 {
    @if $y >= 0 { @return atan($y / $x) + $pi; }
    @if $y < 0 { @return atan($y / $x) - $pi; }
  }
  @if $x == 0 {
  	@if $y > 0 { @return $pi / 2; }
    @if $y < 0 { @return -$pi / 2; }
  }
  @return atan($y / $x);
}

 * atan 함수는 compass에서 import한 것

 

 Mixin 예제

const Face = class extends El {
  constructor(w, h, x, y, z, rx, ry, rz, tx, ty) {
    super();
    this.el.style.cssText = `
      position:absolute; 
      width:${w}px; 
      height:${h}px;
      margin:-${h/2}px 0 0 -${w/2}px;
      transform: translate3d(${x}px, ${y}px, ${z}px)
        rotateX(${rx}rad) rotateY(${ry}rad) rotateZ(${rz}rad);
      background-position: -${tx}px ${ty}px;
      backface-visibility: hidden;
     `;
  }
};
@mixin face($w, $h, $x, $y, $z, $rx, $ry, $rz, $tx, $ty) {
  position: absolute;
  width: #{$w}px;
  height: #{$h}px;
  margin-top: -#{$h/2}px;
  margin-left: -#{$w/2}px;
  transform: translate3d(#{$x}px, #{$y}px, #{$z}px)
    rotateX(#{$rx}rad) rotateY(#{$ry}rad) rotateZ(#{$rz}rad);
  background-position: #{$tx}px #{$ty}px;
}

 

for (let c = 0; c < sides; c++) {
  const x = Math.sin(sideAngle * c) * r / 2;
  const z = Math.cos(sideAngle * c) * r / 2;
  const ry = Math.atan2(x, z);
  const face = new Face(sideLen + 1, height, x, 0, z, 0, ry, 0, sideLen * c, 0);
  face.class = 'drum';
  mesh.add(face);
}
@for $i from 0 through $sides {
  $x:sin($sideAngle * $i) * $r / 2;
  $z:cos($sideAngle * $i) * $r / 2;
  $ry:atan2($x, $z);
  .mesh>div:nth-child(#{$i}) {
    @include face($w, $height, $x, 0, $z, 0, $ry, 0, -$sideLen * $i, 0);
  }
}

 

 * div만 충분히 많이 만들어두면 javascript로 만든 것과 차이가 없다. 남는 div는 스타일을 먹지 않아 없는 것처럼 무시된다.

 

 * 자바스크립트에 의존하지 않고 SASS 상에서 구현할 수 있는 디자인 그래픽 소스에 대해 알아보자.

 * 마인크래프트의 특정 맵에 등장하는 텍스처를 CSS로 만드는 parser도 있다. minecraft to CSS parser라고 검색하면 나온다고 한다.

 

'HTML & CSS' 카테고리의 다른 글

CodeSpitz - Display Model  (0) 2021.12.20
CodeSpitz - Semantic Web & CSS Query  (0) 2021.12.20
CodeSpitz - CSSOM & Vendor Prefix  (0) 2021.12.20
CodeSpitz - CSS Box Model  (0) 2021.12.20
CodeSpitz - Graphics System & Normal Flow  (0) 2021.11.09
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함