데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      WebGL과 함께 배우는 컴퓨터 그래픽스 (1)

      Tkay 24.06.26
      1,435 6 3
      DEVOTEE 요약
      WebGL은 브라우저에서 실시간 3D 그래픽스를 표현하는 유일한 크로스 플랫폼 솔루션으로 게임, AR, VR 등의 XR 어플리케이션 제작에 필수적입니다. 그러나 WebGL을 네이티브로 작성하는 것이 어렵기 때문에 three.js와 같은 라이브러리를 사용하는 것이 효율적이며, 이는 크로스 브라우저를 지원하는 오픈 소스 라이브러리로 성능과 편의성이 검증되었습니다. 기본적으로 three.js를 사용해 씬, 카메라, 렌더러를 설정하고 간단한 3D 오브젝트를 추가한 후, 이를 애니메이션화하는 과정을 설명합니다.

      당신이 WebGL을 공부해야 하는 이유

      우리가 왜 WebGL을 공부해야 할까요? learningwebgl이라는 페이지에서는 다음과 같이 설명하고 있습니다.

      Why learn WebGL? Very simply, it is the only cross platform solution for producing real-time, 3D computer graphics we have.

      WebGL은 브라우저 상에서 그래픽스를 표현하는 거의 유일한 방법입니다.

      때문에 게임을 넘어서, AR, VR과 같은 XR 어플리케이션을 만들거나, 3D 그래픽 에셋을 표현하려면 반드시 필요한 기술입니다.

      물론 Unity나 Unreal과 같은 게임 엔진이 WebGL로 변환해주기는 합니다만, 엄청난 용량을 감당해야 합니다.

      인터넷 웹 브라우저에서 30-40MB 파일을 다운로드 받는 것은 사용자에게 상당한 부담을 줍니다. 서비스 실패로 직결될 수 있을만큼요.


      three.js 소개

      WebGL를 native로 작성하는 것은 상당히 고됩니다.

      그래서 더 쉽게 사용할 수 있게 해주는 몇 가지 라이브러리가 있는데요. 저는 가장 대중적이고 성능이 검증된 three.js를 추천합니다.

      three.js는 크로스 브라우저를 지원하는 오픈 소스 라이브러리입니다. 가볍고, 편의성과 성능을 모두 잡았으며, 안정성도 확보했습니다.

      지금도 꾸준히 업데이트 되고 있습니다.

      다음의 페이지에서 자세한 정보를 보실수 있습니다. https://threejs.org/


      three.js의 튜토리얼 페이지를 중심으로 그래픽스 지식을 함께 설명하고자 합니다. 그래픽스를 전혀 모르시는 분들을 대상으로 작성 되었습니다.

      물론, Unity나 Unreal등의 게임 엔진이나 Maya, Max, Blender와 같은 그래픽스 툴을 잘 다루시는 분들은 더욱 쉽게 구현해 보실 수 있을거예요.


      Scene 만들기

      시작하기 전에, three.js 설치 방법(https://threejs.org/docs/#manual/en/introduction/Installation)에 대해 살펴보기 바랍니다.

      물론, 다른 라이브러리처럼 우리가 작성할 javascript 파일에 three.js를 import하는 것으로도 사용 가능합니다.

      그래픽스 기술에서 화면에 무언가를 그리려면 기본적으로 세 가지가 필요합니다.

      씬(장면; scene), 카메라(camera), 렌더러(renderer)입니다. three.js도 마찬가지죠.

      main.js에 작성을 시작해보겠습니다.

      import * as THREE from 'three';
      
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
      
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.body.appendChild( renderer.domElement );

      Scene은 우리가 화면을 통해 보게 될 3차원의 가상 공간을 의미합니다. 여기엔 다양한 오브젝트들과 그래픽스 요소들이 배치되어 있겠죠.


      Camera는 우리가 생각하는 일반적인 그 카메라입니다.

      가상 공간인 scene을 카메라를 통해 바라보게 되는 것이죠. 영화를 촬영 현장을 떠올려보세요.

      카메라가 세트장과 배우들을 찍고 있을텐데, 이 카메라와 동일한 개념입니다. 세트장과 배우는 scene이 되겠죠.


      그래픽스에서 카메라는 몇 가지가 있긴 하지만, Perspective와 Orthogonal 이렇게 두 개가 일반적으로 사용되고 있습니다.

      Perspective view는 3차원의 공간감과 원근감을 표현합니다. 가까울수록 크게 보이고 멀 수록 작게 보이죠.

      우리에게 가장 익숙한 방식입니다. Orthogonal view은 거리와 무관하게 물체의 크기가 일정하게 표현됩니다.

      이러한 view는 2차원 게임을 제작하는데 유용하게 쓰입니다.

      왼쪽이 perspective view, 오른쪽이 orthogonal view

      PerspectiveCamera 함수는 다음과 같이 정의되어 있습니다. 하나씩 살펴볼게요.

      PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

      Camera와 속성들 (출처: https://learnwebgl.brown37.net/08_projections/projections_perspective.html)

      fov는 field of view를 의미합니다. 게임을 좋아하시는 분들은 아실수도 있을텐데요. 시야 범위(각도)라고 생각하시면 됩니다.

      fov가 작을수록 좁은 시야를 가지게 되고 fov가 클수록 넓은 시야를 가지게 됩니다. 다음의 그림을 보시면 이해가 빠를거예요. fov를 너무 작거나 크게 설정하면 이질감을 가지게 됩니다.

      fov (출처: https://namu.wiki/w/%EC%8B%9C%EC%95%BC%EA%B0%81)

      aspect는 종횡비입니다. 화면 비율이라고도 하죠. 4:3, 16:9 등이 일반적으로 사용됩니다. 여러분의 모니터가 이런 비율일거예요.

      near와 far는 가까운 클리핑 면과 먼 클리핑 면을 말합니다. 카메라로부터 너무 가까운 영역과 너무 먼 영역은 화면에 나타나지 않습니다.

      너무 가까운 영역은 시야를 가리기 때문에 그리지 않는 것이고, 너무 먼 영역은 눈에 보이지도 않는데 연산만 차지하므로 삭제하는 것입니다.

      게임을 하다보면 느끼실 수 있는 부분이지요. 위 그림의 연두색 영역이 실제 화면에 그려지는 영역입니다. 두 클리핑 평면 사이에 있는 이 영역을 view frustum이라 부릅니다.


      Renderer(렌더러)는 렌더링을 해주는 모듈입니다. 렌더링은 무엇일까요? 그래픽스에서는 컴퓨터 알고리즘을 이용하여 2D/3D 모델을 이미지로 바꾸어주는 프로그램을 말합니다.

      최근에는 FE 쪽에서 컴포넌트를 변환하는 의미로 확장하여 사용하기도 하는데, 이와는 다른 개념입니다.

      렌더러 인스턴스를 할당해주고, 설정 몇 개를 더 해줍니다.

      setSize 속성을 살펴볼게요.

      .setSize ( width : Integer, height : Integer, updateStyle : Boolean ) 

      setSize는 렌더러가 화면을 채우는 크기를 설정합니다.

      웹 브라우저에서 사용할 것이기 때문에 무난하게 window.innerWidth, window.innerHeight로 설정해 주었네요. 각각 절반으로 줄이면 화면의 1/4을 차지하게 될 겁니다.

      만약 렌더되는 영역은 유지하면서 화면의 크기만 줄이고 싶다면, updateStyle을 false로 두면 됩니다. 렌더 영역까지 줄이고 싶다면 true로 설정하면 되겠죠.

      마지막으로, render 인스턴스를 HTML 문서에 추가합니다. HTML5의 canvas를 사용합니다.


      Scene에 인스턴스 추가

      여기까지 기본적인 설정을 마무리 했습니다. 이제 scene에 뭔가를 추가해서 우리가 볼 수 있도록 해보죠.

      const geometry = new THREE.BoxGeometry( 1, 1, 1 );
      const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
      const cube = new THREE.Mesh( geometry, material );
      scene.add( cube );
      
      camera.position.z = 5;

      그래픽스에서 geometry는 물체를 표현하는 외골격을 말합니다. 정확히는 객체의 외관을 형성하는 연결관 다각형 집합이라고 할 수 있죠.

      여기에서는 BoxGeometry라는 함수를 이용하여 3차원 box를 만들겠습니다. 인수 세 개는 각각 너비, 높이, 깊이를 의미합니다.

      자세한 것은 여기(https://threejs.org/docs/?q=BoxGeometry#api/en/geometries/BoxGeometry)에서 보실 수 있습니다.


      Material은 geometry 위에 입혀서 질감과 색상들을 표현하는 것을 말합니다. 흔히 말하는 텍스쳐와 라이팅 효과 등이 여기에 해당 되지요.

      여기에서는 MeshBasicMaterial을 할당하고 색상 값만 설정해주었습니다. 0x00ff00은 hex 코드로, RGB 중에서 G 값만 최대치로 설정했네요.

      이렇게 생성된 geometry와 meterial을 합쳐서 하나의 mesh로 생성합니다. 3차원 box가 초록색 재질을 가진 것이죠. cube라고 명명했습니다. 이 cube를 scene에 추가하겠습니다.

      방금 추가한 cube는 가상 공간 내에서 (0, 0, 0)에 위치하게 됩니다. 문제는 우리의 카메라도 동일한 위치에 있다는 것이예요.

      near plane에 잘릴 것 같습니다. 카메라 위치를 좀 조정하지요. camera.position.z 값을 5로 할당했습니다.


      Scene에 cube를 추가했지만 우린 여전히 아무것도 볼 수 없을겁니다. render를 하지 않았으니까요. 렌더 구문을 추가해 주겠습니다.

      function animate() {
      	requestAnimationFrame( animate );
      	renderer.render( scene, camera );
      }
      animate();

      animate 함수 안에 두 번째 라인은 렌더러에 render 함수를 호출하여 화면에 뭔가를 그리는 것이 명확합니다.

      그렇다면 첫번째는 requestAnimationFrame는 무엇일까요? 이것운 WebGL이 아니라 javascript 내장 함수입니다.

      백그라운드로 넘어가면 정지해서 성능을 최적화하고, 너무 자주 호출해서 불필요한 자원을 사용하지 않도록 해줍니다.

      자세한 설명은 여기(https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame)를 참고하세요.


      큐브 움직이기

      검은 화면에 초록색 큐브 하나만 덩그라니 있는 것보단 조금 움직이는게 좋겠습니다.

      게다가 움직이지 않으면 이게 2차원인지 3차원인지 알 수 없을거예요. 큐브가 움직이도록 animate 함수를 다음과 같이 고쳐보겠습니다.

      function animate() {
      	requestAnimationFrame( animate );
      	
      	cube.rotation.x += 0.01;
      	cube.rotation.y += 0.01;
      	
      	renderer.render( scene, camera );
      }
      animate();

      그런데 조금 이상한 부분이 눈에 띕니다. 큐브가 돌아가는 것 같은데 왜 이리 밋밋하지요? 그림자가 없기 때문입니다.

      그림자를 표현하려면 무엇이 또 필요할까요? 바로 빛입니다.

      빛과 그림자를 이용해 사실적인 표현을 하는 작업을 라이팅(lighting)이라고 하고, 이러한 작업을 GPU를 통해 빠르게 수행할 수 있게 해주는 모듈을 쉐이더(shader)라고 합니다.

      이것들은 다음 시간에 다루도록 하지요.


      라이브 샘플을 여기(https://jsfiddle.net/0c1oqf38/)에서 사용해 보실 수 있습니다.

      완성된 코드 및 튜토리얼 원본은 여기(https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene)를 참고하세요.


      감사합니다.

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      Tkay 님의 최신 블로그

      더보기