본문 바로가기

개발/js

three.js 스터디 2주차) Primitives

 primitives 란 실행 시 인자들을 받아 생성되는 3D Geometry이다.  1주 차 때의 BoxGeometry 도 Primitives이다. 공식문서의 튜토리얼에선 다양한 Primitives 들을 확인해 볼 수 있다. 2주 차는 Primitives, 조명(PointLight, AmbientLight)과 재질(MeshBasicMaterial, MeshPhongMaterial)을 연습해보도록 되어있다. 프로젝트로 제품 쇼케이스 같은 걸 구현하고 싶었는 데, 마침 주제가 비슷하게 구현하기 적절한 것 같아, 조촐한 Primitives 전시회(?)를 구성해 보았다.

계획

Primitives 중에 하트 모양(ExtrudeGeometry), 도넛 모양(TorusGeometry), 글자모양(TextGeometry)을 오브제로 전시하는 데,
오브제를 받치는 전시대(BoxGeometry)와 오브제를 각각을 내리쬐는 핀라이트들(PointLight), 그리고 벽과 바닥, 천장(PlaneGeometry)이 구현에 필요하다. 아무래도 핀라이트-오브제-전시대가 한쌍이라 3D Object 하위에 묶으면 좋을 것 같았 는데, 너무 고난과 역경이 길어서 일단 Scene 하위에 나란히 속하게 했다. 오브제가 돋보이도록 오브제는 PhongMaterial로, 나머지는 적절히 재질을 결정하기로 했다. 아래는 아주 러프한 스케치와 상상도이다. 저 스케치에 작성한 수치들은 거의 지켜지지 않았다 ㅎ. 자세한 건 나중에..

왼쪽은 러프한 스케치, 오른쪽은 지피티가 조언해준 전시회 이미지

 

구현

다음은 구현 화면이다.

조금,,,초라한,,,전시회

달라진 점

- 수치적인 부분 (예를 들어 오브제 30cm^3 -> 1m^3)
- TextGeometry는 최신 버전에서 기본적으로 제공하지 않아 원환체 매듭(TorusKnotGeometry)으로 변경.
- 광원의 영향을 받지 않으면 위화감이 커서 정면의 벽만 MeshBasicMaterial 재질로 구현
- 공간 전체를 밝히는 은은한 빛(Ambient Light)을 두고, 핀라이트는(PointLight)로 바로 아래 오브젝트만 비추도록 위치와 distance, intensity를 조정했다.

 

고난과 역경 + 재도전 다짐

- 벽과 천장 세우는 게 어려웠다....! 회전이 제대로 되지 않고 카메라 시야에서 벗어나거나 했다. PlaneGeometry로 구현해서 카메라와 정확히 수평하면 사라지는 것처럼 보이기도 했는데, 결국 끙끙거리다 포기했다. 인터넷에 찾아보니 Shape + Extrude Geometry로 슥슥 만드는 사람들도 있고, Double Side로 설정한 큰 큐브의 내부로 카메라 시점을 가져오기도 하던 데... 다음에 실내 환경 구현을 재도전하고 싶다.

- Shape + Extrude Geometry. 예제 코드의 하트가 찌그러져있기도 하고, 크기도 커서 값을 조정해 볼까 했는 데, 전혀 엄두가 안 났다. 이 방식으로 구현하는 사람들은 어떻게 하는 거지...? 방망이 깎는 노인인가...? 일단 하트가 전시회장에 나타난 것에 만족했는 데, 다음에 이 부분만 따로 좀 더 봐봐야겠다.

- mesh의 position 을 설정할 때 기준점이 mesh 의 x, y, z 중앙이었다..! ㅋㅋ,,, 막판에 axes helper를 켜고 나서 알게 되어서,,, 진열대와 바닥을 어림짐작과 눈대중으로 위치를 조정해 줬었다. 글을 쓰는 지금 당연히 위치 중심점을 조정할 수 있지 않을까 싶어서 gpt에게 물어보니 geometry.translate(x, y, z)로 객체의 정점의 기준점을 변경할 수 있다고 한다. 여러 mesh로 구성된 복잡한 객체의 경우 Group으로 객체를 감싸 position을 설정해 주면 된다고 하는데 이건 관련 자료를 아직 못 찾아서 다음 주차 스터디 (scene graph) 공부할 때 같이 확인해봐야 할 것 같다. 

- 이건 글을 쓰며 정리하다 발견한 건데, Ambient Light는 Scene 의 모든 부분을 골고루 비추기때문에, position 을 설정하는 게 의미가 없었으며, Point Light 는 모든 방향으로 빛을 비추기 때문에 타겟을 설정하는게 별의미가 없었다.  Spot Light 는 비추는 대상이나 방향을 설정할 수 있어 핀라이트에 더 적절해 보인다. 한편 오브제마다 핀라이트를 다는 게 아니라 led라인처럼 달고 싶으면 Directional Light를 위에 하나만 달면 된다.

 


 

재도전..! (11/05)

2024.11.2 스터디에서 고난과 역경 중 벽과 천장이 사라지는 원인을 알게 되었다. 평면인데 기본적으로 material의 양면을 모두 렌더링하지 않기 때문에, 회전하거나 움직여서 뒷면이 카메라에 보일때가 되면 마치 사라지는 것 처럼 보였던 것이다..! 내 한시간..! 그냥 내가 방향치인 줄 알았는데..! 생각해보니까 굳이 평면일 필요도 없기도 해서 양 옆 벽과 천장을 모두 BoxGeometry 로 만들어줬다

천장을 단 김에 빛도 조정해보기로 했다. 의미 없던 Ambient Light 의 위치 설정을 없애줬고(역시 아무 영향없었다.), Point Light 의 target 설정도 없애줬다(아무 영향 없었다).

위치를 설정하던 중 Point Light 이 마치 핀라이트처럼 비추는 게 아니라, 태양(좀 예시가 이상하긴하지만)처럼 빛 덩어리 형태란 걸 알게되었다. 어쩐지... 그래서 방향 설정이나 각도 설정 같은 것 없이 빛의 강도와 dim 설정 등 만 있었던 것이다.... ㅋㅋㅋㅋㅋㅋ 천장에 달면 오브제의 표면까지 빛이 도달하지 않았는 데, 빛의 강도를 높이면 눈 부시고, 전시회 천장이 낮으면 별로기 때문에, 마치 전시대 아래에서 빛이 올라오는 것처럼 위치를 잡아두었다.

마침 전시대가 조금 떠 있는 데, 의도한 것처럼 예쁘게 나오게 되었다 ㅎ. 생각보다 geometry의 위치와 크기, 회전 각도 등을 잡는 게 내게 너무 어려웠는 데, scene graph 에서 지역 공간을 다루게 되니 좀 이 부분을 중점적으로 연습해봐야겠다.

 

참고

 

three.js manual

 

threejs.org